Mysql锁等待超时错误
我在我的应用程序中有一个场景,事务下的简单INSERT语句阻塞MySQL中不同行上的DELETE语句,最终DELETE语句会话超时并出现lock time out错误 我试图在下面的简单场景中解释这种情况。注意,在列上添加索引会有帮助,但是,如果我在DELETE的WHERE子句中有两列,我仍然会看到lock wait timeout。另外请注意,在我启动事务后,我需要做一些其他处理,因此事务提交或回滚只需几分钟。很难相信,即使我删除了不同于我试图插入的记录,MySQL也会阻止它 第1节:Mysql锁等待超时错误,mysql,locking,Mysql,Locking,我在我的应用程序中有一个场景,事务下的简单INSERT语句阻塞MySQL中不同行上的DELETE语句,最终DELETE语句会话超时并出现lock time out错误 我试图在下面的简单场景中解释这种情况。注意,在列上添加索引会有帮助,但是,如果我在DELETE的WHERE子句中有两列,我仍然会看到lock wait timeout。另外请注意,在我启动事务后,我需要做一些其他处理,因此事务提交或回滚只需几分钟。很难相信,即使我删除了不同于我试图插入的记录,MySQL也会阻止它 第1节: mys
mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation, @@session.tx_isolation;
+-----------------------+----------------+------------------------+
| @@GLOBAL.tx_isolation | @@tx_isolation | @@session.tx_isolation |
+-----------------------+----------------+------------------------+
| READ-COMMITTED | READ-COMMITTED | READ-COMMITTED |
+-----------------------+----------------+------------------------+
1 row in set (0.02 sec)`
mysql> create table testtab(col1 int, col2 int);
Query OK, 0 rows affected (0.53 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO testtab values(1,1);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testtab values(2,2);
Query OK, 1 row affected (0.00 sec)
第二节:
mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation, @@session.tx_isolation;
+-----------------------+----------------+------------------------+
| @@GLOBAL.tx_isolation | @@tx_isolation | @@session.tx_isolation |
+-----------------------+----------------+------------------------+
| READ-COMMITTED | READ-COMMITTED | READ-COMMITTED |
+-----------------------+----------------+------------------------+
1 row in set (0.00 sec)
mysql> DELETE FROM testtab where col1=3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
有什么建议吗?这是InnoDB锁定工作原理的结果。引用 锁定读取、更新或删除通常会对SQL语句处理过程中扫描的每个索引记录设置记录锁定。语句中是否存在排除该行的WHERE条件并不重要。InnoDB不记得确切的WHERE条件,只知道扫描了哪些索引范围 同样值得注意的是 如果没有适合语句的索引,并且MySQL必须扫描整个表来处理语句,那么表中的每一行都会被锁定,从而阻止其他用户对表的所有插入。创建好的索引非常重要,这样查询就不会不必要地扫描许多行 因此,在您的情况下,两个
insert
将两个锁定的行添加到表中。由于没有合适的索引,delete
现在将扫描整个表。它必须锁定遇到的每一行,但要做到这一点,它必须等待insert
创建的锁被解除(这不会及时发生)
在<代码> COL1中添加索引将解决此问题,因为<代码>删除>代码>只需考虑(使用代码)> COL1=3 < /代码>行,它可以使用索引查找,因此不会与其他事务插入的行重叠。 如果您在为“两列where条件”找到一个好的索引时遇到问题,您应该添加更多关于它的详细信息,可能会有一个适合这种情况的索引
当然,这不会阻止所有情况(例如,如果您确实想要修改同一行),因此通常最好将事务保持尽可能短,准备等待那么长的时间和/或准备在需要时重复事务顺便说一句,这并不是对InnoDB锁的完整描述,只是解释您的情况的部分。对于类似的示例,如果我想看到阻塞查询(显示完整进程列表仅显示会话2的查询),我有哪些选项。我尝试显示引擎innodb状态、完整进程列表等,但似乎没有显示INSERT语句,这实际上导致事务运行更长时间。