这两天遇到一个死锁的问题,两个程序同时使用 delete 删除两张表,A 程序使用的是T1 LEFT JOIN T2,B 程序使用的是T2 INNER JOIN T1。此时会出现死锁。
因为两个程序的 SQL 连结表的时候,T1 、T2 表的顺序不同,所以尝试把 B 程序T2 INNER JOIN T1调整成T1 INNER JOIN T2,依然会出现死锁。
最后把 B 程序也改成 LEFT JOIN:T1 LEFT JOIN T2,多次尝试后没有发生死锁。但是如果把 B 程序改成T2 LEFT JOIN T1的话,会非常容易发生死锁。
而且SHOW ENGINE INNODB STATUS查看死锁信息信息的时候明确可以看到是record lock。
所以我想问的是,是不是T1 LEFT JOIN T2的时候,会优先把 T1 里的所有 record 锁上,然后再锁 T2 里的 record 。
但是T1 INNER JOIN T2的时候,顺序就不一定了。
我猜测的是:
- LEFT JOIN 的时候,因为 T1 表的所有数据都一定会用上,所以直接遍历上锁了,然后再去遍历 T2 ,所以 T1 中的所有数据一定先于 T2 上锁。
- INNER JOIN 的时候是从 T1 选择一个 record 锁上,然后去遍历 T2 ,相当于一个双重 for 循环。所以 T1 、T2 中的上锁顺序不一定先后顺序如何。
有人知道是不是这么回事吗?