I've done some more experimentation & testing.

At the moment, when syscolumns is updated, if a sub-transction is done, the 
update is done with an expicit no-wait on locks.
I've tried changing this so that it will use the same wait policy as the parent 
transaction - when this is done, I see none of the problems reported, and can 
have up to 100 concurrent threads inserting without any failing (whereas before 
this would instantly lock up).

So the question now is: "is the no-wait for the sub-transaction actually 
necessary?".

Personally, I can't see why it is, although I'm not exactly a guru at derby 
internals.  If the reason why is simply to increase concurrency, then I think 
it's flawed, as it forces more updates to be carried out by the parent 
transaction, which will hold the lock much longer before committing...

Any ideas?  Or is this the wrong list to be asking - should I pose this on 
derby-developers instead?

Many thanks,

        Andrew Lawrenson




-----Original Message-----
From: Andrew Lawrenson [mailto:[EMAIL PROTECTED]
Sent: 29 February 2008 14:56
To: Derby Discussion
Subject: RE: Derby, identity columns & locks on syscolumns

I think I've found my own answer:

When the updating of identity column is done, a sub-transaction is started for 
updating syscolumns.  This transaction normally (for me) lasts at most 1ms.  
However, sometimes under a heavy load, it's taken longer (I've seen about 1/3 
of a second).  Whilst the first transaction is locking syscolumns, any other 
insert causing an update of the identity column will fail immediately, as the 
lock timeout is immediate for the sub-transaction.

When the sub-transactions fail, the updating of syscolumns is done under the 
parent transaction - which may not be committed for several seconds (for me, 
under heavy load).  And during this time, of course, all other inserts will 
start failing under the sub-transactions, which then get re-executed on the 
main transaction, eaching holding a lock on the index for their entire 
transaction.

What I see is that when one update of syscolumns via the sub-transaction fails, 
the entire system locks up & most of the transactions inserting records fail 
(as you suddenly get this cascade of locks being held), although once clients 
start failing the system gradually recovers.

So... Is this something I just have to live with, or is it an issue?  Any 
potential workarounds that don't involve replacing identity columns with GUIDs 
or similar?

        thanks in advance,

        Andrew Lawrenson



