日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

SQL常见死锁例子及分析

發(fā)布時(shí)間:2023/12/29 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQL常见死锁例子及分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

use XTS --步驟一=============創(chuàng)建測(cè)試表=================================================== --測(cè)試表1 if(exists(select 1 from sysobjects where id=OBJECT_ID('testa')))drop table testa CREATE TABLE testa (id int primary key,--Id,并標(biāo)記為主建name varchar(10),--姓名age decimal(26,4),--年齡city varchar(10),--所在城市address varchar(10),--家庭地址remark text --備注 ) --創(chuàng)建非聚集索引 create unique nonclustered index testa_idx1 on testa(name,age) --測(cè)試表2 if(exists(select 1 from sysobjects where id=OBJECT_ID('testb')))drop table testb CREATE TABLE testb (id int primary key,--Id,并標(biāo)記為主建name varchar(10),--姓名age decimal(26,4),--年齡city varchar(10),--所在城市address varchar(10),--家庭地址remark text --備注 )--創(chuàng)建非聚集索引 create unique nonclustered index testb_idx1 on testb(name,age) --步驟二===================添加測(cè)試數(shù)據(jù)================================================ 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'--添加多一點(diǎn),是為了查詢效率降低,以便快速得到驗(yàn)證結(jié)果 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--步驟三===================創(chuàng)建測(cè)試存儲(chǔ)過程及備用表================================================ IF OBJECT_ID ('p1') IS NOT NULL DROP PROC p1 IF OBJECT_ID ('p2') IS NOT NULL DROP PROC p2 --創(chuàng)建備份表,用于查詢存儲(chǔ)過程的結(jié)果存儲(chǔ) if(exists(select 1 from sysobjects where id=OBJECT_ID('testback')))drop table testback CREATE TABLE testback (id int primary key,--Id,并標(biāo)記為主建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,并標(biāo)記為主建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,并標(biāo)記為主建name varchar(10),--姓名age decimal(26,4),--年齡city varchar(10),--所在城市address varchar(10)--家庭地址 )--創(chuàng)建存儲(chǔ)過程p1,更新存儲(chǔ)過程 CREATE PROC p1 ASUPDATE testa SET age = age+1 WHERE id = 1UPDATE testa SET age = age-1 WHERE id = 1 GO--創(chuàng)建存儲(chǔ)過程p2,查詢存儲(chǔ)過程 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---死鎖案例一============兩個(gè)事物各占有自己的資源,同時(shí)又需要對(duì)方的資源================== --查詢一 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'--死鎖三================在較高隔離級(jí)別的事務(wù)中,兩個(gè)事務(wù)同時(shí)執(zhí)行查詢及更新語句============ --查詢事務(wù)一 --需要設(shè)置事務(wù)隔離級(jí)別可重復(fù)瀆或加事務(wù)保持鎖 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--查詢事務(wù)二 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--死鎖四===========同一個(gè)表當(dāng)兩個(gè)事務(wù)都在更新不同的記錄時(shí),即使沒有更新索上的字段, --也會(huì)引起死鎖,因?yàn)椴樵兊淖侄螞]有全部在所建的普通索引上面,所以同樣需要通過聚集索引做全表查詢 --但是聚集索引上的行在同一時(shí)間點(diǎn)上被不同事務(wù)在擁有,這樣就造成了兩個(gè)事務(wù)查詢的時(shí)候都無法獲取 --全部的資源,即造成了死鎖 --測(cè)試數(shù)據(jù)如下 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--那你們可能就會(huì)有疑問,那我是不是單純更新,不做查詢的時(shí)候也會(huì)死鎖?因?yàn)楦氯绻彩峭ㄟ^非主鍵字段更新時(shí),也是全表掃描。 --答案:不會(huì),至于為什么不會(huì),我們只能理解數(shù)據(jù)庫本身在更新和查詢時(shí)上鎖的原理不一樣,這個(gè)我們也可以做個(gè)測(cè)試?yán)印?--查詢一=====事務(wù)A更新20秒后結(jié)束 begin transaction update testx set age=40 where name='程*' waitfor delay '00:00:20' commit transaction--查詢二======事務(wù)B在5秒后結(jié)束 begin transaction update testx set age=40 where name='袁*' waitfor delay '00:00:05' commit transaction--查詢?nèi)?#61;===再分開執(zhí)行下面兩個(gè)查詢 select * from testx where name='袁*' select * from testx where name='程*'--測(cè)試結(jié)果: --當(dāng)我們依次執(zhí)行查詢一,再執(zhí)行查詢二,最后執(zhí)行查詢?nèi)? --結(jié)果就是查詢二5秒后(不需要等待查詢一完成)就執(zhí)行完成了,而查詢?nèi)裏o論執(zhí)行那個(gè)查詢語句都需要等待20秒后(即必須要等待查詢一完成)才能出來查詢查詢結(jié)果 --結(jié)論就是更新和查詢時(shí)上鎖原理不一樣。--=================隔離級(jí)別的演示============================= 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)也叫不可重復(fù)瀆 --查詢一 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--可重復(fù)讀(Repeatable read)演示(保證在同一個(gè)事務(wù)中,瀆取數(shù)據(jù)不會(huì)被其他事務(wù)更改) --查詢一 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--可序列化演示(事務(wù)的最高級(jí)別,保證事務(wù)的串行執(zhí)行) --查詢一 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'--創(chuàng)建覆蓋索引 drop index testa_idx1 on testa create index testa_idx1 on testa(name,age) include(id,address)--設(shè)置隔離級(jí)別為可重復(fù)瀆 SET TRANSACTION ISOLATION LEVEL Repeatable read DBCC USEROPTIONS --開啟事務(wù)隔離的方法 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) --查詢事務(wù)隔離 DBCC Useroptions --清除緩存 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE DBCC FREESYSTEMCACHE('ALL') --開啟SQL性能分析 Set statistics profile on--開啟SQL執(zhí)行時(shí)間統(tǒng)計(jì) set statistics time ON --開啟磁盤的讀寫統(tǒng)計(jì) set statistics io on--鎖查詢相關(guān) 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)

總結(jié)

以上是生活随笔為你收集整理的SQL常见死锁例子及分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。