MySQL 中的记录锁定问题

问题描述 投票:0回答:1

几天以来,我在一个大表(超过 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 locking record gap-system
1个回答
0
投票

您遇到的问题是 MySQL 中死锁或锁争用的典型案例。当两个或多个事务正在等待彼此释放锁,从而阻止其中任何一个事务继续进行时,就会发生死锁。当多个事务竞争相同的资源(行或页)并导致一个或多个事务等待锁被释放时,就会出现锁争用。

在您的情况下,提供的信息表明ID为

34362692
的事务正在等待授予锁,并且已经等待了10秒,最终导致锁等待超时错误。

您可以采取以下一些步骤来解决此问题:

  1. 找出原因:

    • 尝试识别导致争用的查询和事务。查找经常锁定行或表的长时间运行的事务或查询。
  2. 分析查询和索引:

    • 检查导致锁定的查询。检查是否针对
      WHERE
      条件使用了正确的索引。索引不足或不正确可能会导致全表扫描和锁定。
  3. 事务隔离级别:

    • 考虑调整事务隔离级别。如果可能,请使用 READ COMMITTED 隔离级别,这可以降低锁和死锁的风险。但是,这可能并不适合所有场景,因此请评估它对您的应用程序的影响。
  4. 优化交易:

    • 尽量减少事务持有锁的时间。如果某个事务不需要长时间持有锁,请尽快释放它。
  5. 查询调优:

    • 优化您的查询以最大限度地减少被锁定的行数并减少锁定的持续时间。确保您使用正确的索引、编写高效的查询并避免不必要的锁定。
  6. 检查索引:

    • 确保您的表在搜索条件涉及的列上有适当的索引。索引可以通过减少持有锁的时间来显着提高性能。
  7. 避免不必要的锁定:

    • 考虑使用带有
      FOR UPDATE
      FOR SHARE
      子句的 SELECT 语句来仅锁定需要修改的特定行。
  8. 批量处理:

    • 如果您的应用程序允许,请考虑使用批处理在单个事务中更新或处理多行。这可以减少事务和关联锁的数量。
  9. 监控和调整:

    • 持续监控数据库是否存在锁争用问题。您可以使用
      SHOW ENGINE INNODB STATUS
      SHOW PROCESSLIST
      等工具来了解当前正在运行和等待的事务。
  10. 硬件及配置:

  • 确保服务器的硬件、内存和配置足以满足数据库工作负载。调整与InnoDB相关的MySQL配置参数以针对您的特定场景进行优化。

请记住,优化并发性和最小化锁争用对于保持良好的数据库性能至关重要。但是,可能需要结合查询优化、应用程序逻辑调整和潜在的数据库架构更改才能有效解决问题。

© www.soinside.com 2019 - 2024. All rights reserved.