-----Original Message-----
From: Andrew Lawrenson [mailto:[EMAIL PROTECTED]
Sent: 29 February 2008 10:48
To: [email protected]
Subject: Derby, identity columns & locks on syscolumns

Hi all,

    as I understand it, when you insert a row into a table with an identity 
column, it has to lock syscolumns to update the identity value - from the docs:

"Derby keeps track of the last increment value for a column in a cache. It also 
stores the value of what the next increment value will be for the column on 
disk in the AUTOINCREMENTVALUE column of the SYS.SYSCOLUMNS system table. 
Rolling back a transaction does not undo this value, and thus rolled-back 
transactions can leave "gaps" in the values automatically inserted into an 
identity column. Derby behaves this way to avoid locking a row in 
SYS.SYSCOLUMNS for the duration of a transaction and keeping concurrency high."

However, what I'm seeing looks like a row is being locked in sys.syscolumns for 
the duration of the transaction.

When performing lots of inserts in parallel, I'm getting lock timeouts on 
syscolumns for the inserts, e.g.:

transaction A performs an insert in table T1.
transaction B performs an insert in table T1.

1 minute later, transaction B fails, due to an exclusive lock held on 
syscolumns by transaction A.
(Transaction A is itself blocked by an insert on another table - the same 
issue, which is why it hasn't committed)

Now, to me, this looks like the locks on syscolumns _are_ being held for the 
duration of the transaction - is this correct, or is something else likely to 
be to blame?

This is using Derby 10.3.2.1 on Solaris 10 (x86).


Exerpts from the derby log file are as follows:


2008-02-29 09:36:53.652 GMT Thread[btpool0-77,5,main] (XID = 5599782), 
(SESSIONID = 176), (DATABASE = DRSPRI), (DRDAID = null), Executing prepared 
statement: insert into authorisation( authorisationtype, authorisedname, 
userid, teamid, urnRef, reqRef, spocRef, reasonid, loggeddate, notes, 
requestmethod, status, lastuser, authorityid, authoritygroupid )  values 
(?,?,?,?,?,?,?,?,CURRENT_TIMESTAMP,?,?,?,?,?,? ) :End prepared statement with 
14 parameters begin parameter #1: 1 :end parameter begin parameter #2:  :end 
parameter begin parameter #3: 611 :end parameter begin parameter #4: 101 :end 
parameter begin parameter #5: U15-1204277813126 :end parameter begin parameter 
#6:  :end parameter begin parameter #7:  :end parameter begin parameter #8: 
null :end parameter begin parameter #9:  :end parameter begin parameter #10:  
:end parameter begin parameter #11: OPEN :end parameter begin parameter #12: 
611 :end parameter begin parameter #13: 10000 :end parameter begin parameter 
#14: 1 :end parameter
2008-02-29 09:36:53.658 GMT Thread[btpool0-77,5,main] (XID = 5599782), 
(SESSIONID = 176), (DATABASE = DRSPRI), (DRDAID = null), Executing prepared 
statement: VALUES IDENTITY_VAL_LOCAL() :End prepared statement

2008-02-29 09:36:53.704 GMT Thread[btpool0-108,5,main] (XID = 5599789), 
(SESSIONID = 173), (DATABASE = DRSPRI), (DRDAID = null), Executing prepared 
statement: insert into authorisation( authorisationtype, authorisedname, 
userid, teamid, urnRef, reqRef, spocRef, reasonid, loggeddate, notes, 
requestmethod, status, lastuser, authorityid, authoritygroupid )  values 
(?,?,?,?,?,?,?,?,CURRENT_TIMESTAMP,?,?,?,?,?,? ) :End prepared statement with 
14 parameters begin parameter #1: 1 :end parameter begin parameter #2:  :end 
parameter begin parameter #3: 611 :end parameter begin parameter #4: 101 :end 
parameter begin parameter #5: U1-1204278042611 :end parameter begin parameter 
#6:  :end parameter begin parameter #7:  :end parameter begin parameter #8: 
null :end parameter begin parameter #9:  :end parameter begin parameter #10:  
:end parameter begin parameter #11: OPEN :end parameter begin parameter #12: 
611 :end parameter begin parameter #13: 10000 :end parameter begin parameter 
#14: 1 :end parameter

2008-02-29 09:37:53.819 GMT Thread[btpool0-108,5,main] (XID = 5599789), 
(SESSIONID = 173), (DATABASE = DRSPRI), (DRDAID = null), Failed Statement is: 
insert into authorisation( authorisationtype, authorisedname, userid, teamid, 
urnRef, reqRef, spocRef, reasonid, loggeddate, notes, requestmethod, status, 
lastuser, authorityid, authoritygroupid )  values 
(?,?,?,?,?,?,?,?,CURRENT_TIMESTAMP,?,?,?,?,?,? ) with 14 parameters begin 
parameter #1: 1 :end parameter begin parameter #2:  :end parameter begin 
parameter #3: 611 :end parameter begin parameter #4: 101 :end parameter begin 
parameter #5: U1-1204278042611 :end parameter begin parameter #6:  :end 
parameter begin parameter #7:  :end parameter begin parameter #8: null :end 
parameter begin parameter #9:  :end parameter begin parameter #10:  :end 
parameter begin parameter #11: OPEN :end parameter begin parameter #12: 611 
:end parameter begin parameter #13: 10000 :end parameter begin parameter #14: 1 
:end parameter

ERROR 40XL2: A lock could not be obtained within the time requested.  The 
lockTable dump is:
2008-02-29 09:37:53.737 GMT
XID       |TYPE         |MODE|LOCKCOUNT|LOCKNAME                                
                                        |STATE|TABLETYPE / LOCKOBJ              
     |INDEXNAME / CONTAINER_ID / (MODE for LATCH only)  |TABLENAME / CONGLOM_ID 
               |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
*** The following row is the victim ***
5599789   |ROW          |X   |0        |(17,16)                                 
                                        |WAIT |S                                
     |NULL                                              |SYSCOLUMNS             
               |
*** The above row is the victim ***
5599782   |ROW          |X   |2        |(17,16)                                 
                                        |GRANT|S                                
     |NULL                                              |SYSCOLUMNS             
               |



Many thanks,

    Andrew Lawrenson



Reply via email to