SQL常见死锁例子及分析
use XTS
--步骤一=============创建测试表===================================================
--测试表1
if(exists(select 1 from sysobjects where id=OBJECT_ID('testa')))drop table testa
CREATE TABLE testa
(id int primary key,--Id,并标记为主建name varchar(10),--姓名age decimal(26,4),--年龄city varchar(10),--所在城市address varchar(10),--家庭地址remark text --备注
)
--创建非聚集索引
create unique nonclustered index testa_idx1 on testa(name,age) --测试表2
if(exists(select 1 from sysobjects where id=OBJECT_ID('testb')))drop table testb
CREATE TABLE testb
(id int primary key,--Id,并标记为主建name varchar(10),--姓名age decimal(26,4),--年龄city varchar(10),--所在城市address varchar(10),--家庭地址remark text --备注
)--创建非聚集索引
create unique nonclustered index testb_idx1 on testb(name,age) --步骤二===================添加测试数据================================================
insert into testa(id,name,age,city,address)
select 1,'joe',20,'hz','zjwz'insert into testa(id,name,age,city,address)
select 2,'jill',25,'hz','zjhz'insert into testa(id,name,age,city,address)
select 3,'Bob',27,'hz','zjhz'insert into testb(id,name,age,city,address)
select 1,'joe',20,'hz','zjwz'insert into testb(id,name,age,city,address)
select 2,'jill',25,'hz','zjhz'insert into testb(id,name,age,city,address)
select 3,'Bob',27,'hz','zjhz'--添加多一点,是为了查询效率降低,以便快速得到验证结果
declare @i int=4
while (@i<1000)
begininsert into testa(id,name,age,city,address)
select @i,@i,27,'xxxx','xxxx'
set @i=@i+1
end--步骤三===================创建测试存储过程及备用表================================================
IF OBJECT_ID ('p1') IS NOT NULL DROP PROC p1
IF OBJECT_ID ('p2') IS NOT NULL DROP PROC p2
--创建备份表,用于查询存储过程的结果存储
if(exists(select 1 from sysobjects where id=OBJECT_ID('testback')))drop table testback
CREATE TABLE testback
(id int primary key,--Id,并标记为主建name varchar(10),--姓名age decimal(26,4),--年龄city varchar(10),--所在城市address varchar(10)--家庭地址
)if(exists(select 1 from sysobjects where id=OBJECT_ID('testback1')))drop table testback1
CREATE TABLE testback1
(id int primary key,--Id,并标记为主建name varchar(10),--姓名age decimal(26,4),--年龄city varchar(10),--所在城市address varchar(10)--家庭地址
)if(exists(select 1 from sysobjects where id=OBJECT_ID('testback2')))drop table testback2
CREATE TABLE testback2
(id int primary key,--Id,并标记为主建name varchar(10),--姓名age decimal(26,4),--年龄city varchar(10),--所在城市address varchar(10)--家庭地址
)--创建存储过程p1,更新存储过程
CREATE PROC p1 ASUPDATE testa SET age = age+1 WHERE id = 1UPDATE testa SET age = age-1 WHERE id = 1
GO--创建存储过程p2,查询存储过程
CREATE PROC p2 AS
truncate table testback
insert into testback(id,name,age,address)
select id,name,age,address from testa where name='joe'
GO---死锁案例一============两个事物各占有自己的资源,同时又需要对方的资源==================
--查询一
begin transaction
update a set address='TT' from testa a where id=1
waitfor delay '00:00:10'
select * from testb where id=1
commit transaction
--查询二
begin transaction
update a set address='TT' from testb a where id=1
waitfor delay '00:00:10'
select * from testa where id=1
commit transaction--死锁案例二============书签查询引起的死锁=============================================
--高频率update
while (1=1) exec p1--高频率select
while (1=1) exec p2Set statistics profile off
UPDATE testa SET age = age+1 WHERE id = 1
select id,name,age,address from testa where name='joe'--死锁三================在较高隔离级别的事务中,两个事务同时执行查询及更新语句============
--查询事务一
--需要设置事务隔离级别可重复渎或加事务保持锁
SET TRANSACTION ISOLATION LEVEL Repeatable read
while(1=1)
begin
begin transaction
truncate table testback1
insert into testback1(id,name,age,address)
select id,name,age,address from testa where id=1
waitfor delay '00:00:10'
update testa set age=age+1 where id=1
update testa set age=age-1 where id=1
commit transaction
end--查询事务二
SET TRANSACTION ISOLATION LEVEL Repeatable read
while(1=1)
begin
begin transaction
truncate table testback2
insert into testback2(id,name,age,address)
select id,name,age,address from testa where id=1
waitfor delay '00:00:10'
update testa set age=age+1 where id=1
update testa set age=age-1 where id=1
commit transaction
end--死锁四===========同一个表当两个事务都在更新不同的记录时,即使没有更新索上的字段,
--也会引起死锁,因为查询的字段没有全部在所建的普通索引上面,所以同样需要通过聚集索引做全表查询
--但是聚集索引上的行在同一时间点上被不同事务在拥有,这样就造成了两个事务查询的时候都无法获取
--全部的资源,即造成了死锁
--测试数据如下
drop table testx
create table testx(id int primary key,name varchar(10),age int)
create index testx_ind1 on testx(name)
insert into testx(id,name,age)
select '1','袁*','22'
insert into testx(id,name,age)
select '2','程*','20'create table testx1(id int primary key,name varchar(10),age int)
create table testx2(id int primary key,name varchar(10),age int)--查询一
while(1=1)
begin
begin transaction
update testx set age=age+1 where name='程*'
truncate table testx1
insert into testx1(id,name,age)
select id,name,age from testx where name='程*'
commit transaction
end--查询二
while(1=1)
begin
begin transaction
update testx set age=age+1 where name='袁*'
truncate table testx2
insert into testx2(id,name,age)
select id,name,age from testx where name='袁*'
commit transaction
end--那你们可能就会有疑问,那我是不是单纯更新,不做查询的时候也会死锁?因为更新如果也是通过非主键字段更新时,也是全表扫描。
--答案:不会,至于为什么不会,我们只能理解数据库本身在更新和查询时上锁的原理不一样,这个我们也可以做个测试例子。
--查询一=====事务A更新20秒后结束
begin transaction
update testx set age=40 where name='程*'
waitfor delay '00:00:20'
commit transaction--查询二======事务B在5秒后结束
begin transaction
update testx set age=40 where name='袁*'
waitfor delay '00:00:05'
commit transaction--查询三====再分开执行下面两个查询
select * from testx where name='袁*'
select * from testx where name='程*'--测试结果:
--当我们依次执行查询一,再执行查询二,最后执行查询三:
--结果就是查询二5秒后(不需要等待查询一完成)就执行完成了,而查询三无论执行那个查询语句都需要等待20秒后(即必须要等待查询一完成)才能出来查询查询结果
--结论就是更新和查询时上锁原理不一样。--=================隔离级别的演示=============================
DBCC USEROPTIONS
--未提交读(Read uncommitted)演示
--查询一
SET TRANSACTION ISOLATION LEVEL Read uncommitted
select * from testa where id=100
begin transaction
update testa set city='newxx' where id=100
waitfor delay '00:00:10'
rollback transaction --查询二
SET TRANSACTION ISOLATION LEVEL Read uncommitted
select * from testa where id=100--已提交读(Read committed)也叫不可重复渎
--查询一
SET TRANSACTION ISOLATION LEVEL Read committed
select * from testa where id=100
begin transaction
update testa set city='newx' where id=100
waitfor delay '00:00:10'
rollback transaction --查询二
SET TRANSACTION ISOLATION LEVEL Read committed
select * from testa where id=100--可重复读(Repeatable read)演示(保证在同一个事务中,渎取数据不会被其他事务更改)
--查询一
SET TRANSACTION ISOLATION LEVEL Repeatable read
begin transaction
select * from testa where id=100
waitfor delay '00:00:10'
commit transaction--查询二
SET TRANSACTION ISOLATION LEVEL Repeatable read
update testa set city='new' where id=100--可序列化演示(事务的最高级别,保证事务的串行执行)
--查询一
SET TRANSACTION ISOLATION LEVEL Serializable
begin transaction
select * from testa
update testa set city='new' where id=100
waitfor delay '00:00:10'
select * from testa
commit transaction --查询二
SET TRANSACTION ISOLATION LEVEL Serializable
insert into testa(id,name,age,city,address)
select 4000,'Bobx',27,'hz','zjhz'--创建覆盖索引
drop index testa_idx1 on testa
create index testa_idx1 on testa(name,age) include(id,address)--设置隔离级别为可重复渎
SET TRANSACTION ISOLATION LEVEL Repeatable read
DBCC USEROPTIONS --开启事务隔离的方法
declare @sql varchar(8000)
select @sql = '
ALTER DATABASE ' + DB_NAME() + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE ;
ALTER DATABASE ' + DB_NAME() + ' SET TRANSACTION ISOLATION LEVEL read committed;
ALTER DATABASE ' + DB_NAME() + ' SET MULTI_USER;'
Exec(@sql) --查询事务隔离
DBCC Useroptions --清除缓存
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
DBCC FREESYSTEMCACHE('ALL') --开启SQL性能分析
Set statistics profile on--开启SQL执行时间统计
set statistics time ON --开启磁盘的读写统计
set statistics io on--锁查询相关
SELECT request_session_id, resource_type, resource_associated_entity_id,
request_status, request_mode, resource_description
FROM sys.dm_tran_locksselect request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName
from sys.dm_tran_locks where resource_type='OBJECT'sp_lock
sp_who
select * from sys.sysprocesses
dbcc inputbuffer(spid)
SQL常见死锁例子及分析相关推荐
- linux将程序锁死,Linux死锁现象及分析方法(转)
本节我们对Linux死锁做一个基本的介绍,然后讲解如何检测并定位死锁. 1. 什么是死锁? 死锁(DeadLock)是指两个或者两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象 ...
- 关于SQL常见的问题
关于SQL常见的问题 1.MySQL数据库中的char和varchar的主要区别是什么?哪个查询效率高? char有固定的长度:varchar属于可变长的字符类型. char是一种注重时间的存储方式: ...
- Db2数据库中常见的堵塞问题分析与处理方法
Db2 数据库堵塞怎么办 作为一个数据库管理员,工作中经常会遇到的一个问题:当数据库出现故障的情况下,如何快速定位问题和找到解决方案.尤其是在运维非常重要系统的时候,解决问题恢复服务是分秒必争.Db2 ...
- DllMain中不当操作导致死锁问题的分析——DllMain中要谨慎写代码(完结篇)
之前几篇文章主要介绍和分析了为什么会在DllMain做出一些不当操作导致死锁的原因.本文将总结以前文章的结论,并介绍些DllMain中还有哪些操作会导致死锁等问题.(转载请指明出于breaksoftw ...
- DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2
本文介绍使用Windbg去验证<DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子>中的结论,调试对象是文中刚开始那个例子.(转载请指明出于breakso ...
- DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子
有了前面两节的基础,我们现在切入正题:研究下DllMain为什么会因为不当操作导致死锁的问题.首先我们看一段比较经典的"DllMain中死锁"代码.(转载请指明出于breaksof ...
- SQL Server 死锁的告警监控
原文:SQL Server 死锁的告警监控 今天这篇文章总结一下如何监控SQL Server的死锁,其实以前写过MS SQL 监控错误日志的告警信息,这篇文章着重介绍如何监控数据库的死锁,当然这篇文章 ...
- sql server management studio性能分析_如何分析一条SQL的性能
来自公众号:谭小谭 这篇文章将给大家介绍如何使用 explain 来分析一条 sql . 网上其实已经有非常多的文章都很详细的介绍了 explain 的使用,这篇文章将实例和原理结合起来,尽量让你有更 ...
- 一起玩转SQL Server 2012 下的分析服务
转载自:https://blog.csdn.net/aspnetx/article/details/8712286 提到SQL Server 2012的分析服务,那么不得不先说下商业智能,它是一个由数 ...
最新文章
- MySQL 索引详解
- C/Cpp / STL / vector 释放内存的方案
- 这些数学趣图,数学老师看了后会怎么想?
- Nginx Image缩略图模块加强网站运行速度
- UVA5876 Writings on the Wall 扩展KMP
- 使用虚拟机VMware12定制安装redhat6企业版
- java me手机版,一个经典的 JAVA ME 手机程序入门级源码
- Win8(X64)下MySQL5.6版本安装及配置
- css权重机制,CSS权重及其计算
- 计算机图片组合快捷键,Windows电脑常用的10个Win组合快捷键功能,看看你都知道吗?...
- 利用matlab检测曲线,如何在matlab中检测平滑曲线
- 股票中阿尔法和贝塔都什么意思?
- 采样频率、采样点数、频率分辨率
- python里面else什么意思_python中if else和if elif else有什么区别?
- php 视频网站采集器,自己在用的视频网站开源,真正的自动采集无需手动更新...
- 神奇宝贝五分类:数据预处理,可以推广到任意图片集
- 关于flex布局中,父元素高度auto,由一子元素撑开,另一子元素自适应高度问题
- r语言实现关联分析--关联规则挖掘(Apriori算法) (r语言预测学习笔记)
- 温度变送器转换程序c语言,两线制智能温度变送器的设计
- 计算机英语i有关科技翻译的范文,有关健康的英语作文带翻译范文
热门文章
- Win8系统的运行哪里找?
- 用移动硬盘安装系统linux系统,U盘、移动硬盘引导启动安装linux系统【Centos 6.4 】...
- 秘钥认证用户自动控制
- eclipse中安装ant,详细
- 从头开始swift2.1 仿搜材通项目(八) 制定通用的Controller规则
- 【Tools】如何在word/wps中添加代码,并且保持源代码风格
- bind9+mysql搭建高可用DNS解析服务
- python爬取酒店信息_Python 爬虫练手项目—酒店信息爬取
- Layui form 表单验证规则 lay-verify
- 小资之豆浆篇 (IS2120@BG57IV3)