Home » Eclipse Projects » EclipseLink » SEQUENCE table / row lock issue
| | | |
Re: SEQUENCE table / row lock issue [message #753519 is a reply to message #748533] |
Thu, 27 October 2011 14:55 |
|
By default EclipseLink will allocate sequence ids in the current database transaction. If EclipseLink has not yet started a database transaction, then it will start a separate transaction for sequencing (and no locks will be held). EclipseLink does not start the database transaction when you start the JPA transaction, it deferrs it until it has to, so sequencing is normally non locking. If however you call flush() or triggered a flush() from a query, or executed SQL or update JPQL queries, then the database transaction will be started, and sequences acquired after this will hold locks.
You can avoid this be configuring a sequence connection pool, then EclipseLink will use a connection from this pool for sequencing, and never the active transaction.
You can configure a separate connection pool to be used by sequencing using the "eclipselink.connection-pool.sequence.nonJtaDataSource", etc. properties.
See,
http://www.eclipse.org/eclipselink/api/2.3/org/eclipse/persistence/config/PersistenceUnitProperties.html#CONNECTION_POOL_SEQUENCE
James : Wiki : Book : Blog : Twitter
|
|
|
Re: SEQUENCE table / row lock issue [message #753521 is a reply to message #748533] |
Thu, 27 October 2011 14:55 |
James Messages: 272 Registered: July 2009 |
Senior Member |
|
|
By default EclipseLink will allocate sequence ids in the current database transaction. If EclipseLink has not yet started a database transaction, then it will start a separate transaction for sequencing (and no locks will be held). EclipseLink does not start the database transaction when you start the JPA transaction, it deferrs it until it has to, so sequencing is normally non locking. If however you call flush() or triggered a flush() from a query, or executed SQL or update JPQL queries, then the database transaction will be started, and sequences acquired after this will hold locks.
You can avoid this be configuring a sequence connection pool, then EclipseLink will use a connection from this pool for sequencing, and never the active transaction.
You can configure a separate connection pool to be used by sequencing using the "eclipselink.connection-pool.sequence.nonJtaDataSource", etc. properties.
See,
http://www.eclipse.org/eclipselink/api/2.3/org/eclipse/persistence/config/PersistenceUnitProperties.html#CONNECTION_POOL_SEQUENCE
--
James : http://wiki.eclipse.org/EclipseLink : http://en.wikibooks.org/wiki/Java_Persistence : http://java-persistence-performance.blogspot.com/
|
|
| | | |
Re: SEQUENCE table / row lock issue [message #756370 is a reply to message #755241] |
Sat, 12 November 2011 13:26 |
Luca Graf Messages: 17 Registered: September 2011 |
Junior Member |
|
|
Hi James,
i use the eclipselink version bundled with glassfish-3.1.1 (2.3.0.v20110604-r9504).
I have done some futher debuging and it seem's that the SequenceManager uses the wrong allocation strategy (Preallocation_Transaction_NoAccessor_State) also if a sequence connection pool is configured in persistence.xml. The Preallocation_Transaction_NoAccessor_State strategy not use seperate connections for sequence allocation, also it use locks that seems to be the cause for the deadlock.
I have created an issue with a more detailed description and a proposed patch.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=363643
Greetings Luca
P.S. It seems that the old-style (deprecated as of EclipseLink 2.2) configuration 'eclipselink.jdbc.sequence-connection-pool.*' is not affected and can be used as workaround.
[Updated on: Sat, 12 November 2011 13:53] Report message to a moderator
|
|
|
Re: SEQUENCE table / row lock issue [message #1478467 is a reply to message #748493] |
Tue, 18 November 2014 18:10 |
Nuno Godinho de Matos Messages: 34 Registered: September 2012 |
Member |
|
|
Hi,
I must say I am experiencing exactly the same issue with eclipselink 2.3.2,
Of glassfish 3.2.5.
Essentially, when using eclipselink and setting into the persistence XML:
<property name="eclipselink.jdbc.sequence-connection-pool" value="true" />
The code runs perfectly. All entities share the same ID_GEN table.
I can set any given entity to have the tablegenerator annotation configured with a property such as allocationSize = 3, forcing eclipse link to be all the time looking my ID_GEN table all the time. I get no dead locks.
I can setup my derby to have very intense logging, and I can see that eclipse link is doing just what I want it to:
Tue Nov 18 18:44:03 CET 2014 Thread[p: thread-pool-1; w: 5,5,grizzly-kernel] (XID = 1677442), (SESSIONID = 139), (DATABASE = MYDB), (DRDAID = null), Executing prepared statement: UPDATE ID_GEN SET SEQ_VALUE = SEQ_VALUE + ? WHERE SEQ_NAME = ? :End prepared statement with 2 parameters begin parameter #1: 3 :end parameter begin parameter #2: MyEntityLog_Gen :end parameter
Tue Nov 18 18:44:03 CET 2014 Thread[p: thread-pool-1; w: 5,5,grizzly-kernel] (XID = 1677442), (SESSIONID = 139), (DATABASE = MYDB), (DRDAID = null), Executing prepared statement: SELECT SEQ_VALUE FROM ID_GEN WHERE SEQ_NAME = ? :End prepared statement with 1 parameters begin parameter #1: MyEntityLog_Gen :end parameter
Tue Nov 18 18:44:03 CET 2014 Thread[p: thread-pool-1; w: 5,5,grizzly-kernel] (XID = 1677442), (SESSIONID = 139), (DATABASE = MYDB), (DRDAID = null), Committing
It flows just perfectly.
I pump thousands of messages into a system test, and no dead lock whatsoeve.
The one problem with this deprecated setting, is that Oracle weblogic, unlike glassfish, just does not swallow it.
It will complain that a COMMIT cannot be issued under a container managed transaction.
Going back to glassfish, if I try to run the exact same system test, but I modify my persitence xml to have the following properties:
<jta-data-source>jdbc/DERBY_DS</jta-data-source>
<non-jta-data-source>jdbc/DERBY_SEQUENCING_NON_JTA</non-jta-data-source>
<property name="eclipselink.connection-pool.sequence.nonJtaDataSource" value="jdbc/DERBY_SEQUENCING_NON_JTA" />
or
<property name="eclipselink.jdbc.sequence-connection-pool.nonJtaDataSource" value="jdbc/DERBY_SEQUENCING_NON_JTA" />
or both of the above at the same time.
Then ... well, a disaster.
I can clearly see in my Derby Log that the transactions that are part of the main business logic have within them the calls to the UPDATE ID_GEN table.
And of course, it is a massacre of dead locks.
It looks like the nonJtaDataSource configuration property does nothing at all. The non JTA data source in glassfish corresponding to the JNDI name in the persistence.xml has the Non Transactional Connections: set to true.
In weblogic 12c, even with the bundled eclipse link, it is the same disaster.
Example of a derby dead lock when the NON JTA is in the persistence.xml (it is clear by the derby statement log that the UPDATE gens are part of the busines slogic transaction).
Such as:
ERROR 40XL1: A lock could not be obtained within the time requested. The lockTable dump is:
Tue Nov 18 18:26:32 CET 2014
XID |TYPE |MODE|LOCKCOUNT|LOCKNAME |STATE|TABLETYPE / LOCKOBJ |INDEXNAME / CONTAINER_ID / (MODE for LATCH only) |TABLENAME / CONGLOM_ID |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
*** The following row is the victim ***
1675613 |ROW |X |0 |(1,14) |WAIT |T |NULL |ID_GEN |
*** The above row is the victim ***
1675610 |ROW |X |3 |(1,14) |GRANT|T |NULL |ID_GEN |
1675610 |TABLE |IX |2 |Tablelock |GRANT|T |NULL |ID_GEN |
1675613 |TABLE |IX |2 |Tablelock |GRANT|T |NULL |ID_GEN |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.impl.services.locks.Timeout.createException(Unknown Source)
at org.apache.derby.impl.services.locks.Timeout.buildException(Unknown Source)
at org.apache.derby.impl.services.locks.ConcurrentLockSet.lockObject(Unknown Source)
at org.apache.derby.impl.services.locks.AbstractPool.lockObject(Unknown Source)
at org.apache.derby.impl.services.locks.ConcurrentPool.lockObject(Unknown Source)
at org.apache.derby.impl.store.raw.xact.RowLocking3.lockRecordForWrite(Unknown Source)
at org.apache.derby.impl.store.access.heap.HeapController.lockRow(Unknown Source)
at org.apache.derby.impl.store.access.heap.HeapController.lockRow(Unknown Source)
at org.apache.derby.impl.store.access.btree.index.B2IRowLocking3.lockRowOnPage(Unknown Source)
at org.apache.derby.impl.store.access.btree.index.B2IRowLocking3._lockScanRow(Unknown Source)
at org.apache.derby.impl.store.access.btree.index.B2IRowLockingRR.lockScanRow(Unknown Source)
at org.apache.derby.impl.store.access.btree.BTreeForwardScan.fetchRows(Unknown Source)
at org.apache.derby.impl.store.access.btree.BTreeScan.fetchNext(Unknown Source)
at org.apache.derby.impl.sql.execute.TableScanResultSet.loopControl(Unknown Source)
at org.apache.derby.impl.sql.execute.TableScanResultSet.getNextRowCore(Unknown Source)
at org.apache.derby.impl.sql.execute.IndexRowToBaseRowResultSet.getNextRowCore(Unknown Source)
at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(Unknown Source)
at org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(Unknown Source)
at org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(Unknown Source)
at org.apache.derby.impl.sql.execute.UpdateResultSet.getNextRowCore(Unknown Source)
at org.apache.derby.impl.sql.execute.UpdateResultSet.collectAffectedRows(Unknown Source)
at org.apache.derby.impl.sql.execute.UpdateResultSet.open(Unknown Source)
at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(Unknown Source)
at org.apache.derby.impl.sql.GenericPreparedStatement.execute(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeLargeUpdate(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeUpdate(Unknown Source)
at org.apache.derby.iapi.jdbc.BrokeredPreparedStatement.executeUpdate(Unknown Source)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:125)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:831)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:906)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:592)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1717)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:253)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:207)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:193)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:236)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:216)
at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:85)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:844)
at org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:2831)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1516)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1498)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1463)
at org.eclipse.persistence.sequencing.QuerySequence.update(QuerySequence.java:340)
at org.eclipse.persistence.sequencing.QuerySequence.updateAndSelectSequence(QuerySequence.java:277)
at org.eclipse.persistence.sequencing.StandardSequence.getGeneratedVector(StandardSequence.java:71)
at org.eclipse.persistence.sequencing.Sequence.getGeneratedVector(Sequence.java:257)
at org.eclipse.persistence.internal.sequencing.SequencingManager$Preallocation_Transaction_NoAccessor_State.getNextValue(SequencingManager.java:468)
at org.eclipse.persistence.internal.sequencing.SequencingManager.getNextValue(SequencingManager.java:1067)
at org.eclipse.persistence.internal.sequencing.ClientSessionSequencing.getNextValue(ClientSessionSequencing.java:70)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:349)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:308)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.assignSequenceNumber(UnitOfWorkImpl.java:465)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNotRegisteredNewObjectForPersist(UnitOfWorkImpl.java:4231)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.registerNotRegisteredNewObjectForPersist(RepeatableWriteUnitOfWork.java:513)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4176)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:440)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:269)
[Updated on: Tue, 18 November 2014 18:11] Report message to a moderator
|
|
|
Re: SEQUENCE table / row lock issue [message #1479351 is a reply to message #1478467] |
Wed, 19 November 2014 11:08 |
Nuno Godinho de Matos Messages: 34 Registered: September 2012 |
Member |
|
|
Some more information, when a i use the connection pool sequence=true, i see that eclipse link appears to return from the following method, the option:
return PREALLOCATION_TRANSACTION_ACCESSOR;
protected int getStateId(boolean shouldUsePreallocation, boolean shouldUseTransaction) {
if (!shouldUsePreallocation) {
// Non-Oracle native sequencing uses this state
return NOPREALLOCATION;
} else if (!shouldUseTransaction) {
// Oracle native sequencing uses this state
return PREALLOCATION_NOTRANSACTION;
} else if (getConnectionHandler() == null) {
// TableSequence and UnaryTableSequence in case there is no separate connection(s) available use this state
return PREALLOCATION_TRANSACTION_NOACCESSOR;
} else/*if(getConnectionHandler()!=null)*/
{
// TableSequence and UnaryTableSequence in case there is separate connection(s) available use this state
return PREALLOCATION_TRANSACTION_ACCESSOR;
}
}
On the other hand, if the the nonJTA preference is on he seems to return ;
return PREALLOCATION_TRANSACTION_NOACCESSOR;
I also see that when getNexValue() is being used from
/**
* Uses preallocation, uses transaction, no separate connection.
* This is used for a DatabaseSession, or a ServerSession not using native sequencing,
* and not using a sequence connection pool.
* This is used by default for table sequencing, unless a sequence connection pool is specified,
* however it should only be used if there is no non-JTA login available.
* This will use the writeConnection, but use individual transactions per sequence allocation,
* unless the unit of work is in an early transaction, or the connection is JTA (this may deadlock).
*/
class Preallocation_Transaction_NoAccessor_State extends State implements SequencingCallbackFactory {
The code actually tries open a new transaction and commit.
// commitTransaction may copy preallocated sequence numbers
// from localSequences to preallocationHandler: that happens
// if it isn't a nested transaction, and sequencingCallback.afterCommit
// method has been called.
// In this case:
// 1. localSequences corresponding to the accessor
// has been removed from accessorToPreallocated;
// 2. All its members are empty (therefore localSequenceForName is empty).
writeSession.commitTransaction();
However, up to the commit part, the SQL reaches the database.
On the commit part, no SQL actually reaches the databsae.
It is as if the container know that you are using a connection meant for JTA transaction, and your commit is just ignored until the moment the container decides the transactions should really be commited.
Looking pool, new ExternalConnectionPool() that seems to be created, i have no indication whatsoever that the string written in NON-JTA persistence.xml configuration is used anywhere to determine the data source that should be used.
It would appear that the default data source somehow is being used.
Thanks for any feedback.
|
|
|
Re: SEQUENCE table / row lock issue [message #1498080 is a reply to message #748493] |
Thu, 04 December 2014 06:54 |
Nuno Godinho de Matos Messages: 34 Registered: September 2012 |
Member |
|
|
Hi,
Just a brief update.
The one setting that was effective and managed to work both in weblogic as well as in glassfish was:
<property name="eclipselink.jdbc.sequence-connection-pool" value="true" />
<property name="eclipselink.jdbc.sequence-connection-pool.non-jta-data-source" value="jdbc/NON_JTA_DS" />
Where NON_JTA_DS is a non XA data source, in weblogic configured with the support global transaction set to NONE/disabled, and in glassfish with the "Non Transactional" checkbox enabled.
If I may add, the eclipse link documentation could well benefit from some clear examples of persistence-xml configurations coupled with some data source configuration in each application server.
As it stands, there is a bit of a gap in documentation, and in the source code - namely in the eclipse link persistence constant properties are bit confusing with all of the deprecated properties. These source files could well reference external documentation links with clear examples of how to use them.
Many thanks,
Kind regards.
[Updated on: Thu, 04 December 2014 06:56] Report message to a moderator
|
|
|
Goto Forum:
Current Time: Wed Jan 15 08:57:11 GMT 2025
Powered by FUDForum. Page generated in 0.05638 seconds
|