Campbell Ritchie wrote:I do not think Java Concurrency in Practice is a beginner’s book.Nor is Effective Java.
Armando Moncada wrote:Hi,
I was a COBOL programmer for many years. Now I want to learn JAVA. Which beginning books are good?
Armando
Martin Vajsar wrote:
If, on the other hand, you just wanted to overwrite the CLOB with completely new contents, you don't even need to select the old CLOB at all. You could simply create a brand new CLOB in your second method and use that in your UPDATE statement (and omit call to the first method completely).
Martin Vajsar wrote:
Updating a row causes that row to be locked. There is absolutely no uncertainty about this. The explicit (FOR UPDATE) row locking is only necessary if the LOB locator has been read using simple SELECT statement, that does not lock the row unless the FOR UPDATE clause is used. If FOR UPDATE would not be used, several sessions (users) might read the same LOB locator and might try to modify it concurrently.
I think it is OK. I did actually concentrate only on the first method, as it was part of the discussion.
You're in effect updating the lob locator in the row, and the new locator will not be visible outside your transaction until you commit. Moreover, and more importantly, the update does lock the row in the same way a select for update would. So the reason this method does not require an explicit lock is that it is locked implicitly anyway. I'm really sorry for the confusion I've caused.
The way I suggested (update tbl set lob=empty_clob() where ... returning lob into ?) comes somewhere from Oracle's documentation, and maybe (just maybe) it would perform even better. I think that your second method creates a temporary LOB which is then copied to the table's LOB segment when you execute the statement. The method I hinted creates the LOB directly in the table's LOB segment and writes data to it, so no more copying is involved. If your LOB is large, the copying might take some time. I've elaborated on this here. It is well possible that that code could be changed not to require casting to Oracle's classes, but it ties to Oracle anyway by means of the SQL used, so I didn't care.
Martin Vajsar wrote:
Rob Spoor wrote:
Sudheer Bhat wrote:In case 1, you acquire the lock on the row you are updating so that no one else can acquire the lock. So all other interested transactions who may try to update this row has to wait. So the advantage with approach 1, is that you dont have an issue of "lost updates".
If you use explicit transactions, by calling setAutoCommit(false) on the Connection before updating, then commit() after the update, you also get atomic behaviour.
The setAutoCommit(false) is necessary, but might not be sufficient. A little known fact is that when updating LOBs in Oracle, the containing row must be locked to prevent concurrent modifications (at least the 10g documentation states this, 11g seems to be a little bit different; I didn't dig deep in it though). Googling oracle lob update lock row yields some interesting read.
I think creating and inserting new LOB (in the spirit of update tbl set lob=empty_clob() where ... returning lob into ?) instead of overwriting the existing one would not need the row lock, since the newly created lob locator should not be visible outside current transaction. I'm not sure about it, though.