多版本數(shù)據(jù)原理_第1頁
多版本數(shù)據(jù)原理_第2頁
多版本數(shù)據(jù)原理_第3頁
已閱讀5頁,還剩28頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

1、第11章多版本數(shù)據(jù)原理除了 read uncommitted隔離級別,在 SQL Server 2000版本的其他隔離級別都會發(fā)生讀 寫操作相互等待的情況,使數(shù)據(jù)庫運行效率大幅降低。為了解決這種問題,從SQL Server2005版本開始,引入了多版本數(shù)據(jù)技術(shù),在一個事務中修改表中的數(shù)據(jù)時(主要指對表執(zhí)行update或delete操作),會把舊版本的數(shù)據(jù)臨時存入tempdb數(shù)據(jù)庫,此事務結(jié)束之前,其他連接的讀操作可以由tempdb數(shù)據(jù)庫讀取這些臨時數(shù)據(jù),而不是從原數(shù)據(jù)庫讀取,從而使得 讀寫操作不再相互等待。本章內(nèi)容主要包括:數(shù)據(jù)庫開啟read_committed_snapshot參數(shù)后產(chǎn)生的多

2、版本數(shù)據(jù) 數(shù)據(jù)庫開啟allow_snapshot_isolation參數(shù)后產(chǎn)生的多版本數(shù)據(jù)11.1開啟read_committed_snapshot 參數(shù)后產(chǎn)生的多版本數(shù)據(jù)開啟read_committed_snapshot參數(shù)后,新添加到表中的記錄都會在行數(shù)據(jù)最后附加14字節(jié)的版本信息數(shù)據(jù),用于指向記錄更新后產(chǎn)生的舊版本數(shù)據(jù),這些舊版本數(shù)據(jù)存儲于tempdb數(shù)據(jù)庫,開啟 read_committed_snapshot參數(shù)之前已存在的記錄會在其被執(zhí)行update操作時附加14字節(jié)的版本信息。參數(shù)開啟前后行數(shù)據(jù)存儲方式的變化創(chuàng)建測試數(shù)據(jù)庫testRowVersion ,并在其 中創(chuàng)建測試表t,數(shù)據(jù)

3、庫的 read_committed_snapshot 參數(shù)默認未開啟。1> create database testRowVersion2> go在testRowVersion數(shù)據(jù)庫中創(chuàng)建測試表t,并添加一行測試記錄。1> use testRowVersion2> create table t(a int identity, b char(5) default 'xxxxx')3> go在數(shù)據(jù)庫的read_committed_snapshot參數(shù)開啟前后,對 t表各添加一行記錄。1> insert into t default values2

4、> alter database testRowVersion set read_committed_snapshot on3> insert into t default values4> got分配到的數(shù)據(jù)頁。為了查看t表的兩行記錄在數(shù)據(jù)頁中的存儲形式,先查看表1> dbcc ind(testRowVersion,t,-1)2> goPageFID PagePIDIAMFID IAMPIDObjectID IndexID177 NULLNULL 2105058535015517721050585350先使用參數(shù)2執(zhí)行dbcc page命令,導出55號數(shù)據(jù)頁內(nèi)容

