版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第11章多版本數(shù)據(jù)原理除了 read uncommitted隔離級(jí)別,在 SQL Server 2000版本的其他隔離級(jí)別都會(huì)發(fā)生讀 寫(xiě)操作相互等待的情況,使數(shù)據(jù)庫(kù)運(yùn)行效率大幅降低。為了解決這種問(wèn)題,從SQL Server2005版本開(kāi)始,引入了多版本數(shù)據(jù)技術(shù),在一個(gè)事務(wù)中修改表中的數(shù)據(jù)時(shí)(主要指對(duì)表執(zhí)行update或delete操作),會(huì)把舊版本的數(shù)據(jù)臨時(shí)存入tempdb數(shù)據(jù)庫(kù),此事務(wù)結(jié)束之前,其他連接的讀操作可以由tempdb數(shù)據(jù)庫(kù)讀取這些臨時(shí)數(shù)據(jù),而不是從原數(shù)據(jù)庫(kù)讀取,從而使得 讀寫(xiě)操作不再相互等待。本章內(nèi)容主要包括:數(shù)據(jù)庫(kù)開(kāi)啟read_committed_snapshot參數(shù)后產(chǎn)生的多
2、版本數(shù)據(jù) 數(shù)據(jù)庫(kù)開(kāi)啟allow_snapshot_isolation參數(shù)后產(chǎn)生的多版本數(shù)據(jù)11.1開(kāi)啟read_committed_snapshot 參數(shù)后產(chǎn)生的多版本數(shù)據(jù)開(kāi)啟read_committed_snapshot參數(shù)后,新添加到表中的記錄都會(huì)在行數(shù)據(jù)最后附加14字節(jié)的版本信息數(shù)據(jù),用于指向記錄更新后產(chǎn)生的舊版本數(shù)據(jù),這些舊版本數(shù)據(jù)存儲(chǔ)于tempdb數(shù)據(jù)庫(kù),開(kāi)啟 read_committed_snapshot參數(shù)之前已存在的記錄會(huì)在其被執(zhí)行update操作時(shí)附加14字節(jié)的版本信息。參數(shù)開(kāi)啟前后行數(shù)據(jù)存儲(chǔ)方式的變化創(chuàng)建測(cè)試數(shù)據(jù)庫(kù)testRowVersion ,并在其 中創(chuàng)建測(cè)試表t,數(shù)據(jù)
3、庫(kù)的 read_committed_snapshot 參數(shù)默認(rèn)未開(kāi)啟。1> create database testRowVersion2> go在testRowVersion數(shù)據(jù)庫(kù)中創(chuàng)建測(cè)試表t,并添加一行測(cè)試記錄。1> use testRowVersion2> create table t(a int identity, b char(5) default 'xxxxx')3> go在數(shù)據(jù)庫(kù)的read_committed_snapshot參數(shù)開(kāi)啟前后,對(duì) t表各添加一行記錄。1> insert into t default values2
4、> alter database testRowVersion set read_committed_snapshot on3> insert into t default values4> got分配到的數(shù)據(jù)頁(yè)。為了查看t表的兩行記錄在數(shù)據(jù)頁(yè)中的存儲(chǔ)形式,先查看表1> dbcc ind(testRowVersion,t,-1)2> goPageFID PagePIDIAMFID IAMPIDObjectID IndexID177 NULLNULL 2105058535015517721050585350先使用參數(shù)2執(zhí)行dbcc page命令,導(dǎo)出55號(hào)數(shù)據(jù)頁(yè)內(nèi)容
5、,以下導(dǎo)出內(nèi)容中的粗體部分 即是表t的兩行記錄對(duì)應(yīng)的十六進(jìn)制數(shù)據(jù)。1> dbcc traceon(3604)2> dbcc page(testRowVersion,1,55,2)3> go3C16C050:00000000 00000000 00000000 00000000 ?3C16C060:10000d00 01000000 7878787878020000?xxxxx.3C16C070:50000d00 02000000 7878787878020000?P.xxxxx.3C16C080:00000000 00000000 5101000000000000?Q.3C1
6、6DFF0:e00f2e01 0e01e400 0010b800 70006000 ?p.'.OFFSET TABLE:Row - Offset1 (0x1) - 112 (0x70)再使用參數(shù)3執(zhí)行dbcc page命令導(dǎo)出55號(hào)數(shù)據(jù)頁(yè)內(nèi)容,可以更清楚地看出兩行記錄的 差別。1> dbcc page(testRowVersion,1,55,3)2> goSlot 0 Offset 0x60 Length 16Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPRecordSize = 16Memory Du
7、mp 0x3D4EC06000000000:10000d00 01000000 78787878 78020000?xxxxx.Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4a = 1Slot 0 Column 2 Offset 0x8 Length 5 Length (physical) 5b = xxxxxSlot 1 Offset 0x70 Length 30Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPVERSIONING_INFORecord Siz
8、e = 30Memory Dump 0x3D4EC07000000000:50000d00 02000000 78787878 78020000 ?P.xxxxx.00000010:00000000 00000000 51010000 0000?Q.Version Information =Transaction Timestamp: 337Version Pointer: NullSlot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4a = 2Slot 1 Column 2 Offset 0x8 Length 5 Length (phy
9、sical) 5b = xxxxx由以上導(dǎo)出數(shù)據(jù)可以看出兩行記錄存儲(chǔ)方式的差異:第1行記錄的行頭數(shù)據(jù)第 1個(gè)字節(jié)為0x10,其二進(jìn)制數(shù)據(jù)為:0001 0000。 第2行記錄的行頭數(shù)據(jù)第 1個(gè)字節(jié)為0x50,其二進(jìn)制數(shù)據(jù)為:0101 0000。 第2行記錄附加了 14字節(jié)的版本信息。版本信息前8個(gè)字節(jié)表示對(duì)應(yīng)的舊版本數(shù)據(jù)在 tempdb數(shù)據(jù)庫(kù)中的RowID,后6個(gè)字節(jié) 表示修改記錄操作所在事務(wù)的序號(hào)。因?yàn)楫?dāng)前還未產(chǎn)生舊版本數(shù)據(jù),前8個(gè)字節(jié)都為0。版本信息各部分的含義請(qǐng)參考 節(jié)內(nèi)容。11.1.2 update產(chǎn)生的舊版本數(shù)據(jù)及版本信息t表的第1為了觀察到update產(chǎn)生的版本信息數(shù)據(jù),下面開(kāi)始一個(gè)
10、事務(wù),并在其中更新 行記錄。1> begin tran2> update t set b='aaaaa' where a=13> go重新導(dǎo)出55號(hào)數(shù)據(jù)頁(yè),查看其第1行記錄存儲(chǔ)形式的變化。1> dbcc page(testRowVersion,1,55,2)2> go3C16C050:00000000 00000000 00000000 00000000 ?3C16C060:10000d00 01000000 78787878 78020000 ?xxxxx.3C16C070:50000d00 02000000 78787878 78020000
11、?P.xxxxx.3C16C090:OdOOOlOO 00006161 61616102 OOOOcOOO?aaaaa3C16C0A0:3C16DFF0:00000100 00008701 00000000 00005f00 ?e00f2e01 0e01e400 0010b800 70008e00 ?OFFSET TABLE:Row - Offset1 (0x1) - 112 (0x70)0 (0x0) - 142 (0x8e)可以看到,更新后的記錄數(shù)據(jù)被重新添加到數(shù)據(jù)頁(yè)的空閑區(qū)域,同時(shí)修改了slotO的偏移量數(shù)值,即第1行記錄的偏移量數(shù)據(jù)指向更新后的數(shù)據(jù)所存儲(chǔ)的位置,而不是在原數(shù)據(jù)基礎(chǔ)上修改
12、。再使用參數(shù)3導(dǎo)出55號(hào)數(shù)據(jù)頁(yè),可以更清楚地看到第1行記錄被更新后,其存儲(chǔ)格式的變化。1> dbcc page(testRowVersion,1,55,3)2> goSlot 0 Offset 0x8e Length 30Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPVERSIONING_INFORecord Size = 30Memory Dump 0x3D4EC08E00000000:50000d00 01000000 61616161 61020000 ?P.aaaaa.00000010:cOOOOOOO
13、 01000000 87010000 0000?Version Information =Transaction Timestamp: 391Version Pointer: (file 1 page 192 currentSlotld 0)由上面導(dǎo)出數(shù)據(jù)的最后部分可以得知,舊版本數(shù)據(jù)在tempdb數(shù)據(jù)庫(kù)的地址為(1:192:0)。14字節(jié)版本數(shù)據(jù)的前 8個(gè)字節(jié)表示舊版本記錄在tempdb數(shù)據(jù)庫(kù)中的RowID,后面4個(gè)字節(jié)表示修改記錄所在的事務(wù)的序號(hào),其各部分含義可以分解如下。表11-1版本數(shù)據(jù)的各部分含義原十六進(jìn)制數(shù)據(jù)轉(zhuǎn)換前后順序十進(jìn)制數(shù)據(jù)長(zhǎng)度表示意義c0 00 00 000xc01924B
14、舊版本記錄所在數(shù)據(jù)頁(yè)01 000x112B舊版本記錄所在文件號(hào)00 000x002B舊版本記錄slot序號(hào)87 01 00 00 00 000x1873916B修改操作所在事務(wù)序號(hào)導(dǎo)出tempdb數(shù)據(jù)庫(kù)的192號(hào)數(shù)據(jù)頁(yè),查看其中的舊版本數(shù)據(jù)。1> dbcc page(tempdb,1,192,2)2> go3D64C050:00000000 00000000 00000000 00000000 ?3D64C060:26010055 00001976 3d702d5d 01870100 ?&.U.v=p-.3D64C070:00000000 00010000 00000000
15、 00050000 ?3D64C080:05000000 0000000d 00000000 010d0000 ?3D64C090:00000000 00941976 3dfe2c5d 01000000 ?.v=.,.3D64C0A0:00000000 00 10000d 00010000 00787878?xxx3D64C0B0:3D64C0C0:78780200 00 000000 00000000 00000000 ?xx00000000 00000000 00000000 00000000 ?OFFSET TABLE:Row - Offset0 (0x0) - 96 (0x60)可以發(fā)
16、現(xiàn),上面粗體部分是表t第1行記錄在修改之前在(1:55)號(hào)數(shù)據(jù)頁(yè)中存儲(chǔ)的數(shù)據(jù), 從偏移量3D64C060至3D64C0A4為此舊版本數(shù)據(jù)的行頭系統(tǒng)信息。也可以查詢(xún)動(dòng)態(tài)系統(tǒng)視圖sys.dm_tran_version_store得到tempdb數(shù)據(jù)庫(kù)中的當(dāng)前多版本數(shù)據(jù)信息。1> select transaction_sequence_num, database_id, record_image_first_part2> from sys.dm_tran_version_store3> gotransaction_sequence_num database_id record_im
17、age_first_part以上各種數(shù)據(jù)之間的關(guān)系可以用下圖表示。testRowVersion 數(shù)據(jù)庫(kù)tempdb數(shù)據(jù)庫(kù)記錄原數(shù)據(jù)更新為移入更新后的行數(shù)據(jù) 舊版本數(shù)據(jù)指針指向啟動(dòng)另外一個(gè)連接,在其中查詢(xún)t表數(shù)據(jù),可以發(fā)現(xiàn)此時(shí)不再發(fā)生等待,而查到的結(jié)果恰是存儲(chǔ)在tempdb數(shù)據(jù)庫(kù)中的舊版本數(shù)據(jù)。1> use testRowVersion2> go1> select * from t2> goab1 xxxxx2 xxxxx把第1個(gè)連接中的事務(wù)提交后,表t的第1行記錄的存儲(chǔ)形式并未發(fā)生變化。1> commit2> go1> dbcc page(testRo
18、wVersion,1,55,3)2> goSlot 0 Offset 0x8e Length 30Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPVERSIONING_INFORecord Size = 30Memory Dump 0x3D64C08E00000000:50000d00 01000000 61616161 61020000 ?P.aaaaa.00000010:c0000000 01000000 87010000 0000?Version Information =Transaction Timestam
19、p: 391Version Pointer: (file 1 page 192 currentSlotId 0)但tempdb數(shù)據(jù)庫(kù)中的舊版本數(shù)據(jù)已經(jīng)失效,如果此時(shí)查詢(xún)tempdb數(shù)據(jù)庫(kù)中的舊版本數(shù)據(jù),可以看到,這時(shí)不再有結(jié)果出現(xiàn)。1> select transaction_sequence_num, database_id, record_image_first_part2> from sys.dm_tran_version_store3> gotransaction_sequence_num database_id record_image_first_part(0行受影
20、響)而在連接2中重新查詢(xún)t表的數(shù)據(jù),得到的是提交后的結(jié)果。1> select * from t2> goab1 aaaaa2 xxxxx11.1.3 delete操作產(chǎn)生的舊版本數(shù)據(jù)及版本信息數(shù)據(jù)delete操作產(chǎn)生的舊版在testRowVersion數(shù)據(jù)庫(kù)中重建t表,添加2行記錄,用于測(cè)試 本數(shù)據(jù)。1> drop table t2> create table t(a int identity, b char(5) default 'xxxxx')3> go1> insert into t default values2> go 2查看
21、t表分配到的數(shù)據(jù)頁(yè)。1> dbcc ind(testRowVersion,t,-1)2> goPageFID PagePIDIAMFID IAMPIDObjectIDIndexID78 NULLNULL21575115777821575115以參數(shù)2執(zhí)行dbcc page命令導(dǎo)出77號(hào)數(shù)據(jù)頁(yè),查看t表的2行記錄存儲(chǔ)的初始狀態(tài)。1> dbcc traceon(3604)2> dbcc page(testRowVersion,1,77,2)3> go3D7AC050:00000000 00000000 00000000 00000000 ?3D7AC060:50000
22、d00 01000000 78787878 78020000?Pxxxxx.3D7AC070:00000000 000000004c010000 00005000?L.P.3D7AC080:0d000200 00007878 78787802 00000000?xxxxx3D7AC090:00000000 00004d01 0000000000000000?M3D7AC0A0:00000000 00000000 00000000 00000000 ?3D7ADFE0:00000000 00000000 00000000 00000000 ?3D7ADFF0:00000000 00000000
23、21212121 7e006000 ?!.'OFFSET TABLE:Row - Offset1 (0x1) - 126 (0x7e)0 (0x0) - 96 (0x60)再以參數(shù)3執(zhí)行dbcc page命令導(dǎo)出77號(hào)數(shù)據(jù)頁(yè)數(shù)據(jù)。1> dbcc page(testRowVersion,1,77,3)2> goSlot 0 Offset 0x60 Length 30Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPVERSIONING_INFORecord Size = 30Memory Dump 0x3D6
24、AC06000000000:50000d00 01000000 78787878 78020000 ?P.xxxxx.00000010:00000000 00000000 4c010000 0000?L.Version Information =Transaction Timestamp: 332Version Pointer: NullSlot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4a = 1Slot 0 Column 2 Offset 0x8 Length 5 Length (physical) 5b = xxxxxSlot 1
25、 Offset 0x7e Length 30Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPVERSIONING_INFORecord Size = 30Memory Dump 0x3D6AC07E00000000:50000d00 02000000 78787878 78020000 ?P.xxxxx.00000010:00000000 00000000 4d010000 0000?M.Version Information =Transaction Timestamp: 333Version Pointer: NullS
26、lot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4a = 2Slot 1 Column 2 Offset 0x8 Length 5 Length (physical) 5b = xxxxx可以看到,行數(shù)據(jù)中已經(jīng)包含了版本信息數(shù)據(jù),因?yàn)楫?dāng)前還未產(chǎn)生舊版本數(shù)據(jù),其版本指針為空。開(kāi)始一個(gè)事務(wù),在其中刪除 t表的第2行記錄。1> begin tran2> delete from t where a=23> go以參數(shù)3執(zhí)行dbcc page命令,重新導(dǎo)出77號(hào)數(shù)據(jù)頁(yè)數(shù)據(jù),可以看到第2行記錄后面出現(xiàn)了版本數(shù)據(jù)。1> dbc
27、c page(testRowVersion,1,77,3)2> goSlot 0 Offset 0x60 Length 30Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPVERSIONING_INFORecord Size = 30Memory Dump 0x3D9AC06000000000:50000d00 01000000 78787878 78020000 ?P.xxxxx.00000010:00000000 00000000 4c010000 0000?L.Version Information =Trans
28、action Timestamp: 332Version Pointer: NullSlot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4a = 1Slot 0 Column 2 Offset 0x8 Length 5 Length (physical) 5b = xxxxxSlot 1 Offset 0x9c Length 15Record Type = GHOST_VERSION_RECORDRecord Attributes = VERSIONING_INFORecord Size = 15Memory Dump 0x3D9AC09
29、C00000000:4eb80000 00010000 007d0100 000000?N.Version Information =Transaction Timestamp: 381Version Pointer: (file 1 page 184 currentSlotId 0)DBCC執(zhí)行完畢。如果 DBCC輸出了錯(cuò)誤信息,請(qǐng)與系統(tǒng)管理員聯(lián)系。如果使用參數(shù)2執(zhí)行dbcc page命令,由最后的偏移量列表數(shù)據(jù),可以看到這個(gè)未提交 的delete操作把舊版本數(shù)據(jù)的信息加入了數(shù)據(jù)頁(yè)的空閑空間作為表t的第2行記錄,但是其中的數(shù)據(jù)并不包含行數(shù)據(jù),在偏移量列表中未標(biāo)記原數(shù)據(jù),即原數(shù)據(jù)相當(dāng)于被刪除了
30、。1> dbcc page(testRowVersion,1,77,2)13 / 303C2FC050:00000000 00000000 00000000 00000000 ?3C2FC060:50000d00 01000000 78787878 78020000 ?P.xxxxx.3C2FC070:00000000 00000000 4c010000 00005000 ?L.P.3C2FC080:0d000200 00007878 78787802 00000000 ?xxxxx.3C2FC090:00000000 00004d01 000000004eb80000 ?M.N.3C2
31、FC0A0:00010000 007d0100 00000000 00000000 ?.3C2FC0B0:00000000 00000000 00000000 00000000 ?3C2FDFE0:00000000 00000000 00000000 00000000 ?3C2FDFF0:00000000 00000000 21212121 9c006000 ?!.'.OFFSET TABLE:Row - Offset1 (0x1) - 156 (0x9c)0 (0x0) - 96 (0x60)查詢(xún)sys.dm_tran_version_store動(dòng)態(tài)視圖,觀察存儲(chǔ)在tempdb數(shù)據(jù)庫(kù)
32、中的舊版本數(shù)據(jù)。1> select transaction_sequence_num as tran_seq_num.2>database_id as db_id,3>record_image_first_part as rec_1st_part4> from sys.dm_tran_version_store5> gotran_seq_num db_id rec_1st_part3810x50000D0002000000787878787802000000000000000000004D0100000000這里的查詢(xún)結(jié)果恰是表 t的第2行記錄刪除之前在數(shù)據(jù)頁(yè)中對(duì)
33、應(yīng)的數(shù)據(jù)。 查看tempdb數(shù)據(jù)的184號(hào)數(shù)據(jù)頁(yè),可以看到舊版本數(shù)據(jù)存儲(chǔ)的狀態(tài)。1> dbcc page(tempdb,1,184,2)2> go3D9AC050:00000000 00000000 00000000 00000000 ?.3D9AC060:26010063 00001e5a 0100052f 3d7d0100 ?&.c.Z/=.3D9AC070:00000000 00010000 00000000 00050095 ?.3D9AC080:05020000 0000000f 00000000 010d0000 ?.3D9AC090:00bc901f 0580
34、ff03 00800000 00000000 ?3D9AC0A0:00000000 00 50000d 00020000 00787878?.p.xxx3D9AC0B0:78780200 00000000 00000000 004d0100?xx.M.3D9AC0C0:000000 00 8088af05 68ce0100 01000000 ?.h.3D9ADFF0:01000000 a80f0000 4090b205 00006000 ?.'.OFFSET TABLE:Row - Offset0 (0x0) - 96 (0x60)如果回滾以上刪除記錄的操作,則可以看到SQL Serv
35、er把刪除的記錄又重新加入了數(shù)據(jù)頁(yè),并且是在數(shù)據(jù)頁(yè)的空閑空間區(qū)域中加入。1> dbcc page(testRowVersion,1,77,2)2> go3D7AC050:00000000 00000000 00000000 00000000 ?3D7AC060:50000d00 01000000 78787878 78020000 ?P.xxxxx.3D7AC070:00000000 00000000 4c010000 00005000 ?L.P.3D7AC080:0d000200 00007878 78787802 00000000 ?xxxxx3D7AC090:00000000
36、 00004d01 00000000 4eb80000 ?M.N.3D7AC0A0:00010000 007d0100 00000050 000d0002 ?.P.3D7AC0B0:00000078 78787878 02000000 00000000 ?.xxxxx3D7AC0C0:0000004d 01000000 00000000 00000000 ?.M3D7ADFF0:00000000 00000000 21212121 ab006000 ?!.'.OFFSET TABLE:Row - Offset1 (0x1) - 171 (0xab)0 (0x0) - 96 (0x60)
37、注意:這里重新加入的舊版本數(shù)據(jù)來(lái)自于重做日志文件,而不是本數(shù)據(jù)。如果把delete操作提交,SQL Server會(huì)如何處理呢?重新創(chuàng)建表 錄。1> drop table ttempdb中存儲(chǔ)的舊版t,并添加2行測(cè)試記2> create table t(a int identity, b char(5) default 'xxxxx')3> go1> insert into t default values2> go 21> dbcc ind(testRowVersion,t,-1)2> goPageFID PagePIDIAMFID I
38、AMPIDObjectID IndexID78 NULLNULL 535752297717853575229以參數(shù)2執(zhí)行dbcc page命令,導(dǎo)出77號(hào)數(shù)據(jù)頁(yè),查看表t的兩行記錄的初始存儲(chǔ)狀態(tài)。1> dbcc traceon(3604)2> dbcc page(testRowVersion,1,77,2)3> go3D3BC050:00000000 00000000 00000000 00000000 ?3D3BC060:50000d00 01000000 78787878 78020000?Pxxxxx.3D3BC070:00000000 00000000 ab03000
39、0 00005000?P3D3BC080:0d000200 00007878 78787802 00000000?xxxxx3D3BC090:00000000 0000ac03 0000000000000000 ?3D3BC0A0:00010000 007d0100 00000050 000d0002 ?.P.3D3BDFF0:00000000 00000000 21212121 7e006000 ?!.'.OFFSET TABLE:Row - Offset1 (0x1) - 126 (0x7e)0 (0x0) - 96 (0x60)如果最后執(zhí)行提交,則SQL Server只是把slo
40、t 1的偏移量設(shè)置為0,詳細(xì)信息請(qǐng)參考第7章內(nèi)容。1> begin tran2> delete from t where a=23> go1> commit2> go1> dbcc page(testRowVersion,1,77,2)2> go3C2FDFF0:00000000 00000000 21212121 00006000 ?!.'.OFFSET TABLE:Row - Offset1 (0x1)-0(0x0)0 (0x0) - 96 (0x60)11.2開(kāi)啟allow_snapshot_isolation參數(shù)產(chǎn)生的的多版本數(shù)據(jù)從SQ
41、L Server 2005版本開(kāi)始,新加入了snapshot隔離級(jí)別,同時(shí)數(shù)據(jù)庫(kù)增加了allow_s napshot_isolation選項(xiàng)參數(shù)。若要在連接中設(shè)置snap shot隔離級(jí),需要數(shù)據(jù)庫(kù)開(kāi)啟allow_snapshot_isolation 參數(shù)。設(shè)置snapshot隔離級(jí)別后,在此連接的事務(wù)中執(zhí)行的查詢(xún)只能查到這個(gè)事務(wù)開(kāi)始之前 已經(jīng)提交的數(shù)據(jù),同時(shí)允許其他連接修改這個(gè)事務(wù)中所查詢(xún)的數(shù)據(jù),而不會(huì)像serializable隔離級(jí)別那樣,在事務(wù)中查到的數(shù)據(jù)甚至所查詢(xún)的表不允許其他連接修改,而只能等待查詢(xún)所在的事務(wù)完成后再進(jìn)行。即開(kāi)啟數(shù)據(jù)庫(kù)的allow_snapshot_isolation
42、參數(shù)厚,在snapshot隔離級(jí)別下,不會(huì)再有寫(xiě)等待讀的情況發(fā)生,這其中起作用的關(guān)鍵是多版本數(shù)據(jù),也就是對(duì)應(yīng)一行記錄會(huì)有不同版本的多份數(shù)據(jù)存在。多版本數(shù)據(jù)產(chǎn)生的過(guò)程假定數(shù)據(jù)庫(kù)已經(jīng)開(kāi)啟了allow_snapshot_isolation參數(shù),而且對(duì)數(shù)據(jù)庫(kù)啟動(dòng)了A、B、C三個(gè)連接,下面先說(shuō)明多版本數(shù)據(jù)產(chǎn)生的過(guò)程,具體實(shí)驗(yàn)過(guò)程請(qǐng)參看后續(xù)部分。1)連接A設(shè)置為snap shot隔離級(jí)別。2)在連接A中開(kāi)始一個(gè)事務(wù)并執(zhí)行了一次查詢(xún)query_A,為了方便敘述,假定其查詢(xún)結(jié)果為一行,用row_A表示,row_A存儲(chǔ)在數(shù)據(jù)頁(yè)page_A中。3)連接B對(duì)row_A進(jìn)行了修改,修改結(jié)果為row_B, row_B保
43、存在數(shù)據(jù)頁(yè) page_A中,而row_A會(huì)被作為舊版本數(shù)據(jù)存入tempdb數(shù)據(jù)庫(kù),row_A在tempdb數(shù)據(jù)庫(kù)中的存儲(chǔ)地址作為其版本數(shù)據(jù)信息保存在row_B中。4)連接B在連接A中的事務(wù)結(jié)束之前提交了修改結(jié)果,即提交了修改操作所在的事務(wù)。為了保證在連接 A中再次執(zhí)行query_A時(shí),查詢(xún)結(jié)果不變,tempdb中存儲(chǔ)的 row_A要一直保留,而不能被覆蓋,這樣對(duì)于連接A中查到的一行記錄,當(dāng)前就有了兩個(gè)版本的數(shù)據(jù):一是存儲(chǔ)于tempdb數(shù)據(jù)庫(kù)中的row_A,一是存儲(chǔ)于page_A中的row_B。5)如果此時(shí)開(kāi)啟另外一個(gè)連接C,并設(shè)置為snapshot隔離級(jí)別,則此連接中的事務(wù)執(zhí)行query_A查
44、詢(xún)的結(jié)果總為 row_B。6)連接C對(duì)row_B進(jìn)行修改并提交,修改結(jié)果為row_C,row_C會(huì)保存在數(shù)據(jù)頁(yè)page_A中,row_B則會(huì)存入tempdb數(shù)據(jù)庫(kù),row_B在tempdb數(shù)據(jù)庫(kù)中的存儲(chǔ)地 址作為其版本數(shù)據(jù)信息保存在row_C中。7)如果此時(shí)開(kāi)啟另外一個(gè)連接繼續(xù)上述過(guò)程,對(duì)row_A可以生成更多版本的數(shù)據(jù)。對(duì)于連接 A查到的記錄,這時(shí)有了三個(gè)版本,其中最新的row_C保存在原數(shù)據(jù)庫(kù)的page_A,另外兩個(gè)舊版本的row_B、row_A保存在tempdb數(shù)據(jù)庫(kù)中,較新版本的數(shù)據(jù)同時(shí) 保存了其上一個(gè)較舊版本數(shù)據(jù)的地址。在不同時(shí)刻開(kāi)始的事務(wù)執(zhí)行相同的query_A查詢(xún),會(huì)查到這行記錄
45、的不同版本。testRowVersiontestRowVersion-二亍tempdbtestRowVersiontempdbrowC .下面我們進(jìn)行實(shí)驗(yàn)說(shuō)明多版本數(shù)據(jù)的產(chǎn)生。11.2.1 allow_s napshot_isolatio n參數(shù)開(kāi)啟前后行記錄的存儲(chǔ)方式與數(shù)據(jù)庫(kù)開(kāi)啟read_committed_snapshot 參數(shù)的效果相似, 在 allow_snapshot_isolation參數(shù)開(kāi)啟后添加的記錄會(huì)附帶14字節(jié)的版本信息,而參數(shù)開(kāi)啟之前就存在的記錄會(huì)在其被修改時(shí)附帶上版本信息。重建testRowVersion數(shù)據(jù)庫(kù)。1> drop database testRowVe
46、rsion2> create database testRowVersion3> go在testRowVersion數(shù)據(jù)庫(kù)中創(chuàng)建測(cè)試表t。1> use testRowVersion2> create table t(a int identity, b char(5) default 'xxxxx')3> go在開(kāi)啟allow_snapshot_isolation參數(shù)前后對(duì)表t各添加一行記錄。1> insert into t default values3> insert into t default values4> go查看t表
47、分配到的數(shù)據(jù)頁(yè)信息。1> dbcc ind(testRowVersion,t,-1)2> goPageFID PagePIDIAMFID IAMPIDObjectID IndexID77 NULLNULL 2105058535551772105058535由以上結(jié)果可知,t表分配到一個(gè)數(shù)據(jù)頁(yè),為(1:55)。導(dǎo)出55號(hào)數(shù)據(jù)頁(yè)內(nèi)容,查看兩行 記錄存儲(chǔ)形式的差別。1> dbcc traceon(3604)2> dbcc page(testRowVersion,1,55,2)3> go3C16C050:00000000 00000000 00000000 0000000
48、0 ?3C16C060:10000d00 01000000 78787878 78020000?xxxxx.3C16C070:50000d00 02000000 78787878 78020000?Pxxxxx.3C16C080:3C16DFF0:00000000 00000000 bb040000 00000000 ?e00f2e01 0e01e400 0010b800 70006000 ?p.'.OFFSET TABLE:Row - Offset1 (0x1) - 112 (0x70)0 (0x0) - 96 (0x60)由以上導(dǎo)出結(jié)果,可以看到這里的結(jié)果與開(kāi)啟read_commi
49、tted_snapshot參數(shù)的效果相似,第2行記錄附加了 14字節(jié)的版本信息,而第1行記錄未發(fā)生變化。使用參數(shù)3再次執(zhí)行dbcc page命令可以更清楚地看到兩行記錄的差別。1> dbcc traceon(3604)2> dbcc page(testRowVersion,1,55,3)3> goSlot 0 Offset 0x60 Length 16Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPRecordSize = 16Memory Dump 0x3D64C06000000000:10000d00
50、01000000 78787878 78020000 ?xxxxx.Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4a = 1Slot 0 Column 2 Offset 0x8 Length 5 Length (physical) 5b = xxxxxSlot 1 Offset 0x70 Length 30Record Type = PRIMARY_RECORDRecord Attributes = NULL_BITMAPVERSIONING_INFORecord Size = 30Memory Dump 0x3D64C07000
51、000010:00000000 00000000 bb040000 0000?Version Information =Transaction Timestamp: 1211Version Pointer: NullSlot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4a = 2Slot 1 Column 2 Offset 0x8 Length 5 Length (physical) 5b = xxxxx因?yàn)槲磳?duì)第2行記錄進(jìn)行過(guò)修改,此時(shí)還不存在與其對(duì)應(yīng)的舊版本數(shù)據(jù),其版本信息只包括事務(wù)序號(hào),而不包括其他舊版本數(shù)據(jù)信息。11.2.2 sn
52、apshot隔離級(jí)別下產(chǎn)生的多版本數(shù)據(jù)為了查看snapshot隔離級(jí)別下產(chǎn)生的多版本數(shù)據(jù)信息,對(duì)testRowVersion數(shù)據(jù)庫(kù)開(kāi)啟4個(gè)連接,分別標(biāo)記為 A、B、C及D。在連接A中設(shè)置snapshot隔離級(jí)別,然后開(kāi)始一個(gè)事務(wù),在其中查詢(xún)t表的第2行記錄。1> set transaction isolation level snapshot2> go1> begin tran2> select * from t where a=23> goab2 xxxxx在連接B中,對(duì)表t的第2行記錄執(zhí)行update操作,更改其b列的值為"aaaaa",然
53、后 把隔離級(jí)別設(shè)置為 snapshot,顯式開(kāi)始一個(gè)事務(wù),在其中查詢(xún)t表的第2行記錄。1> update t set b='aaaaa' where a=22> go1> set transaction isolation level snapshot2> go1> begin tran2> select * from t where a=23> goab2 aaaaa在連接C中對(duì)表t的第2行記錄執(zhí)行update操作,把其b列的值改為"bbbbb”,然后 執(zhí)行與連接B相似的過(guò)程。1> update t set b=
54、9;bbbbb' where a=22> go1> set transaction isolation level snapshot2> go1> begin tran2> select * from t where a=23> goab2 bbbbb在連接D中對(duì)表t的第2行記錄執(zhí)行update操作,把其b列的值改為"ccccc”,然后執(zhí) 行與連接B相似的過(guò)程。1> update t set b='ccccc' where a=22> go1> set transaction isolation level snapshot2> go1> begin tran2> select * from t where a=23> goab2 ccccc如果在以上4個(gè)連接中分別執(zhí)行第 2次查詢(xún),則其查詢(xún)結(jié)果與各自的第1次結(jié)果是相同的。也就是說(shuō),對(duì)應(yīng)于 t表的第2行記錄,現(xiàn)在有4份數(shù)據(jù),這4份數(shù)據(jù)包括B、C、D 三個(gè)連接對(duì)表t的第2行記錄執(zhí)行的update操作分別產(chǎn)生的一行舊版本數(shù)據(jù),以及最新的修改結(jié)果。不同的連接依照其事務(wù)開(kāi)始的不同時(shí)刻,各自查到不同的數(shù)據(jù)。重新導(dǎo)出1:55數(shù)據(jù)頁(yè)內(nèi)容,第1行記錄對(duì)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年考古發(fā)掘項(xiàng)目土方清理與保護(hù)合同3篇
- 2025版信息安全保密協(xié)議合同5篇
- 二零二五年房地產(chǎn)項(xiàng)目配套基礎(chǔ)設(shè)施建設(shè)合同3篇
- 二零二五年度智能交通管理系統(tǒng)免責(zé)協(xié)議范本4篇
- 2025版鋁材回收利用項(xiàng)目合作協(xié)議4篇
- 2025年度殘疾人勞動(dòng)合同簽訂中的殘疾人權(quán)益保障與就業(yè)促進(jìn)2篇
- 2025餐飲企業(yè)員工勞動(dòng)合同15篇
- 2025年度商業(yè)廣場(chǎng)墻面LED廣告屏租賃合同標(biāo)的協(xié)議4篇
- 2024食用油倉(cāng)儲(chǔ)物流服務(wù)合作合同3篇
- 標(biāo)識(shí)標(biāo)牌施工質(zhì)量保障合同(2025年度)3篇
- 2025年浙江省湖州市湖州職業(yè)技術(shù)學(xué)院招聘5人歷年高頻重點(diǎn)提升(共500題)附帶答案詳解
- ZK24600型平旋盤(pán)使用說(shuō)明書(shū)(環(huán)球)
- 城市基礎(chǔ)設(shè)施維修計(jì)劃
- 2024山西廣播電視臺(tái)招聘專(zhuān)業(yè)技術(shù)崗位編制人員20人歷年高頻500題難、易錯(cuò)點(diǎn)模擬試題附帶答案詳解
- 新材料行業(yè)系列深度報(bào)告一:新材料行業(yè)研究框架
- 人教版小學(xué)英語(yǔ)各冊(cè)單詞表(帶英標(biāo))
- 廣東省潮州市潮安區(qū)2023-2024學(xué)年六年級(jí)上學(xué)期期末考試數(shù)學(xué)試題
- 鄉(xiāng)村治理中正式制度與非正式制度的關(guān)系解析
- 智能護(hù)理:人工智能助力的醫(yī)療創(chuàng)新
- 國(guó)家中小學(xué)智慧教育平臺(tái)培訓(xùn)專(zhuān)題講座
- 5G+教育5G技術(shù)在智慧校園教育專(zhuān)網(wǎng)系統(tǒng)的應(yīng)用
評(píng)論
0/150
提交評(píng)論