資料庫的事務,是指作為單個邏輯工作單元執行的一系列操作。 事務處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向資料的資源。通過將一組相關操作組合為乙個要麼全部成功要麼全部失敗的單元,可以簡化錯誤恢復並使應用程式更加可靠。乙個邏輯工作單元要成為事務,必須滿足所謂的acid(原子性、一致性、隔離性和永續性)屬性。
操作流程
設想網上購物的一次交易,其付款過程至少包括以下幾步資料庫操作:
· 更新客戶所購商品的庫存資訊
· 儲存客戶付款資訊--可能包括與銀行系統的互動
· 生成訂單並且儲存到資料庫中
· 更新使用者相關資訊,例如購物數量等等
正常的情況下,這些操作將順利進行,最終交易成功,與交易相關的所有資料庫資訊也成功地更新。但是,如果在這一系列過程中任何乙個環節出了差錯,例如在更新商品庫存資訊時發生異常、該顧客銀行帳戶存款不足等,都將導致交易失敗。一旦交易失敗,資料庫中所有資訊都必須保持交易前的狀態不變,比如最後一步更新使用者資訊時失敗而導致交易失敗,那麼必須保證這筆失敗的交易不影響資料庫的狀態--庫存資訊沒有被更新、使用者也沒有付款,訂單也沒有生成。否則,資料庫的資訊將會一片混亂而不可**。
資料庫事務正是用來保證這種情況下交易的平穩性和可**性的技術。
資料庫事務的acid屬性
原子性(atomic)
事務必須是原子工作單元;對於其資料修改,要麼全都執行,要麼全都不執行。通常,與某個事務關聯的操作具有共同的目標,並且是相互依賴的。如果系統只執行這些操作的乙個子集,則可能會破壞事務的總體目標。原子性消除了系統處理操作子集的可能性。
一致性(consistent)
事務在完成時,必須使所有的資料都保持一致狀態。在相關資料庫中,所有規則都必須應用於事務的修改,以保持所有資料的完整性。事務結束時,所有的內部資料結構(如 b 樹索引或雙向鍊錶)都必須是正確的。某些維護一致性的責任由應用程式開發人員承擔,他們必須確保應用程式已強制所有已知的完整性約束。例如,當開發用於轉帳的應用程式時,應避免在轉帳過程中任意移動小數點。
隔離性(insulation)
由併發事務所作的修改必須與任何其它併發事務所作的修改隔離。事務檢視資料時資料所處的狀態,要麼是另一併發事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會檢視中間狀態的資料。這稱為可序列性,因為它能夠重新裝載起始資料,並且重播一系列事務,以使資料結束時的狀態與原始事務執行的狀態相同。當事務可序列化時將獲得最高的隔離級別。在此級別上,從一組可並行執行的事務獲得的結果與通過連續執行每個事務所獲得的結果相同。由於高度隔離會限制可並行執行的事務數,所以一些應用程式降低隔離級別以換取更大的吞吐量。防止資料丟失
永續性(durability)
事務完成之後,它對於系統的影響是永久性的。該修改即使出現致命的系統故障也將一直保持。
乙個資料庫可能擁有多個訪問客戶端,這些客戶端都可以併發方式訪問資料庫。資料庫中的相同資料可能同時被多個事務訪問,如果沒有採取必要的隔離措施,就會導致各種併發問題,破壞資料的完整性。
這些問題可以歸結為5類,包括3類資料讀問題(髒讀、幻象讀和不可重複讀)以及2類資料更新問題(第一類丟失更新和第二類丟失更新)。
下面,我們分別通過例項講解引發問題的場景。
髒讀(dirty read)
在講解髒讀前,我們先講乙個笑話:乙個有結巴的人在飲料店櫃檯前轉悠,老闆很熱情地迎上來:「喝一瓶?」,結巴連忙說:「我…喝…喝…」,老闆麻利地開啟易拉罐遞給結巴,結巴終於憋出了他的那句話:「我…喝…喝…喝不起啊!」。在這個笑話中,飲料店老闆就對結巴進行了髒讀。
a事務讀取b事務尚未提交的更改資料,並在這個資料的基礎上操作。如果恰巧b事務回滾,那麼a事務讀到的資料根本是不被承認的。來看取款事務和轉賬事務併發時引發的髒讀場景:
時間
轉賬事務a
取款事務b
t1
開始事務
t2
開始事務
t3
查詢賬戶餘額為1000元
t4
取出500元把餘額改為500元
t5
查詢賬戶餘額為500元(髒讀)
t6
撤銷事務餘額恢復為1000元
t7
匯入100元把餘額改為600元
t8
提交事務
在這個場景中,b希望取款500元而後又撤銷了動作,而a往相同的賬戶中轉賬100元,就因為a事務讀取了b事務尚未提交的資料,因而造成賬戶白白丟失了500元。
不可重複讀(unrepeatable read)
不可重複讀是指a事務讀取了b事務已經提交的更改資料。假設a在取款事務的過程中,b往該賬戶轉賬100元,a兩次讀取賬戶的餘額發生不一致:
時間
取款事務a
轉賬事務b
t1
開始事務
t2
開始事務
t3
查詢賬戶餘額為1000元
t4
查詢賬戶餘額為1000元
t5
取出100元把餘額改為900元
t6
提交事務
t7
查詢賬戶餘額為900元(和t4讀取的不一致)
在同一事務中,t4時間點和t7時間點讀取賬戶存款餘額不一樣。
幻象讀(phantom read)
a事務讀取b事務提交的新增資料,這時a事務將出現幻象讀的問題。幻象讀一般發生在計算統計資料的事務中,舉乙個例子,假設銀行系統在同乙個事務中,兩次統計存款賬戶的總金額,在兩次統計過程中,剛好新增了乙個存款賬戶,並存入100元,這時,兩次統計的總金額將不一致:
時間
統計金額事務a
轉賬事務b
t1
開始事務
t2
開始事務
t3
統計總存款數為10000元
t4
新增乙個存款賬戶,存款為100元
t5
提交事務
t6
再次統計總存款數為10100元(幻象讀)
如果新增資料剛好滿足事務的查詢條件,這個新資料就進入了事務的視野,因而產生了兩個統計不一致的情況。
幻象讀和不可重複讀是兩個容易混淆的概念,前者是指讀到了其它已經提交事務的新增資料,而後者是指讀到了已經提交事務的更改資料(更改或刪除),為了避免這兩種情況,採取的對策是不同的,防止讀取到更改資料,只需要對操作的資料新增行級鎖,阻止操作中的資料發生變化,而防止讀取到新增資料,則往往需要新增表級鎖——將整個表鎖定,防止新增資料。
第一類丟失更新
a事務撤銷時,把已經提交的b事務的更新資料覆蓋了。這種錯誤可能造成很嚴重的問題,通過下面的賬戶取款轉賬就可以看出來:
時間
取款事務a
轉賬事務b
t1
開始事務
t2
開始事務
t3
查詢賬戶餘額為1000元
t4
查詢賬戶餘額為1000元
t5
匯入100元把餘額改為1100元
t6
提交事務
t7
取出100元把餘額改為900元
t8
撤銷事務
t9
餘額恢復為1000元(丟失更新)
a事務在撤銷時,「不小心」將b事務已經轉入賬戶的金額給抹去了。
第二類丟失更新
a事務覆蓋b事務已經提交的資料,造成b事務所做操作丟失:
時間
轉賬事務a
取款事務b
t1
開始事務
t2
開始事務
t3
查詢賬戶餘額為1000元
t4
查詢賬戶餘額為1000元
t5
取出100元把餘額改為900元
t6
提交事務
t7
匯入100元
t8
提交事務
t9
把餘額改為1100元(丟失更新)
上面的例子裡由於支票轉賬事務覆蓋了取款事務對存款餘額所做的更新,導致銀行最後損失了100元,相反如果轉賬事務先提交,那麼使用者賬戶將損失100元。
四類資料完整性:
資料庫知識點
1.truncate delete和drop delete delete是一行行刪除資料,不影響表結構,並且會記錄日誌,可以進行回滾。truncate 刪除表中所有資料,不記錄日誌,不可以回滾,truncate之後表空間和索引大小會回到初始值。所以truncate之前最好備份 drop 刪除整個表結...
資料庫知識點
oracle 安裝oracle時需要的所需的軟體包安裝命令 yum install binutils compat libcap1 gcc glibc ksh libaio libgcc libstdc libxi libxtst make sysstat 1 建使用者create user ora...
資料庫知識點
12頁表必須多看幾遍 長度為 n 個位元組的固定長度且非 unicode 的字元資料。n 必須是乙個介於 1 和 8,000 之間的數值。儲存大小為 n 個位元組。char 在 sql 92 中的同義詞為 character。2 varchar n 長度為 n 個位元組的可變長度且非 unicode...