几天以来,我在一个大表(超过 800,000 条记录)中遇到了 MySQL 问题。到目前为止,我已经确定问题似乎出在 2 条记录上,但我无法更新它们。当我运行失败的更新语句时,这就是我看到的。
我该如何解决这个问题?诸如显示进程列表之类的东西;不显示任何其他内容。冲洗桌子似乎也没有帮助。
Trx id counter 34362695
Purge done for trx's n:o < 34362695 undo n:o < 0 state: running but idle
History list length 2
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 283740434665792, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 283740434664240, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 283740434663464, not started
2 lock struct(s), heap size 1128, 2 row lock(s)
---TRANSACTION 34362692, ACTIVE 10 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1128, 1 row lock(s)
MySQL thread id 8, OS thread handle 9000, query id 52534 localhost ::1 root updating
update users set level = -2 where userid = 5747443
------- TRX HAS BEEN WAITING 10 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 113290 page no 2534 n bits 192 index PRIMARY of table `xyz`.`users` trx id 34362692 lock_mode X locks rec but not gap waiting
Record lock, heap no 21 PHYSICAL RECORD: n_fields 18; compact format; info bits 0
最终导致
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
您遇到的问题是 MySQL 中死锁或锁争用的典型案例。当两个或多个事务正在等待彼此释放锁,从而阻止其中任何一个事务继续进行时,就会发生死锁。当多个事务竞争相同的资源(行或页)并导致一个或多个事务等待锁被释放时,就会出现锁争用。
在您的情况下,提供的信息表明ID为
34362692
的事务正在等待授予锁,并且已经等待了10秒,最终导致锁等待超时错误。
您可以采取以下一些步骤来解决此问题:
找出原因:
分析查询和索引:
WHERE
条件使用了正确的索引。索引不足或不正确可能会导致全表扫描和锁定。事务隔离级别:
优化交易:
查询调优:
检查索引:
避免不必要的锁定:
FOR UPDATE
或 FOR SHARE
子句的 SELECT 语句来仅锁定需要修改的特定行。批量处理:
监控和调整:
SHOW ENGINE INNODB STATUS
和 SHOW PROCESSLIST
等工具来了解当前正在运行和等待的事务。硬件及配置:
请记住,优化并发性和最小化锁争用对于保持良好的数据库性能至关重要。但是,可能需要结合查询优化、应用程序逻辑调整和潜在的数据库架构更改才能有效解决问题。