A deadlock I do not understand.

I am not an expert in InnoDB internals and have only little experience with using transactions actually. But I have started learning basics and understanding SHOW ENGINE INNODB STATUS (and the Information_Schema tables exposing same information in later versions). I stumbled across a different behavior between MySQL 5.0 and later and also find other transactional engines exposing yet another behavior. This is related to SELECT .. LOCK IN SHARE MODE primarily. But let us take SELECT .. FOR UPDATE as well for completness. Case(s) 1 below is about SELECT .. FOR UPDATE and case(s) 2 is about SELECT .. LOCK IN SHARE MODE.

— Case 1a (all InndoDB/XtraDB versions + PBXT)

— From connection 1: Execute the following
USE test;
CREATE TABLE blah(a INT PRIMARY KEY) ENGINE=INNODB;
INSERT INTO blah(a) VALUES(1);
INSERT INTO blah(a) VALUES(0);
START TRANSACTION;
SELECT * FROM blah FOR UPDATE;

— From connection 2: Execute the following
USE test;
DELETE FROM blah;

— from connection 1:
DELETE FROM blah; — 2 row(s) affected

— connection 2 still waiting for commit/rollback/lock_wait_timeout as expected

— case 1 behave identically with all server versions and storage engines supporting transactions (with the exception of ‘Aria’ engine – see case 1b).

— —————————————————————————————————————–

— Case 1b (Aria engine as of MariaDB 5.2.2)

— From connection 1: Execute the following
USE test;
CREATE TABLE blah(a INT PRIMARY KEY) ENGINE=ARIA TRANSACTIONAL = 1;
INSERT INTO blah(a) VALUES(1);
INSERT INTO blah(a) VALUES(0);
START TRANSACTION;
SELECT * FROM blah FOR UPDATE;

— From connection 2: Execute the following
USE test;
DELETE FROM blah; — 2 rows affected so no LOCK on table

— from connection 1:
DELETE FROM blah; — 0 row(s) affected

— —————————————————————————————————————–

— Case 2a – MySQL servers/InnoDB 5.1.51 and 5.5.6 as well as XtraDB as of MariaDB 5.2.2:
— From connection 1:
USE test;
CREATE TABLE blah(a INT PRIMARY KEY) ENGINE=INNODB;
INSERT INTO blah(a) VALUES(1);
INSERT INTO blah(a) VALUES(0);
START TRANSACTION;
SELECT * FROM blah LOCK IN SHARE MODE;

— from connection 2:
USE test;
DELETE FROM blah; — waiting

— from connection 1:
DELETE FROM blah; — 2 rows affected

— connection 2 now instantaneously pops up message
/*
Error Code : 1213
Deadlock found when trying to get lock; try restarting transaction
*/

— —————————————————————————————————————–

— Case 2b – server 5.0.90:
— From connection 1:
USE test;
CREATE TABLE blah(a INT PRIMARY KEY) ENGINE=INNODB;
INSERT INTO blah(a) VALUES(1);
INSERT INTO blah(a) VALUES(0);
START TRANSACTION;
SELECT * FROM blah LOCK IN SHARE MODE;

— from connection 2:
USE test;
DELETE FROM blah;

— from connection 1:
DELETE FROM blah; — 2 rows affected

— connection 1 now pops up message
/*
Error Code : 1213
Deadlock found when trying to get lock; try restarting transaction
*/

— —————————————————————————————————————–

— Case 2c – MariaDB 5.5.2 with PBXT and ARIA engines (they behave the same here)

— From connection 1:
USE test;
CREATE TABLE blah(a INT PRIMARY KEY) ENGINE=INNODB; — ARIA is the same
INSERT INTO blah(a) VALUES(1);
INSERT INTO blah(a) VALUES(0);
START TRANSACTION;
SELECT * FROM blah LOCK IN SHARE MODE;

— from connection 2:
USE test;
DELETE FROM blah; — 2 rows affected, so no LOCK on table

— from connection 1:
DELETE FROM blah; — 0 rows affected

What I do not understand is:

1) What is the explanation of this different server (ie. InnoDB) behaviour between 5.0 and 5.1? Is it a plain bug in MySQL/InnoDB 5.0? Or is it happening due to different (default – I have not changed InnoDB defaults with this example) configuration settings?

2) Why cannot connection 2 in case 2a simply wait and execute DELETE (what will then be against an empty table in this case) once connection 1 has committed and why will there need to be a deadlock with this case? The deadlock prompts instantaneously after the other connection has executed DELETE (and not committed). Bad timing? Server/storage engine interface problem? Or only a Peter-problem? 🙂

Documentation at
http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html
and
http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
.. are not identical (but ‘content-wise’ I do not see much difference between them, so this does not help me).

It further looks like PBXT does not handle SELECT .. LOCK IN SHARE MODE (but SELECT .. FOR UPDATE seems to work fine and identically to InnoDB). I do not know if PBXT is supposed to handle SELECT .. LOCK IN SHARE MODE – now or one day in the future (but if not I’d prefer a plain error returned!). Also I am not sure what the tested version of the ARIA engine is supposed to do in its current stage (it is documented that “TRANSACTIONAL = 1” does not mean it has full transactions support but it should ‘gain’ it over time, I understand). With ARIA neither SELECT .. LOCK IN SHARE MODE nor SELECT .. FOR UPDATE seem to have any effect even if table is declared TRANSACTIONAL = 1.

So trying neither PBXT nor ARIA helped me to understand the difference between MySQL 5.0 and later versions with SELECT …LOCK IN SHARE MODE . And FALCON I do not find it interesting to spend time with now.