第9章 游標(biāo)、事務(wù)與鎖_第1頁
第9章 游標(biāo)、事務(wù)與鎖_第2頁
第9章 游標(biāo)、事務(wù)與鎖_第3頁
第9章 游標(biāo)、事務(wù)與鎖_第4頁
第9章 游標(biāo)、事務(wù)與鎖_第5頁
已閱讀5頁,還剩32頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第9章游標(biāo)、事務(wù)與鎖本章學(xué)習(xí)目標(biāo)

l

理解游標(biāo)、事務(wù)的概念及作用l了解鎖的相關(guān)知識l

掌握并靈活運(yùn)用游標(biāo)和事務(wù)以提高系統(tǒng)開發(fā)效率9.1游標(biāo)9.1.1游標(biāo)及其作用數(shù)據(jù)庫的游標(biāo)是類似于C語言指針的語言結(jié)構(gòu)。通常情況下,數(shù)據(jù)庫執(zhí)行的大多數(shù)SQL命令都是同時(shí)處理集合內(nèi)部的所有數(shù)據(jù)。但是,有時(shí)用戶也需要對這些數(shù)據(jù)集合中的某一行進(jìn)行操作。在沒有游標(biāo)的情況下,這種工作不得不放到數(shù)據(jù)庫前端用高級語言來實(shí)現(xiàn),這將導(dǎo)致不必要的數(shù)據(jù)傳輸,從而延長執(zhí)行時(shí)間。通過使用游標(biāo)就可以在服務(wù)器端有效地解決這個(gè)問題。游標(biāo)支持以下功能;①在結(jié)果集中定位特定行。②從結(jié)果集的當(dāng)前位置檢索行。③支持對結(jié)果集中當(dāng)前位置的行進(jìn)行數(shù)據(jù)修改。

9.1.2使用游標(biāo)游標(biāo)主要用在存儲過程、觸發(fā)器和Transact_SQL腳本中。用戶可以把它理解為一種特殊變量,也必須先聲明后使用。游標(biāo)的使用可以總結(jié)為6個(gè)步驟:聲明游標(biāo)、打開游標(biāo)、提取數(shù)據(jù)、修改數(shù)據(jù)、關(guān)閉游標(biāo)、釋放游標(biāo)。1.

聲明游標(biāo)聲明游標(biāo)的語法如下:DECLAREcursor_name[INSENSITIVE][SCROLL]CURSORFORselect_statement[FOR{READONLY|UPDATE[OFcolumn_name[,...n]]}]其中:l

cursor_name:為游標(biāo)名稱。游標(biāo)命名必須遵從Transact-SQL標(biāo)識符規(guī)則。l

INSENSITIVE:定義一個(gè)游標(biāo)時(shí)將在tempdb數(shù)據(jù)庫中創(chuàng)建一個(gè)臨時(shí)表,用于存儲由該游標(biāo)提取的數(shù)據(jù)。任何通過這個(gè)游標(biāo)進(jìn)行的操作,都在這個(gè)臨時(shí)表里進(jìn)行。因此,在對該游標(biāo)進(jìn)行提取操作時(shí)返回的數(shù)據(jù)中不反映對基表所做的修改,并且該游標(biāo)不允許修改。如果省略INSENSITIVE,那么用戶對基表進(jìn)行的任何操作都將在游標(biāo)中反映出來。l

SCROLL:指定所有的提取選項(xiàng)(FIRST、LAST、PRIOR、NEXT、RELATIVE、ABSOLUTE)均可用。如果在聲明時(shí)未指定SCROLL,則聲明的游標(biāo)只具有默認(rèn)的NEXT功能。是唯一支持的提取選項(xiàng)。如果指定SCROLL,則不能也指定FAST_FORWARD。l

select_statement:是定義游標(biāo)結(jié)果集的標(biāo)準(zhǔn)SELECT語句。在游標(biāo)聲明的SELECT語句內(nèi)不允許使用關(guān)鍵字COMPUTE、COMPUTEBY、FORBROWSE和INTO。l

READONLY:設(shè)置游標(biāo)為只讀,使用該關(guān)鍵字時(shí),不能通過該游標(biāo)更新數(shù)據(jù)。在UPDATE或DELETE語句的WHERECURRENTOF子句中不能引用游標(biāo)。l

