Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When I SELECT multiple rows FOR UPDATE, can I deadlock?

In MySQL+InnoDB, suppose I have a single table, and two threads which both do "SELECT ... FOR UPDATE". Suppose that both of the SELECT statements end up selecting multiple rows, e.g. both of them end up selecting rows R42 and R99. Is it possible that this will deadlock?

I'm thinking of this situation: the first thread tries to lock R42 then R99, the second thread tries to lock R99 then R42. If I'm unlucky, the two threads will deadlock.

I read in the MySQL Glossary for "deadlock" that

A deadlock can occur when the transactions lock rows in multiple tables (through statements such as UPDATE or SELECT ... FOR UPDATE), but in the opposite order. ...

To reduce the possibility of deadlocks, ... create indexes on the columns used in SELECT ... FOR UPDATE and UPDATE ... WHERE statements.

This hints that in my situation (single table) I won't deadlock, maybe because MySQL automatically tries to lock rows in the order of the primary key, but I want to be certain, and I can't find the proper place in the documentation that tells me exactly what's going on.

like image 740
DamonJW Avatar asked Jun 13 '12 03:06

DamonJW


1 Answers

From MySQL documentation

InnoDB uses automatic row-level locking. You can get deadlocks even in the case of 
transactions that just insert or delete a single row. That is because these operations    
are not really “atomic”; they automatically set locks on the (possibly several) index 
records of the row inserted or deleted.

http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlocks.html

So generally, deadlocking is not fatal, you just need to try again, or add the appropriate indexes so that fewer rows are scanned and thus fewer rows are locked.

like image 158
Girish Rao Avatar answered Nov 14 '22 23:11

Girish Rao