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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

SQL SERVER的锁机制(三)——概述(锁与事务隔离级别)

發(fā)布時(shí)間:2023/11/27 生活经验 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQL SERVER的锁机制(三)——概述(锁与事务隔离级别) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

五、鎖與事務(wù)隔離級(jí)別

事務(wù)隔離級(jí)別簡(jiǎn)單的說,就是當(dāng)激活事務(wù)時(shí),控制事務(wù)內(nèi)因SQL語句產(chǎn)生的鎖定需要保留多入,影響范圍多大,以防止多人訪問時(shí),在事務(wù)內(nèi)發(fā)生數(shù)據(jù)查詢的錯(cuò)誤。設(shè)置事務(wù)隔離級(jí)別將影響整條連接。

SQL?Server?數(shù)據(jù)庫引擎支持所有這些隔離級(jí)別:

·?未提交讀(隔離事務(wù)的最低級(jí)別,只能保證不讀取物理上損壞的數(shù)據(jù))

·?已提交讀(數(shù)據(jù)庫引擎的默認(rèn)級(jí)別)

·?可重復(fù)讀

·?可序列化(隔離事務(wù)的最高級(jí)別,事務(wù)之間完全隔離)

SQL?Server?還支持使用行版本控制的兩個(gè)事務(wù)隔離級(jí)別。一個(gè)是已提交讀隔離的新實(shí)現(xiàn),另一個(gè)是新事務(wù)隔離級(jí)別(快照)。

?

設(shè)置語句如下:

SET?TRANSACTION?ISOLATION?LEVEL

????{?READ?UNCOMMITTED

????|?READ?COMMITTED

????|?REPEATABLE?READ

????|?SNAPSHOT

????|?SERIALIZABLE

????}

[?;?]

?

(一)未提交讀

未提交讀是最低的事務(wù)隔離級(jí)別,允許讀取其他事務(wù)已經(jīng)修改但未提交的數(shù)據(jù)行。SQL?SERVER?當(dāng)此事務(wù)等級(jí)進(jìn)行嘗試讀取數(shù)據(jù)時(shí),不會(huì)放置共享鎖,直接讀取數(shù)據(jù),所以忽略已存在的互斥鎖。換句話說,即使該資源已經(jīng)受到了獨(dú)占鎖的保護(hù),當(dāng)使用未提交讀隔離級(jí)別時(shí),此數(shù)據(jù)還是可以被讀取,加快查詢速度,但是會(huì)讀取到別人未修改的數(shù)據(jù),所以此種讀取被稱為臟讀。此種隔離級(jí)別適合不在乎數(shù)據(jù)變更的查詢場(chǎng)景。此隔離級(jí)別與SELECT?語句搭配?NOLOCK?所起到的效果相同

未提交讀示例:

--1.--1.創(chuàng)建測(cè)試表

create?table?tbUnRead

(ID?INT,

name?nvarchar(20)

)

--2新增記錄

insert?tbUnRead?

select?1,'Tom'

union

select?2,'Jack'

--3開啟事務(wù),并進(jìn)行更新

?

begin?tran

update?tbUnRead

set?name='Jack_upd'

where?ID=2

---4查詢事務(wù)數(shù)量(由于沒有回滾或提交事務(wù))

SELECT?@@TRANCOUNT

事務(wù)查詢結(jié)果如下:

?

--5打開另一條連接,設(shè)置事務(wù)隔離級(jí)別為(未提交讀)

set?Transaction?isolation?level?read?uncommitted

--6查詢數(shù)據(jù),查詢到的數(shù)據(jù)是修改之后的數(shù)據(jù)。

select?*?from?tbUnRead?where?ID=2

如下圖:

?

?

(二)已提交讀

已提交讀是SQL?SERVER?默認(rèn)的事務(wù)隔離級(jí)別。當(dāng)事務(wù)正在讀取數(shù)據(jù)時(shí),SQL?SERVER?會(huì)放置共享鎖以防止其他事務(wù)修改數(shù)據(jù),當(dāng)數(shù)據(jù)讀取完成之后,會(huì)自動(dòng)釋放共享鎖,其他事務(wù)可以進(jìn)行數(shù)據(jù)修改。因?yàn)楣蚕礞i會(huì)同時(shí)封鎖封鎖語句執(zhí)行,所以在事務(wù)完成數(shù)據(jù)修改之前,是無法讀取該事務(wù)正在修改的數(shù)據(jù)行。因此此隔離級(jí)別可以防止臟讀。

?

在SQL?SERVER?2005以上版本中,如果設(shè)置READ_COMMITTED_SNAPSHOT為ON,則已提交讀的事務(wù)全使用數(shù)據(jù)行版本控制的隔離下讀取數(shù)據(jù)。讀取操作不會(huì)獲取正被讀取的數(shù)據(jù)上的共享鎖(S?鎖),因此不會(huì)阻塞正在修改數(shù)據(jù)的事務(wù)。同時(shí),由于減少了所獲取的鎖的數(shù)量,因此最大程度地降低了鎖定資源的開銷。使用行版本控制的已提交讀隔離和快照隔離旨在提供副本數(shù)據(jù)的語句級(jí)或事務(wù)級(jí)讀取一致性。

