db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mamta Satoor <msat...@gmail.com>
Subject Working on adding a test case which will reliably run into sequence contention problem
Date Fri, 30 Sep 2011 18:55:59 GMT
Hi,

I think it will be good for us to have a junit test which will
reliably run into sequence contention problem. As a start, I am
working on writing a stand alone program outside of junit which looks
as follows. I have not been able to reproduce the sequence contention
problem with my program yet (instead runs into quite a few "ERROR
40XL1: A lock could not be obtained within the time requested" which
is shown in the stack trace below). Will appreciate if someone can
look at the program and have any insight on how it can be tweaked to
run into sequence contention problem.

The program is real simple,
1)it first creates a table with two columns one of which is an identitiy column
2)it then spawns a number of threads.
3)each one of these threads gets their own connection(with autocommit
off) to the db, prepares an insert statement and performs a number of
inserts using the prepared statement with commit after every 1000
rows.

The program accepts two parameters, number of threads it should spawn
and number of inserts each one of those threads will issue. On the
command line, I have tried setting waitTimeout to 3 and sequence
preallocator to 1 to see if that will help reproduce the problem but
that hasn't helped. Following is how I invoke the program on the
command line
$ java -Dderby.locks.waitTimeout=3
-Dderby.language.sequence.preallocator=1 DERBY4437Sequence 10
100000000 > dellater.txt
The lock timeout trace looks as follows(This stack trace is from
trunk.I have seen similar behavior with 10.8.2.1 RC)
ERROR 40XL1: A lock could not be obtained within the time requested
	at java.lang.Throwable.<init>(Throwable.java:67)
	at org.apache.derby.iapi.error.StandardException.<init>(StandardException.java:80)
	at org.apache.derby.iapi.error.StandardException.<init>(StandardException.java:69)
	at org.apache.derby.iapi.error.StandardException.newException(StandardException.java)
	at org.apache.derby.impl.services.locks.ConcurrentLockSet.lockObject(ConcurrentLockSet.java:618)
	at org.apache.derby.impl.services.locks.AbstractPool.lockObject(AbstractPool.java:119)
	at org.apache.derby.impl.services.locks.ConcurrentPool.lockObject(ConcurrentPool.java:28)
	at org.apache.derby.impl.store.raw.xact.RowLocking3.lockRecordForWrite(RowLocking3.java:248)
	at org.apache.derby.impl.store.access.conglomerate.OpenConglomerate.lockPositionForWrite(OpenConglomerate.java:587)
	at org.apache.derby.impl.store.access.conglomerate.GenericConglomerateController.fetch(GenericConglomerateController.java:382)
	at org.apache.derby.impl.sql.catalog.DataDictionaryImpl.updateCurrentSeqValue(DataDictionaryImpl.java:10279)
	at org.apache.derby.impl.sql.catalog.DataDictionaryImpl.updateCurrentIdentityValue(DataDictionaryImpl.java:10139)
	at org.apache.derby.impl.sql.catalog.SequenceUpdater$SyscolumnsUpdater.updateCurrentValueOnDisk(SequenceUpdater.java:596)
	at org.apache.derby.impl.sql.catalog.SequenceUpdater.updateCurrentValueOnDisk(SequenceUpdater.java:477)
	at org.apache.derby.impl.sql.catalog.SequenceUpdater.getCurrentValueAndAdvance(SequenceUpdater.java:353)
	at org.apache.derby.impl.sql.catalog.DataDictionaryImpl.getCurrentValueAndAdvance(DataDictionaryImpl.java:10337)
	at org.apache.derby.impl.sql.execute.InsertResultSet.getSetAutoincrementValue(InsertResultSet.java:827)
	at org.apache.derby.impl.sql.execute.BaseActivation.getSetAutoincrementValue(BaseActivation.java:666)
	at org.apache.derby.exe.ac846c00a0x0132xbb55xece3x00000028ca080.e0(Unknown
Source)
	at org.apache.derby.impl.services.reflect.DirectCall.invoke(ReflectGeneratedClass.java:139)
	at org.apache.derby.impl.sql.execute.RowResultSet.getNextRowCore(RowResultSet.java:148)
	at org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:185)
	at org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)
	at org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:518)
	at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java:436)
	at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:317)
	at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1242)
	at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(EmbedPreparedStatement.java:1686)
	at org.apache.derby.impl.jdbc.EmbedPreparedStatement.execute(EmbedPreparedStatement.java:1341)
	at DERBY4437Sequence.run(DERBY4437Sequence.java:61)

The test looks as follows
import java.sql.*;

public class DERBY4437Sequence extends Thread {
    public static void main(String[] args) throws Exception {

    	int numberOfThreads = 1000;
    	int numberOfInserts = 100;
		
		if (args.length == 1) {
			numberOfThreads = Integer.parseInt(args[0]);
	    }
		if (args.length == 2) {
			numberOfThreads = Integer.parseInt(args[0]);
			numberOfInserts = Integer.parseInt(args[1]);
	    }
		DERBY4437Sequence initThreads[] =
			new DERBY4437Sequence[numberOfThreads];
		
		Connection conn = null;
        Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
        conn =  DriverManager.getConnection(
                "jdbc:derby:DERBY4437DB;create=true");
        conn.setAutoCommit(false);
        Statement st  = conn.createStatement();
        st.executeUpdate("create table sequenceTable(c11 int "+
        		"generated by default as identity, c12 int)");
        conn.commit();
        conn.close();

        System.out.println("Get threads going");
		for (int i = 0; i < numberOfThreads; i++) {
			initThreads[i] = new DERBY4437Sequence(i,
					numberOfInserts);
			initThreads[i].start();
			sleep(1);
		}
        System.out.println("Done with threads");
    }

    private int threadNumber;
    private int numberOfInserts;
    private PreparedStatement ps;
    private Connection conn;

    DERBY4437Sequence(int threadNumber,
    		int numberOfInserts) throws Exception {
		this.threadNumber = threadNumber;
		this.numberOfInserts = numberOfInserts;
        conn =  DriverManager.getConnection(
        		"jdbc:derby:DERBY4437DB");
        conn.setAutoCommit(false);
        ps = conn.prepareStatement("insert into "+
        		"sequenceTable(c12) values(1)");
		System.out.println("Created ps for thread numer" + threadNumber);
    }

	public void run() {
		System.out.println(threadNumber + " is now running");
    	try {
    		for (int i = 0; i < numberOfInserts; i++) {
    			ps.execute();
    			if (i%1000 == 0) {
    				System.out.println("commit after every 1000 rows " + i
    						+ " by thread " + threadNumber);
    				conn.commit();
    			}
    		}
    	} catch (Exception ex)  {
    		System.out.println("error in thread " + threadNumber);
    		ex.printStackTrace();
    	}
		System.out.println(threadNumber + " is done running");
	}
}

Mime
View raw message