5、,以下導出內(nèi)容中的粗體部分 即是表t的兩行記錄對應的十六進制數(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命令導出55號數(shù)據(jù)頁內(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由以上導出數(shù)據(jù)可以看出兩行記錄存儲方式的差異:第1行記錄的行頭數(shù)據(jù)第 1個字節(jié)為0x10,其二進制數(shù)據(jù)為:0001 0000。 第2行記錄的行頭數(shù)據(jù)第 1個字節(jié)為0x50,其二進制數(shù)據(jù)為:0101 0000。 第2行記錄附加了 14字節(jié)的版本信息。版本信息前8個字節(jié)表示對應的舊版本數(shù)據(jù)在 tempdb數(shù)據(jù)庫中的RowID,后6個字節(jié) 表示修改記錄操作所在事務的序號。因為當前還未產(chǎn)生舊版本數(shù)據(jù),前8個字節(jié)都為0。版本信息各部分的含義請參考 節(jié)內(nèi)容。11.1.2 update產(chǎn)生的舊版本數(shù)據(jù)及版本信息t表的第1為了觀察到update產(chǎn)生的版本信息數(shù)據(jù),下面開始一個

10、事務,并在其中更新 行記錄。1> begin tran2> update t set b='aaaaa' where a=13> go重新導出55號數(shù)據(jù)頁,查看其第1行記錄存儲形式的變化。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ù)頁的空閑區(qū)域,同時修改了slotO的偏移量數(shù)值,即第1行記錄的偏移量數(shù)據(jù)指向更新后的數(shù)據(jù)所存儲的位置,而不是在原數(shù)據(jù)基礎上修改

12、。再使用參數(shù)3導出55號數(shù)據(jù)頁,可以更清楚地看到第1行記錄被更新后,其存儲格式的變化。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)由上面導出數(shù)據(jù)的最后部分可以得知,舊版本數(shù)據(jù)在tempdb數(shù)據(jù)庫的地址為(1:192:0)。14字節(jié)版本數(shù)據(jù)的前 8個字節(jié)表示舊版本記錄在tempdb數(shù)據(jù)庫中的RowID,后面4個字節(jié)表示修改記錄所在的事務的序號,其各部分含義可以分解如下。表11-1版本數(shù)據(jù)的各部分含義原十六進制數(shù)據(jù)轉(zhuǎn)換前后順序十進制數(shù)據(jù)長度表示意義c0 00 00 000xc01924B

