Question

We are developing online schedule application. One schedule can be edited simultaneously by several users. There is one very important business constraint. There must be only three events in one day.

Technically speaking and simplifying, there is a table in database with columns: | id | event | date |. Application runs in transaction "select... count... where..." and if result is less than 3, it inserts new event.

Wich approaches can be used to guarantee that two threads will not create four events in one day? This is a classical check-and-write problem. And we wonder how it can be solved on database level?

Using transactions doesn`t guarantee that in the second transaction another thread will not do the same: checks that number of events is less than 3 and makes insert. Locking the whole table is not acceptable because it will reduce response time, concurrency, etc.

Application is developed in Java using Spring, Hibernate, MySQL.

Thanks in advance for any pieces of advice.

Was it helpful?

Solution

For blocking process you should use Select ... FOR UPDATE statement. But this one works only in innodb.

Example:

//java logic
try {
    //mysql logic
    start transaction;
    select * from where 'some condition' FOR UPDATE
    INSERT INTO TABLE ....    
    commit;
//java logic
catch (Exception e) {
    rollback;
}

See more info about specific row locking http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html

OTHER TIPS

With your data model you could use a check constraint to count the number of rows. AFAIK MySQL doesn't natively support this type of constraint, but it looks like it's possible to emulate them with a trigger

Alternatively you could consider a different data model with a days table and an events table. You could use optimistic locking of days to ensure that a second transaction didn't have an out of date understanding of the data.

Since you are going through Spring, and since there is a concurrency issue, try synchronizing execution at the Java layer, rather than at the DB layer. We've had similar issues when trying to use a DB to maintain concurrency.

Perhaps you could make the execution block in Java synchronized so that it forces execution to block; inside the synchronized method, check that all of your business logic returns true. if true, continue with normal execution. If false, abort with an exception.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top