SQL-mysql锁等待与死锁

SQL-mysql锁等待与死锁
最新回答
绾青鸢

2026-01-27 04:53:20

SQL-MySQL锁等待与死锁锁等待

锁等待是指在一个事务(session)已经对某行数据获取了独占锁(通常是写锁)后,另一个事务尝试对相同的行获取独占锁时,需要等待前一个事务释放锁的情况。

  • 产生原因:当一个事务持有某行数据的写锁时,其他事务无法同时对该行数据进行写操作,只能等待锁被释放。
  • 示例:

    Session A 执行 BEGIN; update ordersetyear= '2022' where id = '1';,此时 Session A 获取了 id=1 的写锁权限。

    Session B 执行相同的更新语句,由于 id=1 的写锁已被 Session A 获取,Session B 会进入锁等待状态。

  • 超时处理:MySQL 有一个参数 innodb_lock_wait_timeout,用于指定锁等待的超时时间。如果超过这个时间,还未获取到锁,则会报 Lock wait timeout exceeded; try restarting transaction 异常。
  • 查看锁等待:可以使用 SHOW PROCESSLIST 或 SHOW ENGINE INNODB STATUS 查看当前正在等待锁的事务。
死锁

死锁是指两个或更多的事务在相互等待对方释放资源,从而导致所有事务都无法继续执行的情况。

  • 产生原因:

    两个事务分别持有不同的锁,并尝试获取对方持有的锁。

    例如,Session A 获取了 id=1 的写锁,Session B 获取了 id=2 的写锁。然后 Session A 尝试获取 id=2 的写锁,而 Session B 尝试获取 id=1 的写锁,此时两者都进入锁等待状态,形成死锁。

  • 示例:

    Session A 执行 BEGIN; update ordersetyear= '2022' where id = '1';,获取 id=1 的写锁。

    Session B 执行 BEGIN; update ordersetyear= '2022' where id = '2';,获取 id=2 的写锁。

    Session A 尝试执行 update ordersetyear= '2022' where id = '2';,进入锁等待状态。

    Session B 尝试执行 update ordersetyear= '2022' where id = '1';,也进入锁等待状态。

    此时,Session A 和 Session B 都在等待对方释放锁,形成死锁。

  • 检测死锁:MySQL 会自动检测到死锁情况,并回滚其中一个事务,同时报 Deadlock found when trying to get lock; try restarting transaction 异常。
  • 查看死锁信息:可以使用 SHOW ENGINE INNODB STATUS 查看死锁的详细信息,包括涉及的事务、锁的类型、等待的锁等。
如何解决死锁
  1. 查找到死锁线程:通过 SHOW PROCESSLIST 或 SHOW ENGINE INNODB STATUS 查找到涉及死锁的事务和线程 ID。
  2. 杀死死锁线程:使用 KILL 命令终止涉及死锁的事务线程。
  3. 回滚事务:如果事务未提交,MySQL 会自动回滚涉及死锁的事务。
如何避免死锁
  1. 使用表锁:在容易产生死锁的表上使用表锁,虽然会降低并发性能,但可以避免死锁的发生。
  2. 避免交叉使用相同的锁:确保事务在获取锁时,按照相同的顺序进行,避免交叉持有锁的情况。
  3. 优化事务设计:尽量缩短事务的执行时间,减少持有锁的时间,从而降低死锁的概率。
  4. 使用合理的索引:确保查询条件能够充分利用索引,减少锁的范围和数量。

综上所述,锁等待和死锁是 MySQL 中常见的并发控制问题。通过合理的事务设计、锁的使用和监控,可以有效地减少和避免这些问题的发生。