UPDATE[OFcolumn_name[,...n]]:定義游標(biāo)內(nèi)可更新的列。如果指定OFcolumn_name[,...n]參數(shù),則只允許修改所列出的列。如果在UPDATE中未指定默認(rèn)為可以更新所有列。2.

打開游標(biāo)在使用游標(biāo)之前,必須首先打開游標(biāo),方可執(zhí)行指定操作。語法格式如下:OPEN{{[GLOBAL]cursor_name}|cursor_variable_name}l

N:

該CURSOR所定義的數(shù)據(jù)已完全從表中讀入,N為全部的數(shù)據(jù)行。l

-M:該CURSOR所定義的數(shù)據(jù)未完全從表中讀入,M為目前CURSOR數(shù)據(jù)子集內(nèi)的數(shù)據(jù)行。l

0:無符合條件的數(shù)據(jù)或該CURSOR已被關(guān)閉或釋放。l

-1:該游標(biāo)為動態(tài)的,數(shù)據(jù)行經(jīng)常變動無法確定。

其中:l

GLOBAL:指定cursor_name為全局游標(biāo)。l

cursor_name:已聲明的游標(biāo)名稱。如果全局游標(biāo)和局部游標(biāo)都使用

cursor_name

作為其名稱,那么如果指定了GLOBAL,cursor_name指的是全局游標(biāo),否則

l

cursor_name指的是局部游標(biāo)。打開一個(gè)游標(biāo)以后,可以使用無參函數(shù)@@ERROR來判斷打開操作是否成功。如果這個(gè)函數(shù)的返回植為0,則表示游標(biāo)打開成功,否則表示游標(biāo)打開失敗。當(dāng)游標(biāo)打開成功之后,可以使用無參函數(shù)@@CURSOR_ROWS來獲取這個(gè)游標(biāo)中當(dāng)前存在的記錄行數(shù)。無參函數(shù)@@CURSOR_ROWS有四種可能的取值:

3.

從游標(biāo)中提取記錄

使用FETCH語句可以從游標(biāo)中提取特定的一行記錄。其語法格式如下:

FETCH

[NEXT|PRIOR|FIRST|LAST

|ABSOLUTE{n|@nvar}

|RELATIVE{n|@nvar}

]

FROM

[GLOBAL]cursor_name}|@cursor_variable_name}[INTO@variable_name[,...n]]

其中各參數(shù)意義如下:l

NEXT:返回緊跟當(dāng)前行之后的結(jié)果行,并且當(dāng)前行遞增為結(jié)果行。如果FETCHNEXT為對游標(biāo)的第一次提取操作,則返回結(jié)果集中的第一行。NEXT為默認(rèn)的游標(biāo)提取選項(xiàng)。l

PRIOR:返回緊臨當(dāng)前行前面的結(jié)果行,并且當(dāng)前行遞減為結(jié)果行。如果FETCHPRIOR為對游標(biāo)的第一次提取操作,則沒有行返回并且游標(biāo)置于第一行之前。l

FIRST:返回游標(biāo)中的第一行并將其作為當(dāng)前行。l

LAST:返回游標(biāo)中的最后一行并將其作為當(dāng)前行。l

ABSOLUTE{n|@nvar}:如果n或@nvar為正數(shù),返回從游標(biāo)頭開始的第n行并將返回的行變成新的當(dāng)前行。如果n或@nvar為負(fù)數(shù),返回游標(biāo)尾之前的第n行并將返回的行變成新的當(dāng)前行。如果n或@nvar為0,則沒有行返回。n必須為整型常量且@nvar必須為smallint、tinyint或int。l

RELATIVE{n|@nvar}:如果n或@nvar為正數(shù),返回當(dāng)前行之后的第n行并將返回的行變成新的當(dāng)前行。如果n或@nvar為負(fù)數(shù),返回當(dāng)前行之前的第n行并將返回的行變成新的當(dāng)前行。如果n或@nvar為0,返回當(dāng)前行。如果對游標(biāo)的第一次提取操作時(shí)將FETCHRELATIVE的n或@nvar指定為負(fù)數(shù)或0,則沒有行返回。n必須為整型常量且@nvar必須為smallint、tinyint或int。l

GLOBAL:指定cursor_name指的是全局游標(biāo)。l

