
|
If you were logged in you would be able to see more operations.
|
|
|
|
Environment:
|
Debian GNU/Linux 3.1 i386
Apache Tomcat 5.0.27
MySQL 4.1.10-Debian_1-log
Debian GNU/Linux 3.1 i386
Apache Tomcat 5.0.27
MySQL 4.1.10-Debian_1-log
|
|
|
Parrallel requests on a basic workflow creates duplicate primary keys constraint errors with mysql.
The problem comes from the missing instruction "nextVal" because sequences are not implemented in mysql.
Therefore, a simple table with just one field is used in osworkflow for having atomicity.
In osworkflow manual, mysql queries for getting a new step id is :
CREATE TABLE OS_STEPIDS
(
ID bigint NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
)TYPE=InnoDB;
-------------------------------------------
INSERT INTO OS_STEPIDS (ID) values (null);
SELECT max(ID) FROM OS_STEPIDS;
And, if there are multiple concurrent calls on doAction(), it is possible that the getNextStepSequence() method of MySQLWorkflowStore return the same id.
Indeed, another insert can arrive between the insert and the select query described above.
Then the max will be the last insert id and not the one we want...
Then a solution is to used the mysql instruction LAST_INSERT_ID() like this :
INSERT INTO OS_STEPIDS (ID) values (null);
SELECT LAST_INSERT_ID();
Because, mysql certifies this is atomic on a per-connection basis :
The last ID that was generated is maintained in the server on a per-connection basis. This means the value the function returns to a given client is the most recent AUTO_INCREMENT value generated by that client. The value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that you can retrieve your own ID without concern for the activity of other clients, and without the need for locks or transactions.
The same problem is encountered with entry ids and the getNextEntrySequence() method of JDBCWorkflowStore.
Then, we can use the same queries with a new table :
CREATE TABLE OS_ENTRYIDS
(
ID bigint NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
)TYPE=InnoDB;
-------------------------------------------
INSERT INTO OS_ENTRYIDS (ID) values (null);
SELECT LAST_INSERT_ID();
Redefining the getNextEntrySequence() method on MySQLWorkflowStore with the same code as getNextStepSequence() methode corrects this bug.
With this solution i did not notice concurrency problems by calling initialize or doAction. I test this with a web application based on tomcat and especially cocoon.
PS : I do not use JNDI by changing getConnection() for giving a SQL Connection from my connection pool.
|
|
Description
|
Parrallel requests on a basic workflow creates duplicate primary keys constraint errors with mysql.
The problem comes from the missing instruction "nextVal" because sequences are not implemented in mysql.
Therefore, a simple table with just one field is used in osworkflow for having atomicity.
In osworkflow manual, mysql queries for getting a new step id is :
CREATE TABLE OS_STEPIDS
(
ID bigint NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
)TYPE=InnoDB;
-------------------------------------------
INSERT INTO OS_STEPIDS (ID) values (null);
SELECT max(ID) FROM OS_STEPIDS;
And, if there are multiple concurrent calls on doAction(), it is possible that the getNextStepSequence() method of MySQLWorkflowStore return the same id.
Indeed, another insert can arrive between the insert and the select query described above.
Then the max will be the last insert id and not the one we want...
Then a solution is to used the mysql instruction LAST_INSERT_ID() like this :
INSERT INTO OS_STEPIDS (ID) values (null);
SELECT LAST_INSERT_ID();
Because, mysql certifies this is atomic on a per-connection basis :
The last ID that was generated is maintained in the server on a per-connection basis. This means the value the function returns to a given client is the most recent AUTO_INCREMENT value generated by that client. The value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that you can retrieve your own ID without concern for the activity of other clients, and without the need for locks or transactions.
The same problem is encountered with entry ids and the getNextEntrySequence() method of JDBCWorkflowStore.
Then, we can use the same queries with a new table :
CREATE TABLE OS_ENTRYIDS
(
ID bigint NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
)TYPE=InnoDB;
-------------------------------------------
INSERT INTO OS_ENTRYIDS (ID) values (null);
SELECT LAST_INSERT_ID();
Redefining the getNextEntrySequence() method on MySQLWorkflowStore with the same code as getNextStepSequence() methode corrects this bug.
With this solution i did not notice concurrency problems by calling initialize or doAction. I test this with a web application based on tomcat and especially cocoon.
PS : I do not use JNDI by changing getConnection() for giving a SQL Connection from my connection pool. |
Show » |
| There are no comments yet on this issue.
|
|