I'm trying to move my application from a single server database to a Galera cluster, this application uses some FOR UPDATE
locks.
Consider this case:
create table rooms ( id int not null, owner int null, PRIMARY KEY (`id`));
insert into rooms values (1, null);
I want to be sure to not overwrite room owner in case of concurrent queries. I will set the owner ID in the room only if the current owner is NULL.
1st TEST - SINGLE DATABASE SERVER
TRX1 - SERVER A
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT * FROM rooms WHERE id=1 FOR UPDATE;
TRX2 - SERVER A
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT * FROM rooms WHERE id=1 FOR UPDATE;
-> here the TRX2 is on hold waiting TRX1.
TRX1 - SERVER A
UPDATE rooms SET owner=1 WHERE id=1;
COMMIT;
-> here the TRX2 is released and the room is retrieved with the updated owner from TRX1. This is the current correct behaviour for a correct concurrency handling.
2st TEST - GALERA CLUSTER WITH 2 DATABASE SERVERS
TRX1 - SERVER A
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT * FROM rooms WHERE id=1 FOR UPDATE;
TRX2 - SERVER B
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT * FROM rooms WHERE id=1 FOR UPDATE;
-> here the TRX2 is NOT put on hold!
TRX1 - SERVER A
UPDATE rooms SET owner=1 WHERE id=1;
COMMIT;
TRX2 - SERVER B
UPDATE rooms SET owner=2 WHERE id=1;
COMMIT;
-> here the TRX2 fails with DEADLOCK error.
Is there any solution to let the second transaction waits the commit of the first trx even if it is running on a second clusetered server?