5分钟快速了解数据库死锁产生的场景和解决方法

 更新时间:2021年05月10日 10:21:32   作者:不剪发的Tony老师  
这篇文章主要给大家介绍了关于如何通过5分钟快速理解数据库死锁的相关资料,文中介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

加锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。任何事务都需要获得相应对象上的锁才能访问数据,读取数据的事务通常只需要获得读锁(共享锁),修改数据的事务需要获得写锁(排他锁)。当两个事务互相之间需要等待对方释放获得的资源时,如果系统不进行干预则会一直等待下去,也就是进入了死锁(deadlock)状态。

以下内容适用于各种常见的数据库管理系统,包括 Oracle、MySQL、Microsoft SQL Server 以及 PostgreSQL 等。

死锁是如何产生的?

演示死锁的产生非常简单,我们只需要创建一个包含两行数据的简单示例表:

CREATE TABLE t_lock(id int PRIMARY KEY, col int);
INSERT INTO t_lock VALUES (1, 100);
INSERT INTO t_lock VALUES (2, 200);

SELECT * FROM t_lock;
id|col|
--+---+
 1|100|
 2|200|

如果我们在不同事务中以不同的顺序修改数据,就可能引起事务之间的相互等待。一个事务等待另一个事务释放资源不会产生什么问题,但是如果两个事务互相等待对方的资源,数据库管理系统只有两个选择:无限等待或者中止一个事务并让另一个事务成功执行。

显然无限等待不是解决问题的方法,因此数据库通常是等待一定时间之后中止其中一个事务。

以下是一个死锁的演示案例:

事务一 事务二 备注
BEGIN; BEGIN; 分别开始两个事务
UPDATE t_lock
SET col = col + 100
WHERE id = 1;
UPDATE t_lock
SET col = col + 200
WHERE id = 2;
事务一修改 id=1 的数据,事务二修改 id=2 的数据
UPDATE t_lock
SET col = col + 100
WHERE id = 2;
事务一修改 id=2 的数据,需要等待事务二释放写锁
等待中… UPDATE t_lock
SET col = col + 200
WHERE id = 1;
事务二修改 id=1 的数据,需要等待事务一释放写锁
死锁 死锁 数据库检测到死锁,选择中止一个事务
更新成功 返回错误

对于 MySQL InnoDB,默认启用了 innodb_deadlock_detect 选项,事务二返回以下错误信息:

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

如果我们禁用 InnoDB 死锁检测选项,事务二在等待 50 s(innodb_lock_wait_timeout )后提示等待超时:

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

Oracle 检测到死锁时返回以下错误:

ORA-00060: 等待资源时检测到死锁

Microsoft SQL Server 检测到死锁时返回的错误如下

消息 1205,级别 13,状态 51,第 7 行
事务(进程 ID 67)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

PostgreSQL 检测到死锁时返回的错误如下:

SQL 错误 [40P01]: 错误: 检测到死锁
  详细:进程32等待在事务 4765上的ShareLock; 由进程16552阻塞.
进程16552等待在事务 4766上的ShareLock; 由进程32阻塞.
  建议:详细信息请查看服务器日志.
  在位置:当更新关系"t_lock"的元组(0, 1)时

如何解决并避免死锁

死锁不是数据库自身的问题,我们无法通过优化数据库配置来解决或者避免死锁,只能通过修改应用程序来解决。简单来说,我们应该在程序中按照相同的顺序修改数据,避免产生相互等待资源的情况发生。例如:

事务一 事务二 备注
BEGIN; BEGIN; 分别开始两个事务
UPDATE t_lock
SET col = col + 100
WHERE id = 1;

UPDATE t_lock
SET col = col + 200
WHERE id = 1;
事务一和事务二都修改 id=1 的数据,后执行的事务需要等待
UPDATE t_lock
SET col = col + 100
WHERE id = 2;
等待中… 事务一修改 id=1 的数据,事务二等待中
COMMIT; 等待中… 事务一提交
UPDATE t_lock
SET col = col + 200
WHERE id = 2;
事务二继续修改 id=2 的数据
COMMIT; 事务二提交

以上场景不会产生死锁。不过,我们在实际应用中可能无法完全按照相同顺序修改数据。如果出现了不可避免的死锁情况,另一种解决方法就是捕获系统返回的死锁异常并在程序中加入重试机制。

总结

本文简要介绍了数据库死锁产生的原因和解决方法。到此这篇关于5分钟快速了解数据库死锁产生的场景和解决方法的文章就介绍到这了,更多相关数据库死锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spark SQL操作JSON字段的小技巧

    Spark SQL操作JSON字段的小技巧

    这篇文章主要给大家介绍了关于Spark SQL操作JSON字段的小技巧,文中通过示例代码介绍的非常详细,对大家学习或者使用spark sql具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-04-04
  • navicat导入CSV文件详细操作步骤

    navicat导入CSV文件详细操作步骤

    通过Navicat我们可以很方便的完成备份和还原操作,下面这篇文章主要给大家介绍了关于navicat导入CSV文件的详细操作步骤,需要的朋友可以参考下
    2023-12-12
  • 站内群发消息三种不同用户量的数据库设计

    站内群发消息三种不同用户量的数据库设计

    很多SNS网站和一部分CMS网站都广泛地应用了站内信这一模块,这个看似简单的东西其实背后隐藏着很多需要设计师重视的设计细节,要做好这个“邮递员”是很不容易的,本文讲述站内群发消息三种不同用户量的数据库设计,逐渐设计一个百万级用户量的站内信群发数据库
    2023-12-12
  • 8种主流NoSQL数据库系统特性对比和最佳应用场景

    8种主流NoSQL数据库系统特性对比和最佳应用场景

    这篇文章主要介绍了8种主流NoSQL数据库系统特性对比和最佳应用场景,对选择一个NoSQL数据库来说是一个不错的参考文章,需要的朋友可以参考下
    2014-06-06
  • clickhouse数据库删除数据的五种方式

    clickhouse数据库删除数据的五种方式

    clickhouse数据库清理数据的方式很多,每种方式都各有自己的优缺点,请根据实际需要采用适合自己的方式,本文将逐一给大家介绍,并通过代码示例讲解的非常详细,需要的朋友可以参考下
    2024-03-03
  • 关于Navicat连接MySql数据库慢的问题

    关于Navicat连接MySql数据库慢的问题

    这篇文章主要介绍了关于Navicat连接MySql数据库慢的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 使用SQL语句查询MySQL,SQLServer,Oracle所有数据库名和表名,字段名

    使用SQL语句查询MySQL,SQLServer,Oracle所有数据库名和表名,字段名

    本文例出了使用SQL语句查询MySQL,SQLServer,Oracle所有数据库名和表名的SQL语句,有需要的可以参考下
    2018-03-03
  • neo4j创建数据库以及导入csv文件内容图文详解

    neo4j创建数据库以及导入csv文件内容图文详解

    这篇文章主要给大家介绍了关于neo4j创建数据库以及导入csv文件内容的相关资料,Neo4j是一个基于图形结构的NoSQL数据库,它提供了一种高效的方式来管理和查询大型复杂数据,需要的朋友可以参考下
    2023-11-11
  • SQLite与MySQL区别及优缺点介绍

    SQLite与MySQL区别及优缺点介绍

    这篇文章介绍了SQLite与MySQL的区别及优缺点,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01
  • navicat怎么卸载,navicat彻底卸载干净教程

    navicat怎么卸载,navicat彻底卸载干净教程

    这篇文章主要介绍了navicat怎么卸载?navicat彻底卸载干净教程。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02

最新评论