@cursor_variable_name:游標(biāo)變量名,引用要進(jìn)行提取操作打開的游標(biāo)。l

INTO@variable_name[,...n]:允許將提取操作的列數(shù)據(jù)放到局部變量中。列表中的各個(gè)變量從左到右與游標(biāo)結(jié)果集中的相應(yīng)列相關(guān)聯(lián)。各變量的數(shù)據(jù)類型必須與相應(yīng)的結(jié)果列的數(shù)據(jù)類型匹配或是結(jié)果列數(shù)據(jù)類型所支持的隱性轉(zhuǎn)換。變量的數(shù)目必須與游標(biāo)選擇列表中的列的數(shù)目一致。4.利用游標(biāo)修改數(shù)據(jù)如果游標(biāo)定義為可更新的,則當(dāng)定位在游標(biāo)中的某一行時(shí),可以使用UPDATE或DELETE語句中的WHERECURRENTOFcursor_name子句執(zhí)行定位更新或刪除操作。5.關(guān)閉游標(biāo)在打開游標(biāo)后,SQLServer服務(wù)器會專門為游標(biāo)開辟一定的內(nèi)存空間存放游標(biāo)操作的數(shù)據(jù)結(jié)果集,同時(shí)游標(biāo)的使用也會根據(jù)具體情況對某些數(shù)據(jù)進(jìn)行封鎖。所以,在不使用游標(biāo)時(shí),一定要關(guān)閉游標(biāo),以通知服務(wù)器釋放游標(biāo)占用的資源。語法如下:CLOSEcursor_name6.釋放游標(biāo)游標(biāo)結(jié)構(gòu)本身也會占用一定的計(jì)算機(jī)資源,所以在使用完游標(biāo)后,應(yīng)該將游標(biāo)釋放,以回收資源。語法如下:DEALLOCATEcursor_name【例9-1】聲明一個(gè)游標(biāo)jbxxb_cursor,用于訪問數(shù)據(jù)庫XSCJ中的“學(xué)生基本信息表”??稍诓樵兎治銎髦羞\(yùn)行如下命令:USEXSCJGODECLAREjbxxb_cursorCURSORFORSELECT*FROM學(xué)生基本信息表

上述命令中,聲明游標(biāo)時(shí)在SELECT語句中未用WHERE子句,故此游標(biāo)返回的結(jié)果集是由“學(xué)生基本信息表”中的所有記錄構(gòu)成的,結(jié)果如圖9-1所示。圖9-1聲明游標(biāo)

【例9-2】

使用游標(biāo)查看數(shù)據(jù)庫XSCJ中“學(xué)生基本信息表”中滿足條件的記錄個(gè)數(shù)。代碼如下:USEXSCJGODECLAREjbxxb_CursorCURSORFORSELECT學(xué)號,姓名FROMxscj.dbo.學(xué)生基本信息表WHERE族別LIKE'哈薩克'OPENjbxxb_CursorFETCHNEXTFROMjbxxb_CursorWHILE@@FETCH_STATUS=0BEGINFETCHNEXTFROMjbxxb_CursorENDCLOSEjbxxb_CursorDEALLOCATEjbxxb_Cursor在以上程序中首先定義了名為jbxxb_cursor的游標(biāo),通過該游標(biāo)可以對學(xué)生基本信息表中族別為“哈薩克”族的學(xué)生學(xué)號和姓名進(jìn)行搜索,用FETCHNEXT來控制其結(jié)果的顯示,其中@@FETCH_STATUS返回被FETCH語句執(zhí)行的最后游標(biāo)的狀態(tài),如果返回值為0,則說明該游標(biāo)成功,如果返回值為-1,則說明該游標(biāo)失敗,如果返回值為-2,則說明被提取的行不存在。結(jié)果如圖9-2所示。

圖9-2打開游標(biāo)【例9-3】為“學(xué)生基本信息表”中姓名以“張”開頭的行聲明一個(gè)簡單的游標(biāo)jbxxb1_cursor,并使用FETCHNEXT逐個(gè)提取這些行。FETCH語句以單行結(jié)果集形式返回由DECLARECURSOR指定列的值。在查詢分析器中運(yùn)行如下命令:USEXSCJGODECLAREjbxxb1_cursorCURSORFORSELECT姓名FROM學(xué)生基本信息表WHERE姓名LIKE'張%'ORDERBY姓名OPENjbxxb1_cursorFETCHNEXTFROMjbxxb1_cursorWHILE@@FETCH_STATUS=0BEGINFETCHNEXTFROMjbxxb1_cursorENDCLOSEjbxxb1_cursorDEALLOCATEjbxxb1_cursor運(yùn)行結(jié)果如圖9-3所示。

