I am writing some spike code that isn't giving me the the results I am expecting.
I have a table that is basically rows of counters. Other tables use these rows to generate what should be unique ID's. When I run the code below what I excepted is that the first thread to reach the the select statement would acquire a lock on that row, or table, stopping all read or writes on the unique id value. However the second thread always completes before the first one, due to it been put to sleep for 1s, thus they both read the same value and write the same value, so it's only increment once and not twice as I excepted.
Is there anything wrong with my code, or is my understanding of the Isolation level's incorrect?
I have removed the boiler plate code. Standard sql.Connection using a MySQL Database.
private void incrementValue() {
connection
.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
statement = connection.createStatement();
System.out.println(Thread.currentThread().getName()
+ " doing select");
resultSet = statement.executeQuery("select * from counter");
System.out.println(Thread.currentThread().getName()
+ "after select");
if (counter++ == 0) {
Thread.sleep(1000);
}
String incrementedValue = getIncrementedValue(resultSet);
statement.executeUpdate("update counter set counter='"
+ incrementedValue + "'");
}
private String getIncrementedValue(ResultSet resultSet) throws SQLException {
String value = "";
if (resultSet.next()) {
System.out.println(Thread.currentThread().getName() + "Value was "
+ resultSet.getString(1));
value = (new Integer(resultSet.getString(1)) + 1) + "";
}
return value;
}
This is called from main
public static void main(String[] args) {
DatabaseExample databaseExample = new DatabaseExample();
Runnable runnable = new Runnable() {
@Override
public void run() {
DatabaseExample databaseExample = new DatabaseExample();
databaseExample.incrementValue();
}
};
new Thread(runnable).start();
databaseExample.incrementValue();
}