-
2022-01-06 17:28:22
-- 查看被锁死的所有表:
select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName
from sys.dm_tran_locks where resource_type='OBJECT'
--解锁:
KILL spid更多相关内容 -
5 分钟理解数据库死锁
2021-05-07 22:03:39本文简要介绍了数据库死锁产生的原因和解决方法。 加锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。任何事务都需要获得相应对象上的锁才能访问数据,读取数据的事务通常只需要获得读锁(共享...
图片来源:网络🍺知人者智,自知者明。胜人者有力,胜己者强。知足者富,强行者有志。不失其所者久,死而不亡者寿。——老子
大家好!我是只谈技术不剪发的 Tony 老师。
加锁(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; 事务二提交 以上场景不会产生死锁。不过,我们在实际应用中可能无法完全按照相同顺序修改数据。如果出现了不可避免的死锁情况,另一种解决方法就是捕获系统返回的死锁异常并在程序中加入重试机制。
总结
本文简要介绍了数据库死锁产生的原因和解决方法。
-
oracle数据库死锁处理步骤
2020-12-14 20:30:02一、数据库死锁的现象 程序在执行的过程中,点击确定或保存按钮,程序没有响应,也没有出现报错。 二、死锁的原理 当对于数据库某个表的某一列做更新或删除等操作,执行完毕后该条语句不提 交,另一条... -
mysql 数据库死锁原因及解决办法
2020-12-15 09:28:18所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。... -
简单说明Oracle数据库中对死锁的查询及解决方法
2020-12-16 07:59:38通过检查数据库表,能够检查出是哪一条语句被死锁,产生死锁的机器是哪一台。 1)用dba用户执行以下语句 select username,lockwait,status,machine,program from v$session where sid in (select session_id ... -
数据库中死锁那些事儿
2020-12-14 23:56:53特此做一个数据库死锁方面的总结,以绝后患,吼吼! 首先我们来看几个定义: 1、死锁 所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都... -
查看数据库死锁信息
2019-02-26 15:44:01服务器运行一天后,就开始频繁报错:Deadlock found when trying to get to lock; try restarting transaction. 死锁的头号原因是外键未加索引,第二号原因是位图索引遭到并发更改; -
讲解Oracle数据库中结束死锁进程的一般方法
2020-12-15 20:38:22Username:死锁语句所用的数据库用户; Lockwait:死锁的状态,如果有内容表示被死锁。 Status: 状态,active表示被死锁 Machine: 死锁语句所在的机器。 Program: 产生死锁的语句主要来自哪个应用程序 2 -
Mybatis update数据库死锁之获取数据库连接池等待
2020-09-01 23:33:45主要介绍了Mybatis update数据库死锁之获取数据库连接池等待的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 -
【数据库】mysql什么情况下会死锁
2021-01-26 22:38:37mysql中死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。...mysql中死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。
推荐课程:MySQL教程。
死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。
那么对应的解决死锁问题的关键就是:让不同的session加锁有次序
案例
需求:将投资的钱拆成几份随机分配给借款人。
起初业务程序思路是这样的:
投资人投资后,将金额随机分为几份,然后随机从借款人表里面选几个,然后通过一条条select for update 去更新借款人表里面的余额等。
例如两个用户同时投资,A用户金额随机分为2份,分给借款人1,2
B用户金额随机分为2份,分给借款人2,1
由于加锁的顺序不一样,死锁当然很快就出现了。
对于这个问题的改进很简单,直接把所有分配到的借款人直接一次锁住就行了。
Select * from xxx where id in (xx,xx,xx) for update
在in里面的列表值mysql是会自动从小到大排序,加锁也是一条条从小到大加的锁
例如(以下会话id为主键):
Session1:
mysql> select * from t3 where id in (8,9) for update;
+----+--------+------+---------------------+
| id | course | name | ctime |
+----+--------+------+---------------------+
| 8 | WA | f | 2016-03-02 11:36:30 |
| 9 | JX | f | 2016-03-01 11:36:30 |
+----+--------+------+---------------------+
rows in set (0.04 sec)
Session2:
select * from t3 where id in (10,8,5) for update;
锁等待中……
其实这个时候id=10这条记录没有被锁住的,但id=5的记录已经被锁住了,锁的等待在id=8的这里
不信请看
Session3:
mysql> select * from t3 where id=5 for update;
锁等待中
Session4:
mysql> select * from t3 where id=10 for update;
+----+--------+------+---------------------+
| id | course | name | ctime |
+----+--------+------+---------------------+
| 10 | JB | g | 2016-03-10 11:45:05 |
+----+--------+------+---------------------+
row in set (0.00 sec)
在其它session中id=5是加不了锁的,但是id=10是可以加上锁的。
-
数据库 死锁的解决
2012-08-31 12:21:14这种死锁比较隐蔽,但其实在稍大点的项目中经常发生。 解决方法: 让用户A的事务(即先读后写类型的操作),在select 时就是用Update lock 语法如下: select * from table1 with(updlock) where .... -
Mysql 数据库死锁过程分析(select for update)
2020-09-10 05:59:27最近有项目需求,需要保证多台机器不拿到相同的数据,后来发现... for update经常导致数据库死锁问题,下面小编给大家介绍mysql 数据库死锁过程分析(select for update),对mysql数据库死锁问题感兴趣的朋友一起学习吧 -
查询死锁数据库
2018-01-16 10:24:05查询死锁数据库,当同一张表存在同时写,并且写的过程比较耗时,此时就会引起数据库死锁 -
sql数据库死锁查询工具
2017-02-27 15:26:51数据库死锁,阻塞查询,杀死死锁,阻塞进程 -
ORACLE数据库双活RAC实践x_数据库中活锁和死锁的概念
2020-04-20 20:46:08云端的数据库多租户;云端的数据库多租户;云端的数据库多租户;云端的数据库多租户;云端的数据库多租户;多租户架构;云端数据库多租户;云端数据库多租户;云端数据库多租户;云端数据库多租户;云端数据库多租户;云端... -
查询Sqlserver数据库死锁的一个存储过程分享
2020-09-10 14:28:01利用sp_who_lock这个存储过程,可以很方便的知道哪个进程出现了死锁,出现死锁的问题在哪里 -
数据库中的并发控制和死锁活锁
2022-04-19 13:51:29死锁和活锁提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
在数据库中,并发控制,即允许多个事务同时对数据库进行访问
并发控制:- 提高系统利用率和响应时间
- 不同的事物可能访问数据库不同的部分
- 当多个事物访问到相同的部分时可能导致执行上的问题
一、事物并发可能带来的错误类型
读写和写写类型:可能导致的问题如丢失更新,读到脏数据,不可重复的读等问题
二、解决方法(可串行化)
1.介绍
可串行化是并发控制的一个标准,简单来说就是有n个事物,会有n!个执行结果,我们只要保证最终执行结果时n!中的一个,就说事物的并发控制是正确的
2.封锁法(实现可串行化的方法之一)
封锁法是决大多数并发控制的解决方法,锁是针对数据对象的,这里以关系为单位,实际上还可以对某个元组上锁等,引入三种封锁机制
- X锁(排他锁)
当事物T1给关系R上排他锁之后,这时候T2对R的读写是不允许的
封锁阶段(2PL):
在一个事物中,所有加锁请求都在解锁前面完成,即如下图,我们称这个限定为2PL
在一个事物中,对数据对象进行操作前,我们会寻求先上锁,这是一种好的表现,称为“well-formed"
如果有那么一个计划是满足2PL和well-formed的,我们称这个S计划是可串行化的,即可并操作。- S锁(共享锁)
允许读,不允许写,S可以有多把。T1给R上了S,T2寻求对R的读,则给R也上S,这时候就可以访问R了。这时候对R的X是不允许的,即不允许修改。 - U锁(更新锁)
对一个更新请求,我们先给上U锁,当真正需要到更新操作时,U锁升级为X锁。这样子可以缩短执行时间,提高并发程度。在U锁的基础上还可以上S锁,即真正修改更新前,我们还可以读操作。
三种锁的并发程度和负担
3.死锁和活锁
死锁:时间顺序上可以理解为T1对R1上X锁,T2对R2上X锁,这时候T2访问到R1,等待T1对R1解锁,处于等待中,但是此时T1也访问到R2,需要等待R2的解锁才可以进行R1的解锁,那么这两个事物就陷入了死循环。再通俗点的一个笑话:hr问你什么时死锁,你回答hr:“你给我offer我就告诉你什么时死锁"。
活锁,也叫饿死现象:尽管不存在死循环,但是等待时间过长活锁是简单的,我们需要关注的是死锁,从预防和解决两个角度解决死锁问题
方案
- 等待时间,给事物设置一个等待时间,当一个事物等待时间达到标准时,事物就会被废弃掉。这只适合小型的数据库,对数据库系统来说,如果等待时间设置的太短,会有无辜的事物被当成发生了死锁给处理掉,时间太长就检测不出死锁,效率低下。
- 等待图,G是事物集合,V是等待时间,当图中出现环的时候,我们就可以认定出现了死锁现象,我们可以周期性检查等待图,或者每当有一个事物添加到图里面时就进行检查。
当图中发生死锁时,我们会挑一个事物abort掉,使得rollback代价最小 - 给事物中的关系一次性上锁,不然不执行,但是这样显然效率会很低下
- 给资源顺序排序,然后在事物中上锁。但是这不符合数据库的应用,数据库中的数据是经常变动的修改的。我们给洗衣机,热水器,微波炉资源排序,如果一个人想要使用这三样,必须按照顺序来,先使用洗衣机,哪怕热水器空着,洗衣机有人在排队。
- 时间戳,具体应用就是死亡等待和伤害等待,这也是在解决死锁方面常用的有效方案
时间戳上简单概况包含了TID,即事物的ID,确保每个事物都是独一无二的和比较年龄
死亡等待:a要用到r,但是b已经锁了r,这时候a和b比较,如果a比较老,就继续等待,a比较年轻的话,直接死掉,后面重启。我们要知道事物会随着时间的推移逐步进行的,即老事物的数量是有限的,新事物是无限的。某个事物年轻,脾气暴躁不能等,无法等到,经过几次重启后,他就会成为最老的,这时候就到他使用了。在他几次排队等待的时间上,后面的比他年轻,也得排在他后面
伤害等待:年轻的等老的
无论是哪种,我们都要确保这是单向的,在时间线上遵循同样的原则
-
数据库查询死锁
2022-01-14 17:09:51数据库查询全局死锁 -
分布式数据库系统中的死锁处理
2020-11-22 13:33:08分布式数据库系统中的死锁处理 -
MySQL数据库的一次死锁实例分析
2021-01-19 22:41:202、背景场景简化如下(数据库引擎InnoDb,数据隔离级别RR[REPEATABLE]) -- 创建表test1 CREATE TABLE test1 ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(10) NOT NULL, PRIMARY KEY (id) ); insert into ... -
数据库什么时候会产生死锁?
2021-01-20 01:03:44数据库从20世纪50年代诞生伊始,就因为支持事务的特性得到大力的发展,最终各种数据库诸如oracle,Sybase,mysql等关系型数据库百花齐放,既然数据库是因为事务而生,那么事务的特性又是哪些呢?简而言之就是ACID... -
各种类型数据库的死锁问题
2020-03-04 12:24:58本文介绍了一位资深的数据库工程师在实际情况中遇到的一些数据库死锁问题。 -
数据库死锁监控.exe
2019-08-28 13:57:40数据库死锁监控,自动刷新,右键杀死进程,查看存储历史执行时间等信息。 -
数据库死锁和操作系统中的死锁
2019-02-26 11:20:30要想知道数据库中的死锁是什么原因首先要有这个数据库知识基础:如果“修改”一条数据,首先数据库管理系统会在上面加锁,以保证在同一时间只有一个事务能进行修改操作。锁定发生在一个事务获得对某一资源的“锁”时... -
数据库以及线程发生死锁
2019-09-18 16:31:13产生死锁的原因主要是: (1) 因为系统资源不足。 (2) 进程运行推进的顺序不合适。...(3)不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 (4)循环等待条件:若干进程之间形成一种头尾相接... -
MYSQL 数据库死锁
2019-08-07 02:11:52博文链接:https://gghaomm.iteye.com/blog/2123485