14、舊版本記錄所在數(shù)據(jù)頁01 000x112B舊版本記錄所在文件號00 000x002B舊版本記錄slot序號87 01 00 00 00 000x1873916B修改操作所在事務序號導出tempdb數(shù)據(jù)庫的192號數(shù)據(jù)頁,查看其中的舊版本數(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)號數(shù)據(jù)頁中存儲的數(shù)據(jù), 從偏移量3D64C060至3D64C0A4為此舊版本數(shù)據(jù)的行頭系統(tǒng)信息。也可以查詢動態(tài)系統(tǒng)視圖sys.dm_tran_version_store得到tempdb數(shù)據(jù)庫中的當前多版本數(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ù)庫tempdb數(shù)據(jù)庫記錄原數(shù)據(jù)更新為移入更新后的行數(shù)據(jù) 舊版本數(shù)據(jù)指針指向啟動另外一個連接,在其中查詢t表數(shù)據(jù),可以發(fā)現(xiàn)此時不再發(fā)生等待,而查到的結(jié)果恰是存儲在tempdb數(shù)據(jù)庫中的舊版本數(shù)據(jù)。1> use testRowVersion2> go1> select * from t2> goab1 xxxxx2 xxxxx把第1個連接中的事務提交后,表t的第1行記錄的存儲形式并未發(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ù)庫中的舊版本數(shù)據(jù)已經(jīng)失效,如果此時查詢tempdb數(shù)據(jù)庫中的舊版本數(shù)據(jù),可以看到,這時不再有結(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中重新查詢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ù)庫中重建t表,添加2行記錄,用于測試 本數(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ù)頁。1> dbcc ind(testRowVersion,t,-1)2> goPageFID PagePIDIAMFID IAMPIDObjectIDIndexID78 NULLNULL21575115777821575115以參數(shù)2執(zhí)行dbcc page命令導出77號數(shù)據(jù)頁,查看t表的2行記錄存儲的初始狀態(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命令導出77號數(shù)據(jù)頁數(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ù),因為當前還未產(chǎn)生舊版本數(shù)據(jù),其版本指針為空。開始一個事務,在其中刪除 t表的第2行記錄。1> begin tran2> delete from t where a=23> go以參數(shù)3執(zhí)行dbcc page命令,重新導出77號數(shù)據(jù)頁數(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輸出了錯誤信息,請與系統(tǒng)管理員聯(lián)系。如果使用參數(shù)2執(zhí)行dbcc page命令,由最后的偏移量列表數(shù)據(jù),可以看到這個未提交 的delete操作把舊版本數(shù)據(jù)的信息加入了數(shù)據(jù)頁的空閑空間作為表t的第2行記錄,但是其中的數(shù)據(jù)并不包含行數(shù)據(jù),在偏移量列表中未標記原數(shù)據(jù),即原數(shù)據(jù)相當于被刪除了

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)查詢sys.dm_tran_version_store動態(tài)視圖,觀察存儲在tempdb數(shù)據(jù)庫

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這里的查詢結(jié)果恰是表 t的第2行記錄刪除之前在數(shù)據(jù)頁中對

33、應的數(shù)據(jù)。 查看tempdb數(shù)據(jù)的184號數(shù)據(jù)頁,可以看到舊版本數(shù)據(jù)存儲的狀態(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ù)頁,并且是在數(shù)據(jù)頁的空閑空間區(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ù)來自于重做日志文件,而不是本數(shù)據(jù)。如果把delete操作提交,SQL Server會如何處理呢?重新創(chuàng)建表 錄。1> drop table ttempdb中存儲的舊版t,并添加2行測試記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命令,導出77號數(shù)據(jù)頁,查看表t的兩行記錄的初始存儲狀態(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的偏移量設置為0,詳細信息請參考第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開啟allow_snapshot_isolation參數(shù)產(chǎn)生的的多版本數(shù)據(jù)從SQ

41、L Server 2005版本開始,新加入了snapshot隔離級別,同時數(shù)據(jù)庫增加了allow_s napshot_isolation選項參數(shù)。若要在連接中設置snap shot隔離級,需要數(shù)據(jù)庫開啟allow_snapshot_isolation 參數(shù)。設置snapshot隔離級別后,在此連接的事務中執(zhí)行的查詢只能查到這個事務開始之前 已經(jīng)提交的數(shù)據(jù),同時允許其他連接修改這個事務中所查詢的數(shù)據(jù),而不會像serializable隔離級別那樣,在事務中查到的數(shù)據(jù)甚至所查詢的表不允許其他連接修改,而只能等待查詢所在的事務完成后再進行。即開啟數(shù)據(jù)庫的allow_snapshot_isolation

42、參數(shù)厚,在snapshot隔離級別下,不會再有寫等待讀的情況發(fā)生,這其中起作用的關(guān)鍵是多版本數(shù)據(jù),也就是對應一行記錄會有不同版本的多份數(shù)據(jù)存在。多版本數(shù)據(jù)產(chǎn)生的過程假定數(shù)據(jù)庫已經(jīng)開啟了allow_snapshot_isolation參數(shù),而且對數(shù)據(jù)庫啟動了A、B、C三個連接,下面先說明多版本數(shù)據(jù)產(chǎn)生的過程,具體實驗過程請參看后續(xù)部分。1)連接A設置為snap shot隔離級別。2)在連接A中開始一個事務并執(zhí)行了一次查詢query_A,為了方便敘述,假定其查詢結(jié)果為一行,用row_A表示,row_A存儲在數(shù)據(jù)頁page_A中。3)連接B對row_A進行了修改,修改結(jié)果為row_B, row_B保

43、存在數(shù)據(jù)頁 page_A中,而row_A會被作為舊版本數(shù)據(jù)存入tempdb數(shù)據(jù)庫,row_A在tempdb數(shù)據(jù)庫中的存儲地址作為其版本數(shù)據(jù)信息保存在row_B中。4)連接B在連接A中的事務結(jié)束之前提交了修改結(jié)果,即提交了修改操作所在的事務。為了保證在連接 A中再次執(zhí)行query_A時,查詢結(jié)果不變,tempdb中存儲的 row_A要一直保留,而不能被覆蓋,這樣對于連接A中查到的一行記錄,當前就有了兩個版本的數(shù)據(jù):一是存儲于tempdb數(shù)據(jù)庫中的row_A,一是存儲于page_A中的row_B。5)如果此時開啟另外一個連接C,并設置為snapshot隔離級別,則此連接中的事務執(zhí)行query_A查