圖9-3從游標(biāo)中提取記錄

【例9-4】本例與上例相似,使用FETCH語句將值存入變量,但FETCH語句的值存儲于局部變量而不是直接返回給基表。PRINT語句將變量組合成單一字符串并將其返回到基表。代碼如下:USEXSCJGODECLARE@學(xué)號varchar(40),@姓名varchar(20)DECLARExb_cursorCURSORFORSELECT學(xué)號,姓名FROM學(xué)生基本信息表WHERE姓名LIKE'張%'ORDERBY姓名OPENxb_cursorFETCHNEXTFROMxb_cursorINTO@學(xué)號,@姓名WHILE@@FETCH_STATUS=0BEGINPRINT'學(xué)生姓名為:'+@姓名+';學(xué)號為'+@學(xué)號FETCHNEXTFROMxb_cursorINTO@學(xué)號,@姓名ENDCLOSExb_cursorDEALLOCATExb_cursor運(yùn)行結(jié)果如圖9-4所示。圖9-4使用FETCH語句將值存入變量

9.2事務(wù)

9.2.1事務(wù)模式日常生活中我們需要一種能保證數(shù)據(jù)完整性的機(jī)制,比如學(xué)生父母給孩子打的生活費(fèi)要么發(fā)送成功,要么發(fā)送失?。ú粦?yīng)該出現(xiàn)一邊發(fā)送成功,另一邊接受不到的情況),這樣才是安全的、可靠的。數(shù)據(jù)庫管理中也需要類似的機(jī)制,那就是事務(wù)。事務(wù)是作為單個(gè)邏輯工作單元執(zhí)行的一系列操作。這一系列操作或者都被執(zhí)行或者都不被執(zhí)行。事務(wù)做為一個(gè)邏輯工作單元必須有四個(gè)屬性,稱為ACID(原子性、一致性、隔離性和持久性)屬性,只有這樣才能成為一個(gè)事務(wù)。

l

原子性:事務(wù)必須是原子工作單元,對于其數(shù)據(jù)修改,要么全都執(zhí)行,要么全都不執(zhí)行。l

一致性:事務(wù)在完成時(shí),必須使所有的數(shù)據(jù)都保持一致狀態(tài)。在相關(guān)數(shù)據(jù)庫中,所有規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持所有數(shù)據(jù)的完整性。l

隔離性:由并發(fā)事務(wù)所作的修改必須與任何其它并發(fā)事務(wù)所作的修改隔離。事務(wù)查看數(shù)據(jù)時(shí)數(shù)據(jù)所處的狀態(tài),要么是另一并發(fā)事務(wù)修改它之前的狀態(tài),要么是另一事務(wù)修改它之后的狀態(tài),事務(wù)不會查看中間狀態(tài)的數(shù)據(jù)。這稱為可串行性,因?yàn)樗軌蛑匦卵b載起始數(shù)據(jù),并且重播一系列事務(wù),以使數(shù)據(jù)結(jié)束時(shí)的狀態(tài)與原始事務(wù)執(zhí)行的狀態(tài)相同。l持久性:事務(wù)完成之后,它對于系統(tǒng)的影響是永久性的。該修改即使出現(xiàn)系統(tǒng)故障也將一直保持。