示例一:設(shè)置READ_COMMITTED_SNAPSHOT為OFF

--1.創(chuàng)建測(cè)試表

create?table?tbUnRead

(ID?INT,

name?nvarchar(20)

)

--2新增記錄

insert?tbUnRead?

select?1,'Tom'

union

select?2,'Jack'

--3開啟事務(wù),并進(jìn)行更新

?

begin?tran

update?tbUnRead

set?name='Jack_upd'

where?ID=2

---4查詢事務(wù)數(shù)量(由于沒有回滾或提交事務(wù))

SELECT?@@TRANCOUNT

--5打開另一條連接,設(shè)置事務(wù)隔離級(jí)別為(已提交讀)

set?Transaction?isolation?level?read?committed

--6查詢數(shù)據(jù),由于當(dāng)前事務(wù)沒有提交,所以無法查詢數(shù)據(jù)

select?*?from?tbUnRead?where?ID=2

6查詢數(shù)據(jù)的結(jié)果 如下圖:

?

?

?

示例二:設(shè)置READ_COMMITTED_SNAPSHOT為ON

use?master

go

---創(chuàng)建測(cè)試數(shù)據(jù)庫

create?database?read_committed_SNAPSHOT_Test

go

---激活數(shù)據(jù)行版本控制

alter?database?read_committed_SNAPSHOT_Test??set?read_committed_SNAPSHOT?on

go

?

use?read_committed_SNAPSHOT_Test

go

?

--1.創(chuàng)建測(cè)試表

create?table?tbReadLevel

(ID?INT,

name?nvarchar(20)

)

?

--2新增記錄

insert?tbReadLevel

select?1,'測(cè)試'

go

select?ID,name?as?"修改前數(shù)據(jù)"??from?tbReadLevel

如下圖:

?

go

--3開啟事務(wù),并進(jìn)行更新

?

begin?tran

update?tbReadLevel

set?name='Jack_upd'

where?ID=1

---4查詢事務(wù)數(shù)量(由于沒有回滾或提交事務(wù))

SELECT?@@TRANCOUNT

?

--5打開另一條連接,設(shè)置事務(wù)隔離級(jí)別為(已提交讀)

--查詢數(shù)據(jù),查詢到的數(shù)據(jù)是上一次提交的數(shù)據(jù)

select?*?from?tbReadLevel?where?ID=1

?5的查詢結(jié)果如下圖:

?

(三)可重復(fù)讀

可重復(fù)讀事務(wù)隔離級(jí)別在事務(wù)過程中,所有的共享鎖均保留到事務(wù)結(jié)束,而不是讀取結(jié)束就釋放,這與已提交讀的行為截然不同,雖然在事務(wù)過程中,重復(fù)查詢相同記錄時(shí)不受其他事務(wù)的影響,但可能由于鎖定數(shù)據(jù)過久,而導(dǎo)致其他人無法處理數(shù)據(jù),影響并發(fā)率,更嚴(yán)重的可能提高發(fā)生死鎖的機(jī)率。

? 總之,如果使用可重復(fù)讀隔離級(jí)別讀取數(shù)據(jù),數(shù)據(jù)讀出之后,其他事務(wù)只能對(duì)此范圍中的數(shù)據(jù)進(jìn)行讀取或新增,但不可以進(jìn)行修改,直到讀取事務(wù)完成。因此,使用此隔離級(jí)別需要謹(jǐn)慎小心,根據(jù)實(shí)際情況進(jìn)行設(shè)置。

?

示例:

?

--1.創(chuàng)建測(cè)試表

create?table?tbUnRead

(ID?INT,

name?nvarchar(20)

)

--2新增記錄

insert?tbUnRead?

select?1,'Tom'

union

select?2,'Jack'

?

--3設(shè)置事務(wù)隔離級(jí)別為(可重復(fù)讀)

set?Transaction?isolation?level?REPEATABLE?READ

--4開啟事務(wù),并進(jìn)行更新

begin?tran

?

--5查詢數(shù)據(jù)

select?*?from?tbUnRead?where?ID=2

---6查詢事務(wù)數(shù)量(沒有回滾或提交事務(wù))

SELECT?@@TRANCOUNT

5與6的執(zhí)行結(jié)果如下圖

?

---7開啟另一條連接,查詢數(shù)據(jù)與修改數(shù)據(jù)?

---事務(wù)雖然沒有完成,但可以查詢到之前的數(shù)據(jù)

select?*?from?tbUnRead?where?ID=2

Go

---8,修改數(shù)據(jù),由于事務(wù)沒有完成,所以無法進(jìn)行修改

update?tbUnRead

set?name='Jack_upd'

where?ID=2

go

