欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文分析SQL?Server中事務(wù)使用的鎖

 更新時間:2022年09月02日 10:46:46   作者:hkant  
這篇文章主要介紹了一文分析SQL?Server中事務(wù)使用的鎖,數(shù)據(jù)庫引擎使用不同的鎖模式鎖定資源,通過不同鎖的組合使用達到不同的數(shù)據(jù)庫事務(wù)隔離級別,需要的朋友可以參考一下

本文屬于基礎(chǔ)知識的回顧,在日常技術(shù)交流和日常工作中經(jīng)常發(fā)現(xiàn)有些同事了解關(guān)于數(shù)據(jù)庫事務(wù)的基本知識,會看SQL語句的執(zhí)行計劃,也知道數(shù)據(jù)庫有X鎖、U鎖和S鎖等各種鎖,但是對于這些鎖在數(shù)據(jù)庫事務(wù)執(zhí)行期間是如何工作?為何這樣配合才能完成數(shù)據(jù)庫事務(wù)?數(shù)據(jù)庫是如何對于各種資源加鎖的?等等這類的問題不太了解,那么對于事務(wù)的執(zhí)行肯定不會有深刻的認識。

這類知識雖然從網(wǎng)上搜索可以找到很多,但是大多內(nèi)容重復(fù),并且只注重理論知識而沒有實踐路徑。就好比池塘中的青蓮只可遠觀而無法靠近仔細觀察,猶如霧里看花水中望月,對于其真實原理總是似懂非懂。

紙上得來終覺淺,絕知此事要躬行,只有親自動手進行分析才能對這些問題有深入的認識,因此本文計劃從數(shù)據(jù)庫的基礎(chǔ)知識入手,以詳細的實踐分析步驟引導(dǎo)認識數(shù)據(jù)庫事務(wù)的執(zhí)行過程,以期讀者可以對于事務(wù)有更加深刻的理解。

SQL Server使用的鎖及鎖對象

數(shù)據(jù)庫引擎使用不同的鎖模式鎖定資源,通過不同鎖的組合使用達到不同的數(shù)據(jù)庫事務(wù)隔離級別。

鎖模式編號效果說明
共享鎖S共享鎖,通常用于不修改數(shù)據(jù)也不希望數(shù)據(jù)被修改的場景
更新鎖U用于可更新的資源,防止這類資源在讀取、鎖定以及隨后可能進行的資源更新時出現(xiàn)死鎖
排他鎖X用于修改數(shù)據(jù)的操作,例如insert、update和delete,防止對同一個資源進行多重修改
意向鎖 包括意向共享、意向更新和意向排他三種,用于保護較低級別的鎖并提升性能
架構(gòu)鎖 用于執(zhí)行依賴表結(jié)構(gòu)的操作時使用,包括架構(gòu)修改 (Sch-M) 和架構(gòu)穩(wěn)定性 (Sch-S)
大容量更新BU在將數(shù)據(jù)大容量復(fù)制到表中且指定了 TABLOCK 提示時使用
鍵范圍 當(dāng)使用可序列化事務(wù)隔離級別時保護查詢讀取的行的范圍。

意向鎖又細分為多種類型:

鎖模式編號效果說明
意向共享IS保護針對底層資源的共享鎖
意向排他IX保護針對底層資源的排他鎖是,IS的超集
共享意向排他SIX保護針對低層資源請求或獲取的意向排他鎖以意向共享鎖
意向更新IU保護針對底層資源的更新鎖
共享意向更新SIUS鎖和IU鎖的組合,作為分別獲取并同時具備兩種鎖的組合效果
更新意向排他UIXU鎖和IX鎖的組合,作為分別獲取并同時具備兩種鎖的組合效果

架構(gòu)鎖細分為兩種類型:

鎖模式編號效果說明
架構(gòu)修改鎖Sch-MDDL執(zhí)行期間使用架構(gòu)修改鎖,該鎖會阻止對于表的所有訪問
架構(gòu)穩(wěn)定鎖Sch-S該鎖不會影響S、U以及X鎖的執(zhí)行,但是會阻止DDL的執(zhí)行

通常開發(fā)人員談到數(shù)據(jù)庫的鎖的時候習(xí)慣說數(shù)據(jù)庫鎖、表鎖或者行鎖。這種描述通常是從被鎖定資源的角度來談?wù)?,通過檢索SQL Server2016的文檔發(fā)現(xiàn)數(shù)據(jù)庫上鎖定更多的資源不只是這三種維度,還有11種類型。