9.2.2事務(wù)管理事務(wù)的執(zhí)行需要經(jīng)過事務(wù)的開始、事務(wù)提交及事務(wù)回滾等三個(gè)過程。其中BEGINTRANSACTION代表事務(wù)的開始點(diǎn),每個(gè)事務(wù)繼續(xù)執(zhí)行直到用COMMITTRANSACTION提交,從而保證數(shù)據(jù)的完整性與一致性,或者遇上錯(cuò)誤用ROLLBACKTRANSACTION語句撤消所有改動。注:SQLSERVER中為了保證最基本數(shù)據(jù)的安全,規(guī)定有幾種語句不能出現(xiàn)在事務(wù)管理中,它們分別是ALTERDATABASE,BACKUPLOG,CREATEDATABASE,DISKINIT,DROPDATABASE,DUMPTRANSACTION,LOADDATABASE,LOADTRANSACTION,RECONFIGURE,RESTOREDATABASE,RESTORELOG,UPDATESTATISTICS等。另外事務(wù)的執(zhí)行方式有兩種,分別是顯式事務(wù)和隱式事務(wù)。其中每個(gè)事務(wù)均以BEGINTRANSACTION語句顯式開始,以COMMIT或ROLLBACK語句顯式結(jié)束的是顯式事務(wù)。隱性事務(wù)在前一個(gè)事務(wù)完成時(shí)新事務(wù)隱式啟動,但每個(gè)事務(wù)仍以COMMIT或ROLLBACK語句顯式完成。

1.定義事務(wù)的開始

語法:BEGINTRANSACTION[事務(wù)名]

功能:標(biāo)記一個(gè)顯式本地事務(wù)的起始點(diǎn)。

2.提交事務(wù)

語法:COMMITTRANSACTION[事務(wù)名]

功能:標(biāo)志一個(gè)成功的隱性事務(wù)或用戶定義事務(wù)的結(jié)果。

3.回滾事務(wù)

語法:ROLLBACKTRANSACTION[事務(wù)名]

功能:將顯式事務(wù)或隱性事務(wù)回滾到事務(wù)的起點(diǎn)或事務(wù)內(nèi)的某個(gè)保存點(diǎn)。

【例9-5】定義一事務(wù)charu(未提交)并將“學(xué)生基本信息表”中族別不是“漢族”的學(xué)生“族別”改成“少數(shù)民族”。代碼如下

USEXSCJ

GO

BEGINTRANSACTIONcharu

GO

UPDATE學(xué)生基本信息表

SET族別='少數(shù)民族'

WHERE族別!='漢族'

GO

運(yùn)行結(jié)果如圖9-5所示。圖9-5使用BEGINTRANSACTION開始事務(wù)

通過以上代碼可以將“族別”不是“漢族”的學(xué)生“族別”改成“少數(shù)民族”,接著可以用ROLLBACK語句將未提交成功的事務(wù)回滾回來。代碼為:ROLLBACKTRANSACTIONcharu但是如果將事務(wù)提交出去以后,就不能再用ROLLBACK語句回滾事務(wù)了,這說明COMMITTRANSACTION語句是用于標(biāo)志已提交成功的事務(wù)??梢杂肧ELECT語句來觀察其結(jié)果。BEGINTRANSACTIONcharuGOUSEXSCJGOUPDATE學(xué)生基本信息表SET族別='少數(shù)民族'WHERE族別!='漢族'GOCOMMITTRANSACTIONcharuGO這以后再不能回滾事務(wù),在查詢分析器里執(zhí)行后的結(jié)果如圖9-6所示,同學(xué)們可以親自驗(yàn)證一下。

圖9-6提交事務(wù)【例9-6】事務(wù)的嵌套,通過本例可以知道嵌套事務(wù)中,內(nèi)部事務(wù)所做的修改等提交完最外層事務(wù)之后才能生效。USEXSCJGOCREATETABLE綜合表(學(xué)號INTPRIMARYKEY,姓名CHAR(8),年齡int)BEGINTRANSACTIONcharuINSERTINTO綜合表VALUES(1,'卡吾薩爾',18)BEGINTRANSACTIONcharu1INSERTINTO綜合表VALUES(2,'夏爾巴提',20)BEGINTRANSACTIONcharu2INSERTINTO綜合表VALUES(3,'張莉',19)COMMITTRANSACTIONcharu2COMMITTRANSACTIONcharu1COMMITTRANSACTIONcharu圖9-7嵌套事務(wù)