--7、8的執(zhí)行結(jié)果如下,可以查詢數(shù)據(jù),但無法更新數(shù)據(jù),如下圖。

?

?

?

(四)快照

快照隔離級(jí)別是SQL?SERVER?2005之后版本新增的隔離級(jí)別,開啟之后,允許事務(wù)過程中讀取操作不受異動(dòng)影響,事務(wù)中任一語句所讀取的數(shù)據(jù),均予事務(wù)激活時(shí),就已經(jīng)完成提交,符合事務(wù)一致性的數(shù)據(jù)行版本。所以只能查核事務(wù)激活之前已經(jīng)完成提交的數(shù)據(jù),也就是說可以查詢已經(jīng)完成提交的數(shù)據(jù)行快照集,但看不見已激活的事務(wù)正在進(jìn)行修改的數(shù)據(jù)行。當(dāng)使用快照隔離級(jí)別讀取數(shù)據(jù)時(shí)不會(huì)要求對(duì)數(shù)據(jù)進(jìn)行鎖定,如果所讀取的記錄正在被某事務(wù)進(jìn)行修改,它也會(huì)讀取此記錄之前已經(jīng)提交的數(shù)據(jù)。故當(dāng)某記錄被事務(wù)進(jìn)行修改時(shí),SQL?SERVER的TEMPDB數(shù)據(jù)庫會(huì)存儲(chǔ)最近提交的數(shù)據(jù)行,以供快照隔離級(jí)別的事務(wù)讀取數(shù)據(jù)時(shí)使用。將Allow_SNAPSHOT_isolation設(shè)為ON,事務(wù)就會(huì)設(shè)置快照隔離級(jí)別。

?

use?master

go

---創(chuàng)建測(cè)試數(shù)據(jù)庫(快照)

create?database?SNAPSHOT_Test

go

---激活數(shù)據(jù)行版本控制

alter?database?SNAPSHOT_Test??set?Allow_SNAPSHOT_isolation?on

go

?

use?SNAPSHOT_Test

go

?

--1.創(chuàng)建測(cè)試表

create?table?tbReadLevel

(ID?INT,

name?nvarchar(20)

)

?

--2新增記錄

insert?tbReadLevel

select?1,'測(cè)試'

union

select?2,'快照測(cè)試'

go

select?ID,name?as?"修改前數(shù)據(jù)"

from?tbReadLevel

go

--3開啟事務(wù),并進(jìn)行更新

begin?tran

update?tbReadLevel

set?name='Jack_upd_快照'

where?ID=1

---4查詢事務(wù)數(shù)量(沒有回滾或提交事務(wù))

SELECT?@@TRANCOUNT

--2、4的執(zhí)行結(jié)果,如下圖。

?

--5打開另一條連接,設(shè)置事務(wù)隔離級(jí)別為(快照)

set?Transaction?isolation?level?SNAPSHOT

--6查詢數(shù)據(jù),查詢的數(shù)據(jù)是上一次提交的數(shù)據(jù)

select?*?from?tbReadLevel?where?ID=1

?

?

(五)可序列化

可序列化是事務(wù)隔離級(jí)別中最高的級(jí)別,為最嚴(yán)謹(jǐn)?shù)母綦x級(jí)別,因?yàn)樗鼤?huì)鎖定整個(gè)范圍的索引鍵,使事務(wù)與其他事務(wù)完全隔離。在現(xiàn)行事務(wù)完成之前,其他事務(wù)不能插入新的數(shù)據(jù)行,其索引鍵值存在于現(xiàn)行事務(wù)所讀取的索引鍵范圍之中。此隔離級(jí)別與Select?搭配holdlock效果一樣。

示例:

--1.創(chuàng)建測(cè)試表

create?table?tbUnRead

(ID?INT,

name?nvarchar(20)

)

--2新增記錄

insert?tbUnRead?

select?1,'Tom'

union

select?2,'Jack'

--3設(shè)置事務(wù)隔離級(jí)別為(可序列化)

?

set?Transaction?isolation?level?SERIALIZABLE

--5開啟事務(wù),并進(jìn)行更新

begin?tran

select?*?from?tbUnRead?where?ID=2

---6查詢事務(wù)數(shù)量(沒有回滾或提交事務(wù))

SELECT?@@TRANCOUNT

5、6執(zhí)行結(jié)果如下圖。

---7,開啟另一條連接,查詢數(shù)據(jù),可以查詢到之前的數(shù)據(jù)

select?*?from?tbUnRead?where?ID=2

---8,修改數(shù)據(jù),無法修改數(shù)據(jù)

update?tbUnRead

set?name='Jack_upd'

where?ID=2

--新增數(shù)據(jù),無法插入數(shù)據(jù)

insert?tbUnRead?

select?3,'May'

轉(zhuǎn)載于:https://www.cnblogs.com/littlewrong/p/9025759.html

總結(jié)

以上是生活随笔為你收集整理的SQL SERVER的锁机制(三)——概述(锁与事务隔离级别)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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