版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
7.1事務的概念
7.2事務的基本操作
7.3封鎖機制
7.4封鎖的問題及解決方法
7.5數(shù)據(jù)庫恢復技術
實驗7事務管理與數(shù)據(jù)庫備份
第7章事務管理
7.1.1引入事務處理的必要性
實際數(shù)據(jù)庫操作中,一個操作常與其他操作具有某種程度的關聯(lián)。只有將這些互相關聯(lián)的操作作為一個整體來進行,才能保證它們的正確性。例如,假定銀行要將“張京”賬戶上的9800元錢轉入“王瑩”賬戶,需要連續(xù)執(zhí)行兩步操作:
●從張京”賬戶上取出9800元;
●為“王瑩”賬戶存入9800元。7.1事?務?的?概?念
【例7-1】假定火車售票系統(tǒng)中有“售票”和“車次”兩個表,分別登記各代售點累計售出的車票數(shù)與全部車次的剩余票數(shù),其關系模式為
售票(代售點號,車次,日期,售出票數(shù))
車次(車次,日期,剩余票數(shù))
現(xiàn)在A0110售票點打算代售3張K236車次2012年10月20日的車票,需要執(zhí)行以下操作:
S1N←查詢K236車次2012年10月20日的“剩余票數(shù)”;
S2如果N<2,則
拒絕操作并通知車票數(shù)不足;
否則{
更新A0110代售點的“售出票數(shù)”;
更新K236車次的“剩余票數(shù)”;
}步驟S1可由一個SELECT語句來完成:
SELECT剩余票數(shù)
FROM車次
WHERE車次='K236'AND日期='2012-10-20';
步驟S2按照S1操作的結果來決定能不能售票并對兩個表進行更新操作,如果剩余票數(shù)多于請求票數(shù)(3張),則可用下面兩個語句更新“售票”表和“車次”表:/*更新A0110代售點K236車次2012年10月20日的“售出票數(shù)”*/
UPDATE售票
SET售出票數(shù)=售出票數(shù)+3
WHERE代售點號='A0110'AND車次='K236'AND日期='2012-10-20'
/*更新K236車次2012年10月20日的“剩余票數(shù)”*/
UPDATE車次
SET剩余票數(shù)=剩余票數(shù)-3
WHERE車次='K236'AND日期='2012-10-20';如果兩個UPDATE語句都能夠成功執(zhí)行,則將協(xié)同完成“A0110代售點售出3張K236車次2012年10月20日車票”這個任務。但是,如果第一個UPDATE語句執(zhí)行成功后,系統(tǒng)隨之發(fā)生故障,則有可能出現(xiàn)問題:假定K236次火車共有1200張車票,2012年10月20日的車票已售出了1197張,其中A0110代售點售出了150張,剩余車票3張。在第1個UPDATE語句成功執(zhí)行后,A0110代售點的“售出票數(shù)”更新為153。當排除了系統(tǒng)故障并重新提供服務時,如果另一個代售點又請求代售3張K236車次2012年10月20日車票,則將因K236車次的“剩余票數(shù)”尚未更新而再次售出3張,結果多售出了3張車票。導致這種錯誤的原因是系統(tǒng)重新提供服務時,數(shù)據(jù)庫的當前狀態(tài)與它所描述的客觀事物當前的實際狀態(tài)是不一致的。為了解決這樣的問題,DBMS引入了事務處理機制,允許用戶將一系列具有內(nèi)在聯(lián)系的操作定義為一個事務,一個事務就是一個邏輯單元,可以采取相應的策略來保證一個邏輯單元內(nèi)的操作要么全部執(zhí)行要么都不執(zhí)行。
在數(shù)據(jù)庫系統(tǒng)上執(zhí)行并發(fā)操作時,事務是作為最小的控制單元來使用的。對于DBMS來說,一個事務就是一個不可分割的邏輯上的工作單元。如果一次只允許一個用戶使用,則該系統(tǒng)為單用戶系統(tǒng);如果允許多個用戶同時使用,則該系統(tǒng)為多用戶系統(tǒng)。在多用戶系統(tǒng)中,經(jīng)常會遇到多個用戶執(zhí)行并發(fā)操作的情況,可將事務作為執(zhí)行這種并發(fā)操作的最小控制單元。7.1.2事務的特點
1.事務結束語句
DBMS中的事務類似于操作系統(tǒng)中的進程,進程是操作系統(tǒng)中分配系統(tǒng)資源和進行處理機調(diào)度的基本單元。而DBMS中的事務是資源競爭、并發(fā)控制和恢復的基本單元。它是由數(shù)據(jù)庫操縱語言(如SQL)或者程序設計語言(如C、C++、Java)提供的事務開始語句、事務結束語句定界的一系列數(shù)據(jù)庫操作語句構成的。通常有兩種事務結束語句:
(1)事務提交:將成功完成的事務的執(zhí)行結果(即更新)永久化,并釋放事務占有的全部資源。
(2)事務回滾:中止當前事務,撤銷對數(shù)據(jù)庫所做的更新,并釋放事務占有的全部資源。
2.事務的類型
SQLServer數(shù)據(jù)庫提供了三種類型的事務模式:顯式事務、隱式事務和自定義事務。
(1)顯式事務是指顯式地定義其開始和結束的事務,又稱為用戶定義事務。當使用BEGINTRAN和COMMIT語句時發(fā)生顯式事務。
(2)隱式事務是指在當前事務提交或回滾后自動開始的事務,需要用COMMIT語句和ROLLBACK語句回滾或結束事務。
(3)自動提交事務是指能夠自動執(zhí)行并自動回滾的事務,即當一個語句成功執(zhí)行后,事務被自動提交;當執(zhí)行過程中產(chǎn)生錯誤時,將會執(zhí)行事務回滾的操作。
【例7-2】用SQLServer提供的顯式事務模式定義例7-1中的數(shù)據(jù)庫更新事務。
BEGINTRANSACTION
UPDATE售票
SET售出票數(shù)=售出票數(shù)+3
WHERE代售點號='A0110'AND車次='K236'AND日期='2012-10-20'
UPDATE車次
SET剩余票數(shù)=剩余票數(shù)-3
WHERE車次='K236'AND日期='2012-10-20'
COMMITTRANSACTION;
3.事務的特點
為了事務能夠并發(fā)執(zhí)行且當發(fā)生故障時保證數(shù)據(jù)的完整性,事務應該具備以下特性。
(1)原子性:事務是由不可分割的操作序列構成的工作單元,由事務管理子系統(tǒng)完成。事務中的全部元素作為一個整體提交或回滾。如果一個事務執(zhí)行失敗,DBMS能夠保證已經(jīng)執(zhí)行了的那些操作不反映到數(shù)據(jù)庫中。例如,銀行轉賬時通過一個事務更新兩個賬戶的存款余額,如果該事務提交了,則這兩個賬戶都會更新;如果事務在執(zhí)行了第一個更新語句后因出現(xiàn)故障而不能執(zhí)行第二個更新語句,則在數(shù)據(jù)庫恢復時將會消除第一個更新語句對數(shù)據(jù)庫的影響。
(2)一致性:一個事務不能違背定義在數(shù)據(jù)庫中的任何完整性檢查。為了維護數(shù)據(jù)的一致性,所有的規(guī)則、約束、檢查都會被應用到事務中。因為所有的數(shù)據(jù)更改都是在事務執(zhí)行期間進行的,因而這些數(shù)據(jù)在事務開始和結束之前能夠確保一致。例如,在銀行系統(tǒng)中,事務開始前,兩個賬戶余額的總額處于一致的狀態(tài),事務進行過程中,一個賬戶余額改變,另一個賬戶余額未變,則這兩個賬戶余額的總額處于不一致狀態(tài),事務完成后,賬戶余額的總額即恢復為一致的狀態(tài)。
(3)隔離性:由并發(fā)事務所做的修改必須與任何其他并發(fā)事務所做的修改隔離。在事務查看數(shù)據(jù)時,數(shù)據(jù)所處的狀態(tài)要么是另一并發(fā)事務修改它之前的狀態(tài),要么是另一事務修改它之后的狀態(tài),事務不會查看中間狀態(tài)的數(shù)據(jù)。這稱為可串行性,因為它能夠重新裝載起始數(shù)據(jù),并且重播一系列事務,以使數(shù)據(jù)結束時的狀態(tài)與原始事務執(zhí)行的狀態(tài)相同。
注:當事務執(zhí)行修改數(shù)據(jù)操作時,如果任何其他進程正在同時使用相同的數(shù)據(jù),則直到該事務成功提交后,對數(shù)據(jù)的修改才能生效。
(4)永久性:事務在提交之后,所做的工作將會永久保存下來,即使硬件和應用程序發(fā)生錯誤,也必須保證對數(shù)據(jù)所做的修改不受影響。7.2.1啟動事務
事務啟動標記一個顯式本地事務的起點。事務一旦啟動,便會一直執(zhí)行下去,直到其中所有操作都準確無誤地完成之后,使用COMMITTRANSACTION語句將該事務對數(shù)據(jù)庫中數(shù)據(jù)的操作結果永久地保存在數(shù)據(jù)庫中,如果在運行事務的過程中遇到了錯誤,則BEGINTRANSACTION命令之后的所有數(shù)據(jù)操作都將進行回滾,將數(shù)據(jù)庫中數(shù)據(jù)恢復到該事務執(zhí)行之前的狀態(tài)。7.2事務的基本操作
SQLServer中,可以通過BEGINTRANSACTION命令啟動事務。該命令的一般形式為
BEGIN
TRAN[SACTION]
[事務名|@事務名變量]
[WITH
MARK['字符串']]
其中,“事務名”即該事務的名稱;“@事務名變量”表示用變量來指定事務的名稱,并且變量只能聲明為char、nchar、varchar和nvarchar幾種數(shù)據(jù)類型;WITHMARK表示指定在日志中的標記事務;“字符串”表示描述被標記的字符串。一個BEGINTRANSACTION語句與其后的一條COMMITTRANSACTION語句之間的所有事情作為單個事務。如果SQLServer遇到一條COMMINT
TRANSACTION語句,那么保存自最近一條BEGIN
TRANSACTION語句之后對數(shù)據(jù)庫所做的工作;如果SQLServer遇到一條ROLLBACK
TRANSACTION語句,則將拋棄所有這些工作。
事務是可以嵌套的,原則是必須先提交或回退內(nèi)層事務,然后再提交或回退外層事務,換句話說,一條COMMIT
TRANSACTION或ROLLBACK
TRANSACTION語句對應最近的一條BEGIN
TRANSACTION語句。
注:也可使用STARTTRANSACTION命令實現(xiàn)開始事務,其用法和功能與BEGINTRANSACTION命令類似。
【例7-3】使用BEGINTRANSACTION命令啟動事務myTrans。
USE
dbTest;
/*打開數(shù)據(jù)庫dbTest*/
GO
DECLARE
@myTrans
varchar(20);
/*本行及下一行聲明了事務名稱*/
select
@myTrans='myTransName';
BEGIN
TRANSACTION
@myTrans;
/*啟動事務*/
GO
SELECT
*
FROM
存貨/*本行及下一行設置執(zhí)行事務的內(nèi)容*/
ORDER
BY
貨號
GO
【例7-4】使用WITHMARK命令為事務logTrans建立一個標記。
USE
dbTest;
GO
BEGIN
TRANSACTION
logTrans
WITH
MARK
'查詢存貨表中的存貨量數(shù)據(jù)'
GO
SELECT
*
FROM
存貨
ORDER
BY
貨號
GO
7.2.2提交事務
使用COMMITTRANSACTION命令來實現(xiàn)事務的提交操作。事務提交標志著一個成功的從BEGINTRANSACTION開始的事務(隱性事務或顯式事務)的結束,使得自從事務開始以來所執(zhí)行的所有數(shù)據(jù)修改的結果成為數(shù)據(jù)庫的永久部分,并釋放事務所占用的資源。
數(shù)據(jù)庫中為了保證數(shù)據(jù)的完整性和一致性,通常要在內(nèi)存中建立一個工作區(qū),用于完成對數(shù)據(jù)庫進行操作處理的各種事務,這些處理結果在COMMIT命令執(zhí)行之前并未保存到數(shù)據(jù)庫中,只有在執(zhí)行COMMIT命令之后,內(nèi)存工作區(qū)的內(nèi)容才被寫入數(shù)據(jù)庫。這樣可以確保數(shù)據(jù)庫中數(shù)據(jù)的完整性和一致性。COMMITTRANSACTION命令的一般形式為
COMMIT
{TRAN
|
TRANSACTION}[事務名
|
@事務名變量]
發(fā)布一條COMMIT
TRANSACTION語句時,SQLServer將最近的一個已啟動事務標記為準備提交。只有在提交一個嵌套事務系列中的最外層事務時,SQLServer才將所有修改都寫入到數(shù)據(jù)庫中。用戶的責任是保證在做完了所有預期的修改之后再發(fā)布COMMIT
TRANSACTION語句。一旦提交了一個事務,就再也不能回退它了。
【例7-5】使用BEGINTRANSACTION命令啟動事務myTrans,并使用COMMITTRANSACTION命令提交該事務。USE
dbTest;
GO
DECLARE
@myTrans
varchar(20);
select
@myTrans='myTransName';
BEGIN
TRANSACTION
@myTrans;
GO
SELECT
*
FROM
存貨
ORDER
BY
貨號
GO
COMMIT
TRANSACTION
GO
7.2.3回滾事務
用戶可以使用ROLLBACKTRANSACTION語句實現(xiàn)回滾事務的操作?;貪L事務是指取消自事務的起點或保存點到事務結束后的所有操作。回滾后系統(tǒng)將釋放由事務控制的資源。ROLLBACKTRANSACTION語句的一般形式為
ROLLBACK
{TRAN
|
TRANSACTION}[
事務名
|
@事務名變量
|
保存點名]
其中,“事務名”表示回滾事務的名稱;“@事務名變量”表示用戶定義的包含有效事務名稱變量的名稱;“保存點名”是用戶在事務中設置的保存點的名稱,保存點可以定義在按條件取消某個事務的一部分后該事務可以返回的一個位置??梢酝ㄟ^回滾到起點而完全取消事務,此時,ROLLBACKTRANSACTION語句拋棄自最近一條BEGIN
TRANSACTION語句以后的所有操作結果;也可以將事務回滾到保存點,再按需要完成剩余的SQL語句和COMMITTRANSACTION語句;ROLLBACKTRANSACTION語句無法回退嵌套事務系列中的單個事務。而總是回退到嵌套事務系列當中的第一個事務(最外層事務)。
如果需要取消整個事務,使用“ROLLBACKTRANSACTION事務名”語句實現(xiàn)。
事務開始后,事務處理期間使用的資源會一直保留,直到事務完成(即鎖定)。如果將事務的一部分回滾到保存點,則將繼續(xù)保留資源直到事務完成或者回滾整個事務為止。
【例7-6】定義一個事務,通過事務將“存貨”表中“貨名”為“應急燈”的單價修改為91,然后再使用ROLLBACKTRANSACTION語句將該事務回滾。
BEGIN
TRANSACTION
UPDATE
存貨
SET
單價=91
WHERE
貨名='應急燈'
ROLLBACK
TRANSACTION
SELECT
*
FROM
存貨
7.2.4設置事務保存點
使用事務時,用戶可以在事務內(nèi)部設置事務保存點,以備必要時回滾到這個保存點。在執(zhí)行事務的過程中,如果需要按條件回滾到預先設定的事務保存點,則撤銷該保存點之后的操作即可。
如果遇到錯誤的可能性較小而且預先檢查更新的有效性的代價較高,則使用保存點將會非常有效。例如,應用程序在客戶訂單中插入一條訂貨記錄時,需要查驗本公司是否有訂單所需求的存貨,但查驗可用存貨量的工作因需多方查詢而代價較大,考慮到該公司具備有效的供應商和分購點,存貨不足的可能性很小,故可將應用程序設計為不先驗貨而直接更新訂單,只需在收到存貨不足的信息時,回滾到這個更新操作之前即可。實現(xiàn)這個功能的方法是:在插入訂貨記錄的操作之前設置一個事務保存點,以備存貨不足時撤銷插入操作。在事務內(nèi)部設置事務保存點使用SAVETRANSACTION語句來實現(xiàn),該語句的一般形式為
SAVE
{TRAN
|
TRANSACTION}[保存點名
|
@保存點名變量]
其中,“保存點名”表示設置事務保存點的名稱;“@保存點名變量”表示包含有效保存點名稱的用戶定義變量的名稱。
設置了事務保存點之后,便可執(zhí)行“ROLLBACKTRANSACTION保存點名”語句回滾到保存點(不回滾到事務的起點)。
【例7-7】定義一個事務,通過事務將“存貨”表中名稱為“應急燈”的數(shù)據(jù)記錄刪除,并在事務中定義保存點,保存點的名稱為markSave。
BEGIN
TRANSACTION
/*啟動事務*/
DELETE
FROM
存貨
/*這兩行設置事務保存點之前執(zhí)行的操作*/
WHERE
貨名='應急燈'
SAVE
TRANSACTION
markSave
/*設置事務保存點markSave*/
DELETE
FROM
存貨
/*這兩行設置事務保存點之后執(zhí)行的操作*/
WHERE
貨名='鉗子'
ROLLBACK
TRANSACTION
Save_Goods
/*回滾到事務保存點markSave*/
SELECT
*
FROM
存貨
封鎖機制是并發(fā)控制的主要手段,是多個用戶能夠同時操縱同一個數(shù)據(jù)庫中數(shù)據(jù)而不發(fā)生數(shù)據(jù)不一致現(xiàn)象的重要保障。
注:單CPU的計算機系統(tǒng)中,同一時間只能由一個事務占用CPU進行處理。所謂的并發(fā)訪問實質(zhì)上是多個事務交叉使用CPU。7.3封鎖機制7.3.1并發(fā)操作可能出現(xiàn)的問題
如果多個涉及數(shù)據(jù)庫中數(shù)據(jù)更新的操作需要并發(fā)執(zhí)行,則應該加以限制,否則可能會產(chǎn)生數(shù)據(jù)不一致問題。
【例7-8】并發(fā)操作不加以限制時產(chǎn)生的數(shù)據(jù)不一致性問題。
假設,一個商店中涉及某種商品的兩宗業(yè)務如下:
進貨:存貨100件,再購進200件。需要執(zhí)行進貨事務來為存貨量加200,用T1表示。
銷售:售出80件,需要執(zhí)行銷售事務來將存貨量減80,用T2表示。
1)丟失更新結果
如果同時發(fā)生進貨操作和銷售操作,則形成并發(fā)操作。在“進貨”讀取存貨量之后,“銷售”也讀取了同一存貨量;“進貨”修改存貨量而回寫更新后的值;“銷售”修改存貨量也回寫更新后的值。此時存貨量為“銷售”回寫的值,“進貨”對存貨量的更新丟失。例如,按圖7-1(a)所示的順序來執(zhí)行進貨與銷售的并發(fā)操作時,發(fā)生了“丟失更新”錯誤。圖7-1進貨和銷售操作并發(fā)執(zhí)行時產(chǎn)生的問題
2)讀“臟數(shù)據(jù)”
在進貨事務與銷售事務并發(fā)執(zhí)行時,如果進貨事務對數(shù)據(jù)庫更新的結果提交之前,銷售事務就使用了進貨的結果,而在進貨事務之后銷售操作又回滾,則會因銷售事務讀取了進貨操作的“臟數(shù)據(jù)”而出錯。例如,按圖7-1(b)所示的順序進行并發(fā)操作時,就產(chǎn)生了這種錯誤。
3)不可重復讀
在進貨事務讀取存貨量A之后,銷售事務執(zhí)行了對A的更新,當進貨事務再次讀取數(shù)據(jù)A(希望與第一次等值)時,得到的數(shù)據(jù)與前一次不同,這時引起的錯誤稱為“不可重復讀”。圖7-1(c)所示并發(fā)操作執(zhí)行過程中,發(fā)生了“不可重復讀”錯誤。7.3.2鎖的概念
當數(shù)據(jù)庫中多個事務并發(fā)執(zhí)行時,事務的隔離性并不總能加以保證。DBMS需要采取一定的措施對并發(fā)執(zhí)行的事務之間的相互影響加以控制。這種并發(fā)控制機制大體上分為悲觀的和樂觀的兩種。
悲觀的并發(fā)控制方法基于數(shù)據(jù)庫的一致性經(jīng)常會被破壞的認識,在事務訪問數(shù)據(jù)庫對象之前采取一定的措施加以控制,只有得到訪問許可的事務才能訪問指定的數(shù)據(jù)庫對象。為當前事務所使用的數(shù)據(jù)庫對象加鎖就是悲觀的并發(fā)控制方法。樂觀的并發(fā)控制方法基于數(shù)據(jù)庫的一致性被破壞的可能性較小的認識,允許事務執(zhí)行時直接訪問數(shù)據(jù)庫對象,只在事務結束時才驗證數(shù)據(jù)庫的一致性是否遭到破壞。基于有效性驗證的方法就是樂觀的并發(fā)控制方法。
加鎖是處理多用戶并發(fā)訪問的重要方法。鎖是一個事務防止另一個事務訪問自用資源,實現(xiàn)當前事務與其他事務并發(fā)訪問數(shù)據(jù)庫中數(shù)據(jù)的一種主要手段。基于加鎖的并發(fā)控制方法的基本思想是:當事務T需要訪問數(shù)據(jù)庫對象Q時,先申請對Q的鎖。如果經(jīng)批準得到了,則T繼續(xù)執(zhí)行,而且此后不允許其他事務修改Q,直到事務T釋放Q上的鎖為止。也就是說,當一個用戶鎖住數(shù)據(jù)庫中某個對象時,其他用戶就不能再訪問它。封鎖具有如下三個環(huán)節(jié):
(1)申請加鎖,即事務在操作前對待用的數(shù)據(jù)提出加鎖請求;
(2)獲得鎖,即當條件成熟時,事務在系統(tǒng)允許時獲得數(shù)據(jù)的控制權;
(3)釋放鎖,即事務在完成操作后放棄數(shù)據(jù)的控制權。
為了達到封鎖的目的,使用時事務應選擇合適的鎖,并應遵從一定的封鎖協(xié)議。
在DBMS中為數(shù)據(jù)庫對象加鎖時,除了能夠對不同的資源加鎖之外,還可以使用不同程度的加鎖方式,如SQLServer中可以使用共享鎖、更新鎖、結構鎖等。其中,基本鎖有兩種類型:排他鎖(ExclusiveLocks,簡稱X鎖)和共享鎖(ShareLocks,簡稱S鎖)。排他鎖又稱為獨占鎖或寫鎖。一旦事務對某個數(shù)據(jù)對象加上了排他鎖,則只允許該事務讀取和修改這個數(shù)據(jù)對象,其他任何事務既不能讀取和修改這個數(shù)據(jù)對象,也不能再對它加任何類型的鎖,直到該事務釋放這個對象上的鎖為止。
共享鎖又稱為讀鎖。如果一個事務對某個數(shù)據(jù)對象加上了共享鎖,則其他事務只能對這個數(shù)據(jù)對象再加共享鎖而不能加排他鎖,直到該事務釋放了這個數(shù)據(jù)對象上的共享鎖
為止。
封鎖方法要求每個事務都要根據(jù)自己對數(shù)據(jù)對象的操作類型(讀、寫或讀寫)向事務管理器申請適當?shù)逆i:讀操作申請S鎖,寫操作或讀寫操作申請X鎖。事務管理器收到封鎖請求后,按封鎖相容性原則判斷是否滿足該事務的加鎖請求。事務只有得到授予的鎖之后,才能繼續(xù)其操作,否則只能等待。
所謂“鎖相容”指的是:如果事務T1已持有數(shù)據(jù)對象Q的某種鎖,則當T2申請對Q的鎖時,批準T2獲得即稱為T2的申請鎖類型與T1的持有鎖類型相容;否則稱為不相容。
基本鎖類型的相容性原則是:共享鎖與共享鎖相容;排他鎖與共享鎖以及排他鎖與排他鎖都是不相容的,如圖7-2所示。圖7-2封鎖相容性矩陣7.3.3封鎖協(xié)議
1.一級封鎖協(xié)議
一級封鎖協(xié)議是:一個事務在修改數(shù)據(jù)之前,必須先對其加上自己的X鎖,直到該事務結束才釋放它。事務結束包括正常結束(提交)和非正常結束(回滾)。根據(jù)協(xié)議的要求,將圖7-3中的任務T1和T2作為事務,用A表示存貨量,重新執(zhí)行各操作的過程如圖7-3(a)所示。圖7-3封鎖操作的幾種情況
2.二級封鎖協(xié)議
二級封鎖協(xié)議的內(nèi)容包括:
(1)一級封鎖協(xié)議;
(2)任一事務在讀取數(shù)據(jù)(不修改)之前,必須先對其加上S鎖,讀完后即可釋放S鎖。
二級封鎖協(xié)議不但能夠防止丟失修改的結果,還可以進一步解決讀“臟”數(shù)據(jù)問題。但由于二級封鎖協(xié)議對數(shù)據(jù)讀完后即可釋放S鎖,故不能解決“不可重復讀”問題。例如,圖7-3(c)所示的并發(fā)操作執(zhí)行過程遵從二級封鎖協(xié)議,但卻發(fā)生了“不可重復讀”錯誤。
3.三級封鎖協(xié)議
三級封鎖協(xié)議的內(nèi)容包括:
(1)一級封鎖協(xié)議;
(2)任一事務在讀取數(shù)據(jù)(不修改)之前,必須先對其加上S鎖,直到事務結束才釋放這個S鎖。
由于三級封鎖協(xié)議強調(diào)即使事務讀完數(shù)據(jù)A之后也不釋放S鎖,從而使得其他事務無法更改數(shù)據(jù)A,因而,三級封鎖協(xié)議不但解決了丟失修改結果的問題和讀“臟”數(shù)據(jù)問題,而且防止了“不可重復讀”錯誤。
1.活鎖
如果多個事務要對同一數(shù)據(jù)對象加鎖,則可能造成某些事務永遠等待而得不到控制權,這種現(xiàn)象稱為活鎖,又稱為餓死。例如,假定:
7.4封鎖的問題及解決方法●?T1事務為R數(shù)據(jù)加了鎖,T2事務又請求為R加鎖,于是T2等待;
●?T3事務也請求為R加鎖,當T1釋放了R上的鎖之后,系統(tǒng)首先批準了T3的請求,T2仍然等待;
●?T4又請求為R加鎖,當T3釋放了R上的鎖之后,系統(tǒng)又批準了T4的請求;
……
這樣,T2可能永遠等待下去。
2.死鎖
如果兩個以上事務集合中的每個事務都在等待加鎖當前已被另一事務加鎖的數(shù)據(jù)項,從而造成多事務交錯等待的僵持局面,這種現(xiàn)象稱為死鎖。例如:
●如果T1和T2事務都需要R1和R2數(shù)據(jù),操作時T1為R1加了鎖,T2為R2加了鎖;
●?T1又請求為R2加鎖,T2又請求為R1加鎖;
●因T2已封鎖了R2,故T1等待T2釋放R2上的鎖。同理,因T1已封鎖了R1,故T2等待T1釋放R1上的鎖。由于T1和T2都沒有獲得全部需要的數(shù)據(jù),故都不會結束而只能繼續(xù)等待。
3.死鎖的預防
數(shù)據(jù)庫系統(tǒng)中,產(chǎn)生死鎖的原因是兩個或多個事務都為某些數(shù)據(jù)對象加了鎖,然后又都請求對已為其他事務加了鎖的數(shù)據(jù)對象加鎖,從而出現(xiàn)死鎖等待。防止死鎖的發(fā)生其實就是要破壞產(chǎn)生死鎖的條件。
預防死鎖通常有兩種方法。
(1)一次封鎖法:要求每個事務必須一次將所有要使用的數(shù)據(jù)全部加鎖,否則就不能繼續(xù)執(zhí)行。這種方法可以有效地防止死鎖的發(fā)生,但降低了系統(tǒng)的并發(fā)度。
(2)順序封鎖法:預先對數(shù)據(jù)對象規(guī)定一個封鎖順序,所有事務都按這個順序執(zhí)行封鎖。順序封鎖法同樣可以有效地防止死鎖,但維護眾多而且變化的資源的封鎖順序較為困難,成本較高且較難實現(xiàn)。
4.死鎖的診斷與解除
數(shù)據(jù)庫系統(tǒng)中診斷死鎖的方法與操作系統(tǒng)類似,即使用一個事務等待圖,它動態(tài)地反映所有事務的等待狀況。并發(fā)控制子系統(tǒng)周期性地(比如每隔1分鐘)檢測事務等待圖,如果發(fā)現(xiàn)圖中存在回路,則表示系統(tǒng)中出現(xiàn)了死鎖。
一般來講,死鎖是不可避免的。DBMS的并發(fā)控制子系統(tǒng)一旦檢測到系統(tǒng)中存在死鎖,就要設法解除。通常采用的方法是選擇一個處理死鎖代價最小的事務,將其撤銷,釋放此事務持有的所有的鎖,使其他事務得以繼續(xù)運行下去。當然,對撤銷的事務所執(zhí)行的數(shù)據(jù)修改操作必須加以恢復。
5.兩段鎖協(xié)議
可串行性是并行調(diào)度正確性的唯一準則,兩段鎖協(xié)議是為保證并行調(diào)度可串行性而提供的封鎖協(xié)議。
兩段封鎖協(xié)議規(guī)定:
(1)在對任何數(shù)據(jù)進行讀、寫操作之前,事務首先要獲得對該數(shù)據(jù)的封鎖。
(2)在釋放一個封鎖之后,事務不再獲得任何其他封鎖。
所謂“兩段”鎖的意思是:事務分為兩個階段,第一階段是獲得封鎖,也稱為擴展階段;第二階段是釋放封鎖,也稱為收縮階段。在一個事務中,從任何有解鎖釋放點的地方開始,如果后面還發(fā)生加鎖,就違反了兩段封鎖協(xié)議。例如,假定事務1的封鎖序列是:事務2的封鎖序列是:
SlockAUnlockASlockBXlockCUnlockCUnlockB;
則事務1遵守兩段封鎖協(xié)議,而事務2不遵守兩段封鎖協(xié)議。
如果并行執(zhí)行的所有事務都遵守兩段鎖協(xié)議,則對這些事務的所有并行調(diào)度策略都是可串行化的。因此得出結論:所有遵守兩段鎖協(xié)議的事務,其并行的結果一定是正確的。
應該注意的是:事務遵守兩段鎖協(xié)議是可串行化調(diào)度的充分條件,而不是必要條件。也就是說,可串行化的調(diào)度中,不一定所有事務都必須符合兩段封鎖協(xié)議。
6.鎖的粒度與鎖升級
關系數(shù)據(jù)庫中,加鎖的對象可以是整個數(shù)據(jù)庫,也可以是一個關系、一個元組甚至是一個元組的幾個屬性值。加鎖對象還可以是一些物理單元,如頁(數(shù)據(jù)頁或索引項)、塊等。鎖的粒度(Granularity)指的是加鎖對象的大小。鎖粒度與系統(tǒng)的并發(fā)度和并發(fā)控制的開銷密切相關。鎖粒度越小,并發(fā)度越高,系統(tǒng)開銷也越大;鎖粒度越大,并發(fā)度越低,系統(tǒng)開銷也越小。7.5.1數(shù)據(jù)庫故障的種類
1.事務內(nèi)部故障
事務程序可以發(fā)現(xiàn)某些事務內(nèi)部故障,但仍有許多非預期(未預先置入程序)故障,如運算溢出、違反了某些完整性限制,以及在并發(fā)執(zhí)行時發(fā)生死鎖而需要撤銷的事務等,往往不能被事務處理程序本身發(fā)現(xiàn)。7.5數(shù)據(jù)庫恢復技術
2.系統(tǒng)故障
系統(tǒng)故障是指那些造成系統(tǒng)停止運轉而需要重新啟動系統(tǒng)的事件,如突然停電、CPU故障、操作系統(tǒng)故障、DBMS代碼錯誤、數(shù)據(jù)庫服務器出錯以及某種誤操作等。這類故障影響正在運行的所有事務,但并未破壞數(shù)據(jù)庫。這時候,內(nèi)存中的內(nèi)容,尤其是數(shù)據(jù)庫緩沖區(qū)中的內(nèi)容都會丟失,所有事務都會非正常終止。系統(tǒng)故障主要有兩種情況:
一是發(fā)生故障時,某些尚未完成的事務的部分結果已送入物理數(shù)據(jù)庫,可能會使得數(shù)據(jù)庫處于不正確狀態(tài)。為了保證數(shù)據(jù)一致性,需要清除這些事務對數(shù)據(jù)庫的修改。因而,恢復子系統(tǒng)必須在系統(tǒng)重新啟動時讓非正常終止的事務回滾,強行撤銷(UNDO)那些未完成的事務。
二是發(fā)生故障時,有些已完成的事務的部分或者全部因尚未寫入磁盤上的物理數(shù)據(jù)庫而滯留在緩沖區(qū),故障使得這些事務對數(shù)據(jù)庫的修改部分或全部丟失,這也會使數(shù)據(jù)庫處于不一致狀態(tài)。因此,應將這些事務已提交的結果重新寫入數(shù)據(jù)庫。這就要求系統(tǒng)重新啟動后,恢復子系統(tǒng)在撤銷所有未完成事務之外,還需要重做(REDO)那些已提交的事務,使得數(shù)據(jù)庫真正恢復到一致狀態(tài)。
3.介質(zhì)故障
介質(zhì)故障指的是外存儲器的故障,如磁盤損壞、磁頭碰撞、瞬時磁場干擾等,這些是與前兩種故障(軟故障)不同的硬故障。這類故障會破壞數(shù)據(jù)庫或部分數(shù)據(jù),并影響正在存取這部分數(shù)據(jù)的那些事務。
介質(zhì)故障發(fā)生的可能性較小,但其破壞作用卻是最大的,可能會使得數(shù)據(jù)無法恢復。解決的辦法是及時進行系統(tǒng)備份并且定期進行維護。
4.計算機病毒
計算機病毒是具有破壞作用的程序,這種程序可以破壞數(shù)據(jù)、占用計算機軟件或硬件資源、妨礙計算機系統(tǒng)的正常運行并且通過極強的自我復制功能而快速“傳染”給其他應用程序或計算機系統(tǒng),使得包括數(shù)據(jù)庫系統(tǒng)在內(nèi)的計算機系統(tǒng)無法正常工作。因此,重要的數(shù)據(jù)庫系統(tǒng)應該十分重視計算機病毒的預防和清除工作。
5.用戶操作錯誤
有時候,用戶有意或無意的操作也可能刪除數(shù)據(jù)庫中的有用數(shù)據(jù)、加入錯誤數(shù)據(jù)或者造成系統(tǒng)無法正常工作,這需要通過技術(如用戶、權限管理等)、培訓以及人事制度上的綜合治理來加以保證。7.5.2數(shù)據(jù)庫恢復技術
1.數(shù)據(jù)轉儲法
DBA應該根據(jù)數(shù)據(jù)庫使用情況確定適當?shù)霓D儲周期和轉儲策略。根據(jù)轉儲時系統(tǒng)狀態(tài)的不同,可將轉儲分為靜態(tài)轉儲和動態(tài)轉儲兩種。
靜態(tài)轉儲是指在轉儲過程中,系統(tǒng)不運行其他事務而專門進行數(shù)據(jù)轉儲工作。靜態(tài)轉儲操作開始時,數(shù)據(jù)庫處于一致狀態(tài),轉儲期間不允許其他事務對數(shù)據(jù)庫進行任何存取、修改操作,數(shù)據(jù)庫仍處于一致狀態(tài)。靜態(tài)轉儲雖然簡單,并且能夠得到一個數(shù)據(jù)一致的副本,但這種轉儲必須等待正在運行的事務結束后才能進行,新的事務也必須等待轉儲結束后才能執(zhí)行,降低了數(shù)據(jù)庫的可用性。動態(tài)轉儲是指在轉儲過程中允許其他事務對數(shù)據(jù)庫進行存取或修改操作的轉儲方式。也就是說,轉儲和用戶事務并發(fā)執(zhí)行。動態(tài)轉儲時不必等待正在運行的事務結束,也不會影響新事務開始,其主要缺點是后備副本中的數(shù)據(jù)并不總是正確有效的。由于動態(tài)轉儲是動態(tài)進行的,后備副本中存儲的可能是過時的數(shù)據(jù)。因此,有必要將轉儲期間各事務對數(shù)據(jù)庫的修改活動登記下來,建立日志文件,使得通過后備副本和日志文件可將數(shù)據(jù)庫恢復到某一時刻的正確狀態(tài)。轉儲還可以分為海量轉儲和增量轉儲兩種,海量轉儲是指每次轉儲全部數(shù)據(jù)庫。這種轉儲方式可以得到后備副本并用之于方便地進行數(shù)據(jù)恢復工作。如果數(shù)據(jù)庫中的數(shù)據(jù)量大且更新頻率高,則不適合頻繁地海量轉儲。增量轉儲是指每次只轉儲上一次轉儲后更新過的數(shù)據(jù),適用于數(shù)據(jù)庫較大但事務處理卻十分頻繁的數(shù)據(jù)庫系統(tǒng)。
由于數(shù)據(jù)轉儲可在動態(tài)和靜態(tài)兩種狀態(tài)下進行,因此數(shù)據(jù)轉儲方法可以分為4類:動態(tài)海量轉儲、動態(tài)增量轉儲、靜態(tài)海量轉儲和靜態(tài)增量轉儲。
2.日志文件的內(nèi)容
不同數(shù)據(jù)庫系統(tǒng)的日志文件格式不完全相同。日志文件主要有以記錄為單位的日志文件和以數(shù)據(jù)塊為單位的日志文件。
以記錄為單位的日志文件中需要登記的內(nèi)容包括每個事務的開始(BEGINTRANSACTION)標記、結束(COMMIT或ROLLBACK)標記和所有更新操作,這些內(nèi)容均作為日志文件中的一個日志記錄(LogRecord)。對于更新操作的日志記錄,其內(nèi)容主要包括事務標識(表明是哪個事務)、操作的類型(插入、刪除或修改)、操作對象(記錄內(nèi)部標識)、更新前數(shù)據(jù)的舊值(插入操作,該項為空)及更新后數(shù)據(jù)的新值(刪除操作,該項為空)。以數(shù)據(jù)塊為單位的日志文件內(nèi)容包括事務標識和更新的數(shù)據(jù)塊。由于更新前后的各數(shù)據(jù)塊都放入了日志文件,所以操作的類型和操作對象等信息就不必放入日志記錄。
3.日志文件法
日志文件可用于事務故障恢復、系統(tǒng)故障恢復以及協(xié)助后備副本進行介質(zhì)故障恢復。如果數(shù)據(jù)庫文件被損毀,則可重新裝入后備副本而將數(shù)據(jù)庫恢復到轉儲結束時的正確狀態(tài),再通過建立的日志文件,重新執(zhí)行已完成的事務并撤銷故障發(fā)生時尚未完成的事務。這樣,不必運行應用程序即可將數(shù)據(jù)庫恢復到故障前某一時刻的正確狀態(tài)。
為了保證數(shù)據(jù)庫的可恢復性,登記日志文件時必須遵循兩條原則:一是嚴格按照事務執(zhí)行的時間次序登記;二是先寫日志文件再寫數(shù)據(jù)庫。將修改數(shù)據(jù)的結果寫入數(shù)據(jù)庫與將描述本次修改的日志記錄寫入日志文件是兩種不同的寫操作。如果這兩種寫操作只完成了一個,則有可能發(fā)生故障:
●如果先寫數(shù)據(jù)庫修改結果而未在運行記錄中登記,則以后無法恢復這個修改結果。
●如果先寫日志而未修改數(shù)據(jù)庫,則按日志文件恢復時只是多執(zhí)行一次不必要的UNDO操作,并不影響數(shù)據(jù)庫的正確性。
可見,先寫日志文件而后進行數(shù)據(jù)庫的更新操作是比較安全的。7.5.3數(shù)據(jù)庫恢復方法
1.發(fā)生事務故障時的恢復方法
如果某個事務執(zhí)行過程中發(fā)生了故障,則恢復子系統(tǒng)可以通過日志文件撤銷(UNDO)該事務對數(shù)據(jù)庫已經(jīng)做出的修改結果。這個工作是按照以下步驟進行的:
(1)反向(從后往前)掃描文件日志,查找該事務的更新操作。
(2)如果找到的是該事務的起始記錄,則UNDO結束;否則,對該事務的更新操作執(zhí)行逆操作,即將日志記錄中“更新前的值”寫入數(shù)據(jù)庫。
●如果記錄中是插入操作,則相當于做刪除操作。
●如果記錄中是刪除操作,則做插入操作。
●如果是修改操作,則相當于用修改前的值替代修改后的值。
(3)重復執(zhí)行(1)和(2),恢復該事務的其他更新操作,直至讀到該事務的開始標記為止,該事務的故障恢復工作才能完成。
事務故障的恢復通常是由系統(tǒng)自動完成的,用戶并不知曉系統(tǒng)是如何進行的。
2.發(fā)生系統(tǒng)故障時的恢復方法
系統(tǒng)的恢復是按照以下步驟進行的:
(1)正向(從頭到尾)掃描日志文件,找出那些故障發(fā)生前已經(jīng)提交的事務,將其事務標記記入重新執(zhí)行(REDO)的隊列。同時找出故障發(fā)生時尚未完成的事務,將其事務標記記入撤銷(UNDO)隊列。
注:已提交事務既有BEGINTRANSACTION記錄,也有COMMIT或ROLLBACK記錄;未完成事務只有BEGINTRANSACTION記錄而無相應的COMMIT或ROLLBACK記錄。
(2)對撤銷隊列中的各個事務進行撤銷(UNDO)處理。方法是:反向掃描日志文件,對每個事務的更新操作執(zhí)行逆操作,即將日志記錄中“更新前的值”寫入數(shù)據(jù)庫。
(3)對重新執(zhí)行隊列中的各個事務進行重新執(zhí)行(REDO)處理。方法是:正向掃描日志文件,對每個重新執(zhí)行的事務重新執(zhí)行日志文件登記操作,即將日志記錄中“更新后的值”寫入數(shù)據(jù)庫。
3.發(fā)生介質(zhì)故障時的恢復方法
介質(zhì)發(fā)生故障時,磁盤上的物理數(shù)據(jù)庫和日志文件都可能遭到破壞,這時的恢復工作最麻煩,必須重裝最新的數(shù)據(jù)庫后備副本,重新執(zhí)行該副本到發(fā)生故障之間完成的那些事務(對靜態(tài)轉儲而言)?;謴筒襟E為:
(1)恢復系統(tǒng),必要時還要更新介質(zhì)(磁盤等)。
(2)如果操作系統(tǒng)或者DBMS崩潰,則需要重新啟動系統(tǒng)。
(3)裝入最新的數(shù)據(jù)庫后備副本,使數(shù)據(jù)庫恢復到最近一次轉儲時的一致性狀態(tài)。對于動態(tài)轉儲的數(shù)據(jù)庫副本,還需要同時裝入轉儲開始時刻的日志文件副本。利用恢復系統(tǒng)故障的方法(重做?+?撤銷),才能將數(shù)據(jù)庫恢復到一致性狀態(tài)。
(4)裝入轉儲結束時刻的日志文件副本。
(5)掃描日志文件,找出故障發(fā)生時提交的事務,加入REDO隊列。
(6)重新執(zhí)行REDO隊列中的事務。
通過日志文件法進行數(shù)據(jù)庫恢復時,恢復子系統(tǒng)必須搜索所有的日志來確定哪些事務需要重新執(zhí)行。
1.實驗任務與目的
(1)在SQLServer的查詢編輯器中編寫代碼,在單個批處理中實現(xiàn)一個事務。了解事務的概念以及事務與批處理的關系。
(2)在SQLServerManagementStudio中創(chuàng)建一個數(shù)據(jù)庫的完整備份,再還原該數(shù)據(jù)庫。掌握創(chuàng)建和和使用數(shù)據(jù)庫備份的方法。實驗7事務管理與數(shù)據(jù)庫備份
2.預備知識
(1)本實驗涉及本章中以下內(nèi)容:
●事務的概念、基本特征以及基本操作方法。
●?SQLServer中的事務以及批處理的語法。
●封鎖機制的概念以及死鎖的診斷方法。
●數(shù)據(jù)庫故障的種類以及數(shù)據(jù)庫恢復技術的知識。
(2)?SQLServer鎖的類型及其控制。
SQLServer的基本鎖是S(共享)鎖和X(排他)鎖?;炬i之外還有三種鎖:意向鎖、修改鎖和模式鎖,這幾種鎖由SQLServer系統(tǒng)自動控制。
SQLServer一般都會自動提供加鎖功能,例如:
●在SELECT語句訪問數(shù)據(jù)庫時,系統(tǒng)自動使用共享鎖訪問數(shù)據(jù);使用INSERT、DELETE和UPDATE語句添加、修改和刪除數(shù)據(jù)時,系統(tǒng)自動為所使用的數(shù)據(jù)加上排他鎖。
●系統(tǒng)用意向鎖將鎖分別按行級鎖層、頁級鎖層和表級鎖層設置,使得多個鎖之間的沖突最小化。
●在系統(tǒng)修改一個頁(內(nèi)存中固定大小的一塊數(shù)據(jù),常與外存中一個扇區(qū)大小相同)時,自動加修改鎖(與共享鎖兼容),修改過后上升為排他鎖。
●在操作涉及到引用表或索引時,自動提供模式鎖(鎖住正在使用的表等對象的結構)和修改鎖(通知其他用戶當前用戶正在修改數(shù)據(jù))。
SQLServer自動使用與任務相應的等級鎖來鎖定資源對象,以使鎖的成本最小化。用戶對鎖機制有所了解即可,使用時不涉及鎖的操作。可以認為SQLServer的封鎖機制對用戶是透明的。
(3)死鎖原理與SQLServer中的排查。
計算機操作系統(tǒng)中將死鎖定義為:一級進程中的各個進程均占有不會釋放的資源,但因互相申請被其他進程占用而不會釋放的資源,從而形成的一種永久等待狀態(tài)。SQLServer中,如果兩個或兩個以上任務都鎖定了其他任務試圖鎖定的資源,則會造成這些任務永久阻塞,從而出現(xiàn)死鎖。
使用SQLServer的存儲過程sp_who查看數(shù)據(jù)庫里的活動用戶和進程的情況;使用sp_lock查看當前數(shù)據(jù)庫中鎖的情況,通過objectID(@objID)還可以查看哪個資源被鎖。
SQLServer內(nèi)部有一個鎖監(jiān)視器線程執(zhí)行死鎖檢查,鎖監(jiān)視器對特定線程啟動死鎖檢查時,標識線程正在等待的資源,然后查找特定資源的所有者并遞歸地繼續(xù)執(zhí)行對那些線程的死鎖搜索,直到找到一個構成死鎖條件的循環(huán)。檢測到死鎖后,數(shù)據(jù)庫引擎選擇一個回滾時開銷最小的事務進行回滾并釋放該事務持有的所有鎖,使得其他線程的事務可以請求資源并繼續(xù)運行。實驗7.1實現(xiàn)事務
1.編輯創(chuàng)建事務的代碼
在SQLServerManagementStudio中,展開dbCourses數(shù)據(jù)庫所在的服務器結點,再展開其中的“數(shù)據(jù)庫”結點,選定dbCourses結點;單擊工具欄上的“新建查詢”按鈕,打開查詢編輯器窗口并在其中輸入以下代碼:
BEGINTRANSACTION
INSERTINTO班級(班號,班名,專業(yè)號,人數(shù))
VALUES('20123001','應數(shù)21','68',28)
IF@@ERROR=0BEGIN
PRINT'班級表中插入了一條記錄'
UPDATE學生
SET班號='20123001'
WHERE班號='12345678'
DELETE專業(yè)
WHERE學院號='19'
COMMITTRANSACTIONEND
ELSEBEGIN
PRINT'班級表中插入記錄失敗,回滾事務'
ROLLBACKTRANSACTION
END
2.執(zhí)行事務
單擊!按鈕執(zhí)行這一段程序,如果發(fā)生錯誤,據(jù)此修改數(shù)據(jù)庫中相應數(shù)據(jù),直到運行通過為止。實驗7.2檢測死鎖
1.編輯創(chuàng)建兩個表的代碼
在SQLServerManagementStudio中,展開服務器結點,再展開其中的“數(shù)據(jù)庫”結點,選定某個數(shù)據(jù)庫結點;單擊工具欄上的“新建查詢”按鈕,打開查詢編輯器窗口并在其中輸入以下代碼:
usedbCourses
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 私定終身合同范例
- 個人代理銷售傭金合同范例
- 裝修粉刷合同范例
- 總價合同施工合同范例
- 電梯管理合同范例
- 鍋爐就位合同范例
- 提前解聘合同范例
- 餐飲臨時試用合同范例
- 公司管理協(xié)議合同范例
- 電子勞動合同范例
- 急診科診療常規(guī)
- 產(chǎn)品外觀檢驗標準(通用)
- 股東協(xié)議明確約定投資人不參與經(jīng)營管理
- 丹麥門薩權威IQ測試(附參考答案)
- 電氣試驗110kV交接試驗細則
- 外立面裝修改造工程施工方案(79頁)
- 汽車吊接地比壓計算
- 跨國公司財務管理課后習題答案
- 人教版(2019)高一物理必修第三冊 13.5能量量子化 課件(共18張PPT)
- 溝槽管件尺寸對照表
- 美術教案雄偉的塔教學反思
評論
0/150
提交評論