我正在运行以下MySQL UPDATE语句:

mysql> update customer set account_import_id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

我没有使用事务,为什么会得到这个错误?我甚至尝试重新启动我的MySQL服务器,它没有帮助。

该表有406,733行。


当前回答

行数并不大……如果account_import_id不是主键,则在它上创建一个索引。

CREATE INDEX idx_customer_account_import_id ON customer (account_import_id);

其他回答

查看一下您的数据库是否进行了微调,特别是事务隔离。增加innodb_lock_wait_timeout变量不是一个好主意。

检查MySQL中的数据库事务隔离级别:

mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation, @@session.tx_isolation;
+-----------------------+-----------------+------------------------+
| @@GLOBAL.tx_isolation | @@tx_isolation  | @@session.tx_isolation |
+-----------------------+-----------------+------------------------+
| REPEATABLE-READ       | REPEATABLE-READ | REPEATABLE-READ        |
+-----------------------+-----------------+------------------------+
1 row in set (0.00 sec)

您可以通过更改隔离级别来获得改进。使用类似oracle的READ COMMITTED而不是REPEATABLE READ。REPEATABLE READ是InnoDB的默认值。

mysql> SET tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

此外,仅在必要时尝试使用SELECT FOR UPDATE。

完全符合MarkR的说法。自动提交使每个语句成为一个语句事务。

SHOW ENGINE INNODB STATUS会给你一些死锁原因的线索。还要仔细查看慢速查询日志,看看还有什么正在查询表,并尝试删除正在执行满表罐操作的任何内容。行级锁定工作得很好,但当您试图锁定所有行的时候就不行了!

如何强制解锁MySQL中锁定的表:

像这样打破锁可能会导致数据库中的原子性不被强制用于导致锁的sql语句。

这很棘手,正确的解决方案是修复导致锁的应用程序。然而,当美元处于危险之中时,迅速的一脚将使事情再次启动。

1)进入MySQL

mysql -u your_user -p

2)让我们看看锁定的桌子列表

mysql> show open tables where in_use>0;

3)让我们看看当前进程的列表,其中一个正在锁定你的表

mysql> show processlist;

4)终止其中一个进程

mysql> kill <put_process_id_here>;

我有2个Doctrine DBAL连接,其中一个是非事务性的(用于重要日志),它们旨在并行运行,而不是相互依赖。

CodeExecution(
    TransactionConnectionQuery()
    TransactionlessConnectionQuery()
)

我的集成测试被包装到事务中,以便在每次测试后进行数据回滚。

beginTransaction()
CodeExecution(
    TransactionConnectionQuery()
    TransactionlessConnectionQuery() // CONFLICT
)
rollBack()

我的解决方案是在这些测试中禁用包装事务,并以另一种方式重置db数据。

某些东西阻塞了查询的执行。很可能是另一个查询更新、插入或删除查询中的某个表。你必须找出那是什么:

SHOW PROCESSLIST;

一旦你找到阻塞进程,找到它的id并运行:

KILL {id};

重新运行初始查询。