鎖對象關(guān)于鎖對象的說明
AllocUnit分配單元
Application應(yīng)用程序?qū)S玫馁Y源
Database整個數(shù)據(jù)庫
Extent一組連續(xù)的8個頁
File數(shù)據(jù)庫文件
Heap/B-tree堆或者B樹
Key索引上的某一行
Metadata元數(shù)據(jù)
Object表、存儲過程、視圖等包括所有的數(shù)據(jù)和索引
OIB用于聯(lián)機索引構(gòu)建時的鎖
Page數(shù)據(jù)庫上8KB頁
RID堆上的某一行
RowGroup列存儲索引行組的時候使用的鎖
Xact事務(wù)的鎖定資源

了解了數(shù)據(jù)庫的鎖及其鎖定對象,那么日常使用的select、insert和update語句到底是如何應(yīng)用這些概念呢?

SQL Server執(zhí)行Select時使用的鎖

首先通過建表腳本創(chuàng)建一個數(shù)據(jù)庫表:

USE [Test]
GO
/****** Object:  Table [dbo].[UserTable]    Script Date: 2022/6/29 20:08:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserTable](
	[id] [varchar](36) NOT NULL,
	[name] [varchar](256) NULL,
	[code] [varchar](256) NULL,
	[createtime] [datetime] NULL,
	[lastmodifytime] [datetime] NULL,
PRIMARY KEY CLUSTERED 
(
	[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
USE [Test]
GO
INSERT [dbo].[UserTable] ([id], [name], [code], [createtime], [lastmodifytime]) VALUES (N'5E4B68B0-71B8-43FB-B6B4-8E9D43A30589', N'test1', N'123456', CAST(N'2022-06-29T18:02:21.517' AS DateTime), CAST(N'2022-06-29T18:02:21.517' AS DateTime))
GO

由于Select語句在SQL Server的默認事務(wù)隔離級別(read commited)中執(zhí)行完成后就會釋放相關(guān)的鎖,而非等到事務(wù)結(jié)束,在這種情況下無法通過sp_lock或者sys.dm_tran_locks視圖觀察select語句執(zhí)行過程中鎖的執(zhí)行情況,因此比較方便的辦法是在查詢語句執(zhí)行之前調(diào)整當(dāng)前會話的事務(wù)隔離級別為repeatable read,在這個隔離級別中select語句默認會在事故執(zhí)行完成后提交,比較方便分析。

在SQL Server Manager Studio的查詢窗口中執(zhí)行語句:

set transaction isolation level repeatable read
set statistics profile on 
begin tran
select * from usertable where  id='5E4B68B0-71B8-43FB-B6B4-8E9D43A30589'

在前面的事務(wù)目前是已經(jīng)執(zhí)行未提交的狀態(tài),此時可以通過dm_tran_locks查詢到該語句目前持有的鎖:

select request_session_id,resource_type,request_status,request_mode,resource_description,
case resource_type
when 'Page' then OBJECT_NAME(p.object_id)
when 'object' then OBJECT_NAME(lock.resource_associated_entity_id)
when 'database' then (select name from master..SysDatabases where dbid=resource_database_id)
when 'key' then object_name(p.object_id)
end 
as objectName from sys.dm_tran_locks lock
left join sys.partitions p 
on p.hobt_id=lock.resource_associated_entity_id
order by lock.request_session_id
request_session_idresource_typerequest_statusrequest_moderesource_descriptionobjectName
62DATABASEGRANTS Test
62PAGEGRANTIS0.236111111UserTable
62OBJECTGRANTIS UserTable
62KEYGRANTS(0ee48b5e6942)UserTable

查詢結(jié)果字段說明:

  • request_session_id:會話編號
  • resource_type:被鎖定的資源類型
  • request_status:請求的狀態(tài)
  • request_mode:鎖類型
  • resource_description 資源描述情況
  • objectName:對象名稱

目前select查詢持有的鎖:

  • 通過目前的查詢結(jié)果可以看到在DATABASE上加了S鎖(數(shù)據(jù)庫名為Test);
  • 在數(shù)據(jù)所屬的頁上增加了意向共享鎖;
  • 表上增加了意向共享鎖;
  • 數(shù)據(jù)行上增加了共享鎖;

目前的事務(wù)執(zhí)行過程中只對于匹配到的數(shù)據(jù)行進行了鎖定,如果插入刪除語句并未涉及到該數(shù)據(jù)行就不會受到影響,但是如果涉及到這行數(shù)據(jù)那肯定需要等S鎖釋放后才能進行。

SQL Server執(zhí)行insert時使用的鎖

首先在事務(wù)中執(zhí)行insert語句并且不提交(注意將上個章節(jié)中的事務(wù)提交):

begin tran

insert into UserTable (id,code,name,createtime,lastmodifytime)
values(newid(),'test2','測試用戶2',getdate(),getdate())

insert的時候默認會有事務(wù),因此主動聲明一個事務(wù)并只執(zhí)行不提交就可以很容易的查到當(dāng)前會話持有的鎖。

通過dm_tran_locks查詢到該語句目前持有的鎖:

request_session_idresource_typerequest_statusrequest_moderesource_descriptionobjectName
70DATABASEGRANTS Test
70PAGEGRANTIX1:280UserTable
70OBJECTGRANTIX UserTable
70KEYGRANTX(c75ad92ba798)UserTable

該事務(wù)持有的鎖:

  • 數(shù)據(jù)庫層面的共享鎖;
  • 數(shù)據(jù)頁上的意向排他鎖;
  • 數(shù)據(jù)表的意向排他鎖;
  • 數(shù)據(jù)行的排他鎖;

結(jié)合上文中對于鎖類型的講解可以很容易理解數(shù)據(jù)庫增加這些鎖的用意。數(shù)據(jù)庫層面增加S鎖可以保護當(dāng)前正在進行的事務(wù)的安全,同時針對發(fā)生數(shù)據(jù)變化的數(shù)據(jù)頁和數(shù)據(jù)表增加意向排他鎖可以防止其他事務(wù)對于數(shù)據(jù)庫和數(shù)據(jù)頁進行更高層的修改(比如架構(gòu)級別或者DDL之類的事務(wù)),IX鎖對于IX和IS是可以并存的,因此可以最大限度上支持同一個區(qū)域內(nèi)的其他修改和查詢事務(wù)。

SQL Server執(zhí)行update時使用的鎖

首先在數(shù)據(jù)庫中執(zhí)行update語句而不提交(注意將上個章節(jié)中的事務(wù)提交或者回滾):

begin tran 
update UserTable set lastmodifytime=GETDATE()  where id ='06757850-68D6-416C-B3D1-FD3B29BAD4BB'

通過dm_tran_locks查詢到該語句目前持有的鎖:

request_session_idresource_typerequest_statusrequest_moderesource_descriptionobjectName
52DATABASEGRANTS Test
52PAGEGRANTIX1:280UserTable
52OBJECTGRANTIX UserTable
52KEYGRANTX(ead909dc80bf)UserTable

該事務(wù)持有的鎖:

  • 數(shù)據(jù)庫層面的共享鎖;
  • 數(shù)據(jù)頁上的意向排他鎖;
  • 數(shù)據(jù)表上面的意向排他鎖;
  • 數(shù)據(jù)行的排他鎖;

有了insert的經(jīng)驗后,理解update語句使用的鎖難度就不大了。其與insert使用的鎖的類型基本一樣,由于本次是使用主鍵進行修改,數(shù)據(jù)庫可以直接定位到需要進行變更的數(shù)據(jù)行,因此只需要在對應(yīng)的行上增加X鎖就可以滿足事務(wù)的需要。

日常使用的時候很少直接通過id更新數(shù)據(jù),往往基于一些非聚集索引更新數(shù)據(jù),在這種情況下數(shù)據(jù)庫對于鎖的使用會有什么不一樣呢?首先針對測試的數(shù)據(jù)表增加兩個索引:

create nonclustered index idx_UserTable_Name on UserTable(name)
create nonclustered index idx_UserTable_LastModifyTime on UserTable(lastmodifytime)

然后將update語句修改為根據(jù)name更新數(shù)據(jù):

begin tran 
set statistics profile on 
update UserTable set lastmodifytime=GETDATE()  where name like '%test%'

該語句對應(yīng)的鎖的情況統(tǒng)計:

request_session_idresource_typerequest_statusrequest_moderesource_descriptionobjectName
52DATABASEGRANTS Test
52PAGEGRANTIX1:280UserTable
52PAGEGRANTIX1:368UserTable
52KEYGRANTX(ba4eae1b81ad)UserTable
52KEYGRANTX(500c265deab6)UserTable
52KEYGRANTX(a1a185fdb4ae)UserTable
52OBJECTGRANTIX UserTable
52KEYGRANTX(ff4928fe375a)UserTable
52KEYGRANTX(0ee48b5e6942)UserTable

可以發(fā)現(xiàn)通過非聚集索引更新數(shù)據(jù)的時候,數(shù)據(jù)庫需要檢查的內(nèi)容明顯增加,并且增加IX鎖的數(shù)據(jù)也多了不少。只看這個表格可能不太好理解,這些key對應(yīng)的X鎖為什么要增加,以及是使用的哪個索引呢?

為了了解更多的信息,上文中查詢事務(wù)鎖的語句需要進行一些改動,增加對于索引的關(guān)聯(lián)查詢:

with indexs 
as (
SELECT  索引名稱 = a.name ,
        表名 = c.name ,
        索引字段名 = d.name ,
        a.indid
FROM    sysindexes a
        JOIN sysindexkeys b ON a.id = b.id
                               AND a.indid = b.indid
        JOIN sysobjects c ON b.id = c.id
        JOIN syscolumns d ON b.id = d.id
                             AND b.colid = d.colid
WHERE   a.indid NOT IN ( 0, 255 )  
AND   c.name='UserTable' --查指定表 
)
select request_session_id,resource_type,request_status,request_mode,resource_description,
case resource_type
when 'Page' then OBJECT_NAME(p.object_id)
when 'object' then OBJECT_NAME(lock.resource_associated_entity_id)
when 'database' then (select name from master..SysDatabases where dbid=resource_database_id)
when 'key' then object_name(p.object_id)
end 
as objectName,index_id,i.索引名稱 from sys.dm_tran_locks lock
left join sys.partitions p on p.hobt_id=lock.resource_associated_entity_id
left join indexs  i on i.indid=index_id
order by lock.request_session_id

通過關(guān)聯(lián)查詢索引信息,得到了更豐富的內(nèi)容:

request_session_idresource_typerequest_statusrequest_moderesource_descriptionobjectNameindex_id索引名稱
52DATABASEGRANTS TestNULLNULL
52PAGEGRANTIX1:280UserTable1PK__Test1__3213E83F133024F3
52PAGEGRANTIX1:368UserTable4idx_UserTable_LastModifyTime
52KEYGRANTX(ba4eae1b81ad)UserTable4idx_UserTable_LastModifyTime
52KEYGRANTX(500c265deab6)UserTable4idx_UserTable_LastModifyTime
52KEYGRANTX(a1a185fdb4ae)UserTable1PK__Test1__3213E83F133024F3
52OBJECTGRANTIX UserTableNULLNULL
52KEYGRANTX(ff4928fe375a)UserTable4idx_UserTable_LastModifyTime
52KEYGRANTX(0ee48b5e6942)UserTable1PK__Test1__3213E83F133024F3
52KEYGRANTX(150ba0b85c41)UserTable4idx_UserTable_LastModifyTime

從上表中可以看出在更新數(shù)據(jù)的時候,由于涉及到多行的非聚集索引上面的數(shù)據(jù),因此對于該索引涉及到的數(shù)據(jù)行都增加了X鎖,涉及到的數(shù)據(jù)頁也比之前更多了。類型為X鎖,同時索引名稱為PK__Test1__3213E83F133024F3的有兩行,因為本次事務(wù)匹配到了兩行數(shù)據(jù);類型為X鎖,同時索引名稱為idx_UserTable_LastModifyTime的一共有四行。為什么是四行呢?因為有兩個舊的數(shù)據(jù)需要刪除,同時新增了兩個新的數(shù)據(jù),所以是四行。其他的非聚集索引的數(shù)據(jù)并沒有修改,所以本次不需要申請X鎖。

總結(jié)

數(shù)據(jù)庫中的各種事務(wù)隔離級別都是通過對于不同鎖的綜合運用實現(xiàn)的。對于鎖的認識可以從兩個角度進行:鎖模式和鎖對象。哪怕是一個簡單的select語句都會有默認的某種鎖以保護數(shù)據(jù)的正確性。需要注意不同的數(shù)據(jù)組合情況、不同的事務(wù)隔離級別下SQL語句的執(zhí)行過程可能是不一樣的,因此其使用的鎖也會千變?nèi)f化,本文所列舉的只是一些很簡單的情況,但是規(guī)則類似,分析路徑也是基本一致的,有興趣的可以自己嘗試下日常工作中語句的執(zhí)行過程中使用的鎖,這對于理解數(shù)據(jù)庫工作原理,有針對性的對于SQL語句調(diào)優(yōu)都有一定幫助(注意不要在生產(chǎn)環(huán)境執(zhí)行這類分析)。

到此這篇關(guān)于一文分析SQL Server中事務(wù)使用的鎖的文章就介紹到這了,更多相關(guān)SQL Server事務(wù)鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解析mysql中如何獲得數(shù)據(jù)庫的大小

    解析mysql中如何獲得數(shù)據(jù)庫的大小

    本篇文章是對mysql中如何獲得數(shù)據(jù)庫的大小的解決方法進行了詳細的分析介紹,需要的朋友參考下
    2013-06-06
  • mysql中的四大運算符種類實例匯總(20多項)?

    mysql中的四大運算符種類實例匯總(20多項)?

    這篇文章主要介紹了mysql中的四大運算符種類匯總,運算符連接表達式中的各個操作數(shù),他的作用是用來指明對數(shù)據(jù)表中的操作數(shù)所進行的運算
    2022-07-07
  • Mysql精粹系列(精粹)

    Mysql精粹系列(精粹)

    本文都是小編日常整理的mysql精粹內(nèi)容,需要大家熟練掌握并記憶的知識,非常不錯,具有參考借鑒價值,對mysql知識感興趣的朋友一起看看吧
    2016-09-09
  • 詳細解讀MySQL中的權(quán)限

    詳細解讀MySQL中的權(quán)限

    這篇文章主要介紹了MySQL中的權(quán)限,包括各個權(quán)限所能操作的事務(wù)以及操作權(quán)限的一些常用命令語句,需要的朋友可以參考下
    2015-05-05
  • mysql高效查詢left join和group by(加索引)

    mysql高效查詢left join和group by(加索引)

    這篇文章主要給大家介紹了關(guān)于mysql高效查詢left join和group by,這個的前提是加了索引,以及如何在MySQL高效的join3個表 的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • MySQL5.7不停業(yè)務(wù)將傳統(tǒng)復(fù)制變更為GTID復(fù)制的實例

    MySQL5.7不停業(yè)務(wù)將傳統(tǒng)復(fù)制變更為GTID復(fù)制的實例

    下面小編就為大家?guī)硪黄狹ySQL5.7不停業(yè)務(wù)將傳統(tǒng)復(fù)制變更為GTID復(fù)制的實例。小編覺的挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • 淺談Mysql哪些字段適合建立索引

    淺談Mysql哪些字段適合建立索引

    這篇文章主要介紹了淺談Mysql哪些字段適合建立索引,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 查看連接mysql的IP地址的實例方法

    查看連接mysql的IP地址的實例方法

    在本篇文章里小編給大家分享的是一篇關(guān)于查看連接mysql的IP地址的實例方法,有需要的朋友們可以參考下。
    2020-10-10
  • MySQL(基于GTID方式)實現(xiàn)主從復(fù)制和單主復(fù)制詳細教程

    MySQL(基于GTID方式)實現(xiàn)主從復(fù)制和單主復(fù)制詳細教程

    在分布式數(shù)據(jù)庫系統(tǒng)中,主從復(fù)制是實現(xiàn)高可用性和數(shù)據(jù)冗余的重要手段,基于GTID的復(fù)制模式可以提供更強的復(fù)制一致性和簡化故障轉(zhuǎn)移過程,本文將詳細介紹如何配置單主復(fù)制的GTID模式,以便在MySQL數(shù)據(jù)庫中實現(xiàn)穩(wěn)定可靠的數(shù)據(jù)復(fù)制,需要的朋友可以參考下
    2024-07-07
  • 解決MySQL 5.7.9版本sql_mode=only_full_group_by問題

    解決MySQL 5.7.9版本sql_mode=only_full_group_by問題

    這篇文章主要介紹了解決MySQL 5.7.9版本sql_mode=only_full_group_by問題,需要的朋友可以參考下
    2017-05-05

最新評論