資料庫事務 ACID屬性、資料庫并發問題和四種隔離級別
資料庫事務
資料庫事務是一組邏輯操作單元,使資料從一種狀態變換到另一種狀態
一組邏輯操作單元;一個或多個DML操作
事務處理原則
保證所有事務都作為一個作業單元來執行,即使出現故障,都不能改變這種執行方式,
一個事務執行多次操作時,要么所有事務都被提交,則永久保存;要么放棄所有修改,整個事務回滾到最初狀態
資料一旦提交,則不可回滾
那些操作會導致自動提交
DDL操作一旦執行,都會自動提交
DML默認情況下,一旦執行,就會自動提交
可以通過set autocommit = false的方式取消DML自動提交
默認在關閉連接時,會自動提交資料
ACID屬性
事務必須滿足四個屬性,即原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability),即ACID四種屬性,
原子性
一個事務是一個不可分割的整體,為了保證事務的總體目標,事務必須具有原子性,即當資料修改時,要么全都執行,要么全都不執行,即,不允許事務部分地完成,避免了只執行這些操作的一部分而帶來的錯誤,
一致性
一個事務在執行之前和執行之后,資料庫資料必須保持一致性,資料庫的一致性狀態應該滿足模式鎖指定的約束條件,那么在完整執行該事務后,資料庫仍然處于一致性狀態,
例如:銀行轉賬,轉賬前后兩個賬戶金額之和應保持不變,
隔離性
由并發事務所作的修改必須與任何其它并發事務所作的修改隔離,事務查看資料庫時資料所處的狀態,要么是另一并發事務修改它之前的狀態,要么是另一事務修改它之后的狀態,事務不會查看中間狀態的資料,
例如:對任何一對事務T1和T2,對T1而言,T2要么在T1開始之前已經結束,要么在T1完成之后再開始執行,
持久性
也被稱為永久性,事務完成以后,DBMS(資料庫管理系統)保證它對資料庫中資料的修改是永久性的,當系統或介質發生故障時,該修改也永久保持,持久性一般通過資料庫備份與恢復來保證,
- 注意 嚴格而言,資料庫事務屬性都是由資料庫管理系統來進行保證的,在整個應用程式的運行程序中,應用程式無須去考慮資料庫的ACID實作,
一般情況下,通過執行COMMIT(提交)或ROLLBACK(回滾)陳述句來終止事務,當執行COMMIT陳述句時,自從事務啟動以來對資料庫所做的一切更改就成為永久性的,即被寫入到磁盤,而當執行ROLLBACK陳述句時,自從事務啟動以來對資料庫所做的一切更改都會被撤銷,并且資料庫中內容回傳到事務開始之前所處的狀態,無論什么情況,在事務完成時,都能保證回到一致性狀態,
資料庫并發問題
如果沒有鎖定且多個用戶同時訪問一個資料庫,則當他們的事務同時使用相同的資料時可能會發生問題,由于并發操作帶來的資料不一致性包括:丟失資料更新、讀“臟”資料(臟讀)、不可重復讀,
更新丟失
- 兩個事務都同時更新一行資料,一個事務對資料的更新把另一個事務對資料的更新覆寫了,這是因為系統沒有執行任何的鎖操作,因此并發并沒有被隔離開來,
臟讀
- 一個事務讀取到了另一事務未提交的資料操作結果,這是相當危險的,因為很可能所有的操作都被回滾,
不可重復讀
- 不可重復讀(Non-repeatable Reads):一個事務對同一行資料重復讀取兩次,但是卻得到了不同的結果,
包括以下情況:
- 虛讀:事務T1讀取某一資料后,事務T2對其做了修改,當事務T1再次讀取該資料時得到與前一次不同的值,
- 幻讀:事務在操作程序中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的資料或者缺少了第一次查詢中出現的資料,這是因為在兩次查詢程序中有另外一個事務插入資料造成的,
資料庫事務的四種隔離級別
資料庫事務的隔離級別有4個,由低到高依次為Read uncommitted 、Read committed 、Repeatable read 、Serializable ,這四個級別可以逐個解決臟讀 、不可重復讀 、幻讀這幾類問題,
不同的隔離級別對事務的處理不同,
- 讀未提交資料(Read Uncommitted):只處理更新丟失,如果一個事務已經開始寫資料,則不允許其他事務同時進行寫操作,但允許其他事務讀此行資料,可通過“排他寫鎖”實作,
- 讀已提交資料(Read Committed):處理更新丟失、臟讀,讀取資料的事務允許其他事務繼續訪問改行資料,但是未提交的寫事務將會禁止其他事務訪問改行,可通過“瞬間共享讀鎖”和“排他寫鎖”實作,
- 可重復讀取(Repeatable Read):處理更新丟失、臟讀和不可重復讀取,讀取資料的事務將會禁止寫事務,但允許讀事務,寫事務則禁止任何其他事務,可通過“共享讀鎖”和“排他寫鎖”實作,
- 序列化(串行化)(Serializable):提供嚴格的事務隔離,要求失去序列化執行,事務只能一個接一個地執行,不能并發執行,僅僅通過“行級鎖”是無法實作事務序列化的,必須通過其他機制保證新插入的資料不會被剛執行查詢操作的事務訪問到,
隔離級別越高,越能保證資料的完整性和統一性,但是對并發性能的影響也越大,對于多數應用程式,可以優先考慮把資料庫系統的隔離級別設為Read Committed,它能夠避免臟讀,而且具有較好的并發性能,盡管它會導致不可重復讀、幻讀和第二類丟失更新這些并發問題,在可能出現這類問題的個別場合,可以由應用程式采用悲觀鎖或樂觀鎖來控制,

- Oracle 支持的 2 種事務隔離級別:READ COMMITED, SERIALIZABLE. Oracle 默認的事務隔離級別為: READ COMMITED
- Mysql 支持 4 中事務隔離級別. Mysql 默認的事務隔離級別為: REPEATABLE READ
事務隔離級別設定
//查看當前事物級別:
SELECT @@tx_isolation;
//設定mysql的隔離級別:
//set session transaction isolation level 設定事務隔離級別
//設定read uncommitted級別:
set session transaction isolation level read uncommitted;
//設定read committed級別:
set session transaction isolation level read committed;
//設定repeatable read級別:
set session transaction isolation level repeatable read;
//設定serializable級別:
set session transaction isolation level serializable;
Java代碼獲取和設定隔離級別(下文conn為Connection 物件,具體實作不做整理)
//獲取資料庫事務隔離級別
int transactionIsolation = conn.getTransactionIsolation();
//設定資料庫事務隔離級別;事務隔離級別:TRANSACTION_READ_COMMITTED
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/266967.html
標籤:MySQL