以上代碼中一直執(zhí)行到最后一行后該事務(wù)才生效,用戶在操作時(shí),可以先試用COMMITTRANSACTIONcharu之前的代碼,后用SELECT或直接打開表的方式查看其結(jié)果,即會發(fā)現(xiàn)用戶表列表中除了剛創(chuàng)建的表名之外,該表內(nèi)無任何數(shù)據(jù)。這說明定義的事務(wù)未提交成功,在執(zhí)行最關(guān)鍵的外層事務(wù)的提交之后才能完成本次事務(wù)的提交,同時(shí)也可以通過SELECT或直接打開表的方式觀察到其結(jié)果已生效。9.3鎖9.3.1鎖的基礎(chǔ)知識SQLServer2000使用鎖定確保事務(wù)完整性和數(shù)據(jù)庫一致性。鎖定可以防止用戶讀取正在由其他用戶更改的數(shù)據(jù),并可以防止多個(gè)用戶同時(shí)更改相同的數(shù)據(jù)。如果不使用鎖定,則數(shù)據(jù)庫中的數(shù)據(jù)可能在邏輯上不正確,并且對數(shù)據(jù)的查詢可能會產(chǎn)生意想不到的結(jié)果。這些問題包括:

(1)丟失或覆蓋更新當(dāng)兩個(gè)或多個(gè)事務(wù)選擇同一行,然后基于最初選定的值更新該行時(shí),會發(fā)生丟失更新問題。每個(gè)事務(wù)都不知道其它事務(wù)的存在。最后的更新將重寫由其它事務(wù)所做的更新,這將導(dǎo)致數(shù)據(jù)丟失。如網(wǎng)絡(luò)數(shù)據(jù)庫管理員A和B同時(shí)對“學(xué)生基本信息表”中學(xué)號為000001的學(xué)生的政治面貌進(jìn)行修改,管理員A將其政治面貌改成黨員,接著管理員B將其政治面貌改成群眾,結(jié)果管理員A所做的修改沒被保存,管理員B所做的保存生效。如果在第一個(gè)管理人員完成之后第二個(gè)管理人員才能進(jìn)行更改,則可以避免該問題的發(fā)生。

(2)未確認(rèn)的相關(guān)性(臟讀)當(dāng)?shù)诙€(gè)事務(wù)選擇其它事務(wù)正在更新的行時(shí),會發(fā)生未確認(rèn)的相關(guān)性問題。第二個(gè)事務(wù)正在讀取的數(shù)據(jù)還沒有確認(rèn)并且可能由更新此行的事務(wù)所更改。

如管理人員A正在更改電子文檔。在更改過程中,另一個(gè)管理人員B復(fù)制了該文檔(該副本包含到目前為止所做的全部更改)并將其分發(fā)給預(yù)期的用戶。此后,A認(rèn)為目前所做的更改是錯(cuò)誤的,于是刪除了所做的編輯并保存了文檔。分發(fā)給用戶的文檔包含不再存在的編輯內(nèi)容(臟讀),并且這些編輯內(nèi)容應(yīng)認(rèn)為從未存在過。如果在A確定最終更改前任何人都不能讀取更改的文檔,則可以避免該問題。(3)不一致的分析(非重復(fù)讀)當(dāng)?shù)诙€(gè)事務(wù)多次訪問同一行而且每次讀取不同的數(shù)據(jù)時(shí),會發(fā)生不一致的分析問題。不一致的分析與未確認(rèn)的相關(guān)性類似,因?yàn)槠渌聞?wù)也是正在更改第二個(gè)事務(wù)正在讀取的數(shù)據(jù)。然而,在不一致的分析中,第二個(gè)事務(wù)讀取的數(shù)據(jù)是由已進(jìn)行了更改的事務(wù)提交的。而且,不一致的分析涉及多次(兩次或更多)讀取同一行,而且每次信息都由其它事務(wù)更改,因而該行被非重復(fù)讀取。

如一位管理人員兩次讀取同一文檔,但在兩次讀取之間,另一位管理人員重寫了該文檔。當(dāng)管理人員第二次讀取文檔時(shí),文檔已更改。原始讀取不可重復(fù)。如果只有在管理員全部完成編寫后另外的人員才可以讀取文檔,則可以避免該問題。

(4)幻像讀

當(dāng)對某行執(zhí)行插入或刪除操作,而該行屬于某個(gè)事務(wù)正在讀取的行的范圍時(shí),會發(fā)生幻像讀問題。事務(wù)第一次讀的

行范圍顯示出其中一行已不復(fù)存在于第二次讀或后續(xù)讀中,因?yàn)樵撔幸驯黄渌聞?wù)刪除。同樣,由于其它事務(wù)的插入操作,事務(wù)的第二次或后續(xù)讀顯示有一行已不存在于原始讀中。