44、詢的結(jié)果總為 row_B。6)連接C對row_B進行修改并提交,修改結(jié)果為row_C,row_C會保存在數(shù)據(jù)頁page_A中,row_B則會存入tempdb數(shù)據(jù)庫,row_B在tempdb數(shù)據(jù)庫中的存儲地 址作為其版本數(shù)據(jù)信息保存在row_C中。7)如果此時開啟另外一個連接繼續(xù)上述過程,對row_A可以生成更多版本的數(shù)據(jù)。對于連接 A查到的記錄,這時有了三個版本,其中最新的row_C保存在原數(shù)據(jù)庫的page_A,另外兩個舊版本的row_B、row_A保存在tempdb數(shù)據(jù)庫中,較新版本的數(shù)據(jù)同時 保存了其上一個較舊版本數(shù)據(jù)的地址。在不同時刻開始的事務執(zhí)行相同的query_A查詢,會查到這行記錄

45、的不同版本。testRowVersiontestRowVersion-二亍tempdbtestRowVersiontempdbrowC .下面我們進行實驗說明多版本數(shù)據(jù)的產(chǎn)生。11.2.1 allow_s napshot_isolatio n參數(shù)開啟前后行記錄的存儲方式與數(shù)據(jù)庫開啟read_committed_snapshot 參數(shù)的效果相似, 在 allow_snapshot_isolation參數(shù)開啟后添加的記錄會附帶14字節(jié)的版本信息,而參數(shù)開啟之前就存在的記錄會在其被修改時附帶上版本信息。重建testRowVersion數(shù)據(jù)庫。1> drop database testRowVe

46、rsion2> create database testRowVersion3> go在testRowVersion數(shù)據(jù)庫中創(chuàng)建測試表t。1> use testRowVersion2> create table t(a int identity, b char(5) default 'xxxxx')3> go在開啟allow_snapshot_isolation參數(shù)前后對表t各添加一行記錄。1> insert into t default values3> insert into t default values4> go查看t表

47、分配到的數(shù)據(jù)頁信息。1> dbcc ind(testRowVersion,t,-1)2> goPageFID PagePIDIAMFID IAMPIDObjectID IndexID77 NULLNULL 2105058535551772105058535由以上結(jié)果可知,t表分配到一個數(shù)據(jù)頁,為(1:55)。導出55號數(shù)據(jù)頁內(nèi)容,查看兩行 記錄存儲形式的差別。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)由以上導出結(jié)果,可以看到這里的結(jié)果與開啟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因為未對第2行記錄進行過修改,此時還不存在與其對應的舊版本數(shù)據(jù),其版本信息只包括事務序號,而不包括其他舊版本數(shù)據(jù)信息。11.2.2 sn

52、apshot隔離級別下產(chǎn)生的多版本數(shù)據(jù)為了查看snapshot隔離級別下產(chǎn)生的多版本數(shù)據(jù)信息,對testRowVersion數(shù)據(jù)庫開啟4個連接,分別標記為 A、B、C及D。在連接A中設置snapshot隔離級別,然后開始一個事務,在其中查詢t表的第2行記錄。1> set transaction isolation level snapshot2> go1> begin tran2> select * from t where a=23> goab2 xxxxx在連接B中,對表t的第2行記錄執(zhí)行update操作,更改其b列的值為"aaaaa",然

53、后 把隔離級別設置為 snapshot,顯式開始一個事務,在其中查詢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中對表t的第2行記錄執(zhí)行update操作,把其b列的值改為"bbbbb”,然后 執(zhí)行與連接B相似的過程。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中對表t的第2行記錄執(zhí)行update操作,把其b列的值改為"ccccc”,然后執(zhí) 行與連接B相似的過程。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個連接中分別執(zhí)行第 2次查詢,則其查詢結(jié)果與各自的第1次結(jié)果是相同的。也就是說,對應于 t表的第2行記錄,現(xiàn)在有4份數(shù)據(jù),這4份數(shù)據(jù)包括B、C、D 三個連接對表t的第2行記錄執(zhí)行的update操作分別產(chǎn)生的一行舊版本數(shù)據(jù),以及最新的修改結(jié)果。不同的連接依照其事務開始的不同時刻,各自查到不同的數(shù)據(jù)。重新導出1:55數(shù)據(jù)頁內(nèi)容,第1行記錄對

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論