Reputation: 10872
I have two tables table_a
and table_b
. In my application, I have a business method which does the following:
// it is one transaction
INSERT INTO table_b (join_col) VALUES (some_value);
UPDATE table_a a
JOIN table_b b ON a.join_col = b.join_col AND a.column_a = b.column_b
SET a.column_c = a.column_c + 1;
I'm using InnoDB engine and the problem is, when I run my method in parallel or almost in parallel, I often get this error message:
Deadlock found when trying to get lock; try restarting transaction
It seems, like the first transaction started to update table_a
and put a lock on table_b
, while the second parallel transaction can not insert into table_b
, because it is locked.
If I comment my UPDATE
statement, it starts working. Both transactions insert into table_b
without problems. So, how can I fix it? If it matters, I'm using MySQL 5.7.
Upvotes: 2
Views: 876
Reputation: 142540
That seems like strange code.
Well, If you are playing with the same B in another thread, what do you expect? You don't want the list of things in B to be changing.
Consider using a TEMPORARY TABLE
for B??
Upvotes: 0
Reputation: 108839
It looks like you're locking table b, then table a. Probably the a lock is an index lock.
Try this, to always grab an appropriate lock on table a first.
BEGIN TRANSACTION;
SELECT COUNT(join_col) INTO @counter
FROM table_a a
WHERE a.join_col = some_value
FOR UPDATE;
INSERT INTO table_b (join_col) VALUES (some_value);
UPDATE table_a a
JOIN table_b b ON a.join_col = b.join_col
AND a.column_a = b.column_b
SET a.column_c = a.column_c + 1;
COMMIT;
The INTO @counter
stuff prevents the first SELECT from returning a result set to your program.
If that doesn't work, try using LOCK TABLES. It's a big hammer, but effective.
LOCK TABLES table_a, table_b WRITE;
your queries
UNLOCK TABLES;
Upvotes: 1