如一位管理人員更改作者提交的文檔,但當(dāng)生產(chǎn)部門將其更改內(nèi)容合并到該文檔的主副本時(shí),發(fā)現(xiàn)作者已將未編輯的新材料添加到該文檔中。如果在編輯人員和生產(chǎn)部門完成對原始文檔的處理之前,任何人都不能將新材料添加到文檔中,則可以避免該問題。9.3.2死鎖當(dāng)某組資源的兩個(gè)或多個(gè)線程之間有循環(huán)相關(guān)性時(shí),將發(fā)生死鎖。死鎖是一種可能發(fā)生在任何多線程系統(tǒng)中的狀態(tài)。多線程系統(tǒng)中的一個(gè)線程可能獲取一個(gè)或多個(gè)資源(如鎖)。如果正獲取的資源當(dāng)前為另一線程所擁有,則第一個(gè)線程可能必須等待擁有線程釋放目標(biāo)資源。這時(shí)就說等待線程在那個(gè)特定資源上與擁有線程有相關(guān)性。SQLSERVER使用不同的鎖模式鎖定資源,這些鎖模式確定了并發(fā)事務(wù)訪問資源的方式。下面介紹幾種常用的鎖模式。(1)共享鎖:用于只讀操作,如SELECT共享鎖允許并發(fā)事務(wù)讀取一個(gè)資源。資源上存在共享鎖時(shí),任何其他事務(wù)都不能修改數(shù)據(jù)。除非將事務(wù)隔離級別設(shè)置為可重復(fù)讀或更高級別,或者在事務(wù)生存周期內(nèi)用鎖定提示保留共享鎖,那么一旦讀取數(shù)據(jù),便立即釋放資源上的共享鎖。(2)更新鎖:用于可更新的資源中。更新鎖可以防止通常形式的死鎖。一般更新模式由一個(gè)事務(wù)可完成,這一系列操作要求鎖轉(zhuǎn)換為排他鎖。如果兩個(gè)以上事務(wù)獲得共享鎖且都要把資源上的共享鎖轉(zhuǎn)換為排他鎖時(shí)會發(fā)生沖突而死鎖。為避免這種死鎖問題,要使用更新鎖。一次只有一個(gè)事務(wù)可以獲得資源的更新鎖。如果事務(wù)修改資源,則更新鎖轉(zhuǎn)換為排他鎖。否則轉(zhuǎn)換為共享鎖。(3)排他鎖:用于數(shù)據(jù)修改操作。確保不會同時(shí)對同一資源進(jìn)行多重更新。顧名思義排他鎖是排斥被鎖定的資源由多個(gè)事務(wù)訪問?!纠?-7】分別使用企業(yè)管理器和sp_lock系統(tǒng)存儲過程顯示SQLServer中當(dāng)前持有的鎖信息。方法一、在企業(yè)管理器中展開【服務(wù)器組】,選擇【管理】/【當(dāng)前活動】/【鎖/進(jìn)程ID】可以觀察鎖信息。方法二、在查詢分析器中執(zhí)行以下命令,結(jié)果如圖9-8所示。USEXSCJGOEXECsp_lockGO圖9-8查看當(dāng)前鎖

如果擁有線程需要獲取另外一個(gè)資源,而該資源當(dāng)前為等待線程所擁有,則這種情形將成為死鎖:在事務(wù)提交或回滾之前兩個(gè)線程都不能釋放資源,而且它們因?yàn)檎却龑Ψ綋碛械馁Y源而不能提交或回滾事務(wù)。例如,運(yùn)行事務(wù)1的線程T1具有學(xué)生基本信息表上的排它鎖。運(yùn)行事務(wù)2的線程T2具有系部表上的排它鎖,并且之后需要學(xué)生基本信息表上的鎖。事務(wù)2無法獲得這一鎖,因?yàn)槭聞?wù)1已擁有它。事務(wù)2被阻塞,等待事務(wù)1。然后,事務(wù)1需要

系部表的鎖,但無法獲得鎖,因?yàn)槭聞?wù)2將它鎖定了。事務(wù)在提交或回滾之前不能釋放持有的鎖。因?yàn)槭聞?wù)需要對方控制的鎖

溫馨提示

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

最新文檔

評論

0/150

提交評論