資料庫--事務Transaction
一、事務的概念:
事務(Transaction)是指邏輯上的一組操作,事務是用於保證資料的唯一性,它由一組相關的DML語句組成,該DML語句要麼全部成功,要麼全部失敗。這些操作
是一個不可分割的工作單位,是DB環境中的邏輯工作單位。事務是為了保證資料庫的完整性,事務不能巢狀。
事務的管理:預設的情況下,資料庫會自動的管理事務,管理的方式是一條語句就獨佔一個事務。如果要自己控制事務也可以通過如下的命令開啟、提交、回滾事務
開啟事務:start transaction
提交事務:commit
回滾事務:rollback
JDBC中事務管理:
conn.setAutoCommit(false);
conn.commit();
conn.rollback();
SavePoint sp = conn.setSavePoint();
conn.rollback(sp);
二、事務的四大特性:ACID
一個事務具有的最基本的特性,一個設計良好的資料庫可以幫我們保證事務的這四大特性(ACID)
1.原子性(Automic):事務是一個不可分割的工作單位,事務中的操作要麼都不發生,要麼都發生。
2.一致性(Consistent):如果事務執行之前資料庫是一個完整性的狀態,那麼事務結束之後,無論事務是否執行成功,資料庫仍然是一個完整性的狀態。
【資料庫的完整性狀態】:單一個數據庫中的所有的資料都符合資料庫中所定義的所有的約束,此時可稱資料庫是一個完整性狀態。
3.隔離性(Isolation):事務的隔離性是指多個使用者併發訪問資料庫時,一個使用者的資料不能被其他使用者的事務所幹擾,多個併發事務之間資料要相互隔離。
4.永續性(Duration):永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何的影響。
三、資料庫的事務隔離機制:
1.隔離性:事務的隔離性,在事務中,多個執行緒操作同一張表相同的記錄時,每個執行緒要相互的隔離。那麼資料庫如何設計才能保證呢?如果將資料庫設計成單執行緒
的資料庫,可以防止所有的執行緒安全問題,自然就保證了資料庫的隔離性,但是如果資料庫設計成單執行緒的,那麼面對高併發的資料訪問時,這種資料的效率就是非常
低效的。
2.資料庫中的鎖機制:
第一種方式:
A.共享鎖:----S鎖:只讀事務
B.互斥鎖:----X鎖:任何操作都不能做
第二種方式:
A.行級鎖:鎖住表的一行
B.表級鎖:
a.行級共享鎖:可以執行查詢
b.行級互斥鎖:要等鎖釋放才可以執行操作
3.共享鎖和互斥鎖:
A.共享鎖:
在非Serializable隔離級別做查詢不加任何鎖,而在Serializable隔離級別下做的查詢加上共享鎖。
共享鎖的特點:共享鎖和共享鎖可以共存,但是共享鎖和互斥鎖不能共存
B.互斥鎖:
在所有隔離級別下進行增刪改的操作都會加互斥鎖
互斥鎖的特點:和任意的其他鎖都不能共存
4.隔離機制
如果兩個執行緒併發修改,一定會出現問題,這是必須要利用鎖機制來防止多個執行緒併發的修改資料;如果是兩個執行緒併發的查詢資料,沒有執行緒安全問題。上
面兩種都是極端的情況,如果是兩個執行緒中,一個修改,一個查詢,那麼就會出現不同的情況:
a.髒讀:一個事務讀取到了另一事務未提交的資料
b.不可重複讀:在一個事務內讀取到表中的某一行資料,多次讀取的結果不同(行級別的問題)
c.幻讀(虛讀):在一個事務內讀取到了別的事務插入的資料,導致前後讀取的資料不一致(表級別的問題)
針對上面的三種情況,都違背了資料庫的隔離性,對於髒讀和不可重複讀,強調的是內容的改變,而對於虛讀強調的是數量的變化。
由於事務的隔離性會出現不同的情況,所以資料庫的設計者就提供了不同的隔離機制來供使用資料庫的使用者來對自己的特殊情況作出自己的選擇,所以資料庫
設計者提供了一下四種事務的隔離級別:
a.Read uncommitted ==不防止任何隔離性問題,會出現髒讀,不可重複讀,虛讀問題
b.Read committed == 可以防止髒讀問題,但是不能防止不可重複讀和虛讀問題
c.Repeatable read == 可以防止髒讀和不可重複讀問題,但是不能避免虛讀問題
d.Serializable ==此種機制,相當於將資料庫設計成單執行緒資料庫,可以防止上面的任何隔離性問題
四種隔離機制的比較:
從安全性考慮:Serializable > Repeatable read >Read committed > Read uncommitted
從效率上考慮:Read uncommited > Read committed > Repeatable read > Serializable
對於要使用資料庫的時候,要根據自己使用資料庫的需求,綜合分析對安全性和效率的要求,選擇一個隔離級別使資料庫執行在這個隔離級別上。
不同的資料庫對預設的事務隔離級別是不同的:mysql 預設隔離級別是 Repeatable read隔離級別,而對於Oracle 預設的隔離級別是Read committed。
5.查詢隔離機制:
a.查詢當前資料庫的隔離級別:
Select @@tx_isolation;
b.設定隔離級別:
Set [global/session] transaction isolation level xxx;
注意:其中如果不寫設定的物件是globle或session則預設是session。session是指修改當前客戶端和資料庫互動時的隔離級別,而如果使用global,則修改的
是資料庫的預設隔離級別。
四、樂觀鎖和悲觀鎖
問題引出:兩個執行緒基於同一個查詢結果進行修改,後修改的人會將修改人的修改記錄覆蓋掉。
1. 樂觀鎖:樂觀鎖會樂觀的認為每次查詢都不會造成更新丟失,利用一個版本欄位進行控制。
2.悲觀鎖:悲觀鎖悲觀的認為每一次操作都會造成更新丟死問題,在每次查詢時就加上互斥鎖。
總結:
對於查詢非常多,修改非常少,使用樂觀鎖
對於修改非常多,查詢非常少,使用悲觀鎖