maria-discuss team mailing list archive
-
maria-discuss team
-
Mailing list archive
-
Message #04401
Re: Exclusive lock not working
Hi, Jesse!
On Mar 17, Jesse Schalken wrote:
> I have a transaction that checks if a row exists with a particular value
> and if not, generates the data for that row and inserts it:
>
> -- schema
>
> CREATE TABLE test (
> col INT,
> data TEXT,
> KEY (col)
> );
>
> -- transaction
>
> START TRANSACTION;
> SELECT * FROM test WHERE col = 4 FOR UPDATE;
> -- If no results, generate data and insert
> INSERT INTO test SET col = 4, data = 'generated data goes here';
> COMMIT;
>
> The problem I have is that if two copies of this transaction run
> concurrently (with the queries interleaved), they both pass the SELECT and
> deadlock on the INSERT. I would expect that the SELECT would acquire an
> exclusive lock on "col = 4" so only one transaction will proceed to insert,
> but the "FOR UPDATE" seems to behave as a shared lock instead.
The statement SELECT ... FOR UPDATE works for you exactly as it says. It
*selects* and locks it *for update*. Because the row doesn't exist,
SELECT actually selects nothing. So it locks nothing for update.
When the row exists, the first transaction returns a row and the second
waits on SELECT.
> What is the correct way to write this transaction so only one copy proceeds
> to generate the "data" string and insert the row?
Your goal is to "check if a row exists with a particular value
and if not, generate the data for that row and insert it". Normally
uniqueness checks are done inside a database. Make your KEY (col) a
UNIQUE key, then when you insert the database will check whether a row
exists and will insert the value if not.
If you insist on doing it in the application, you can try user-level
locks, GET_LOCK/RELEASE_LOCK functions. Like
SELECT GET_LOCK(4, 10);
-- If the result is 1
SELECT * FROM test WHERE col = 4;
-- If no results, generate data and insert
INSERT INTO test SET col = 4, data = 'generated data goes here';
SELECT RELEASE_LOCK(4);
Regards,
Sergei
Chief Architect MariaDB
and security@xxxxxxxxxxx
Follow ups
References