acid
ACID,指數據庫事務正確執行的四個基本要素的縮寫。包含:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。一個支持事務(Transaction)的數據庫係統,必需要具有這四種特性,否則在事務過程(Transaction processing)當中無法保證數據的正確性,交易過程極可能達不到交易方的要求。
回滾
刪除由一個或多個部分完成的事務執行的更新。為在應用程序、數據庫或係統錯誤後還原數據庫的完整性,需要使用回滾。1 事務並發處理(麵試的意義更大)
a) 事務:ACID
i. Atomic ConsistencyItegrity Durability
b) 事務並發時可能出現的問題:
第一類丟失更新(Lost Update)
時間 |
取款事務A |
存款事務B |
T1 |
開始事務 |
|
T2 |
|
開始事務 |
T3 |
查詢賬戶餘額為1000元 |
|
T4 |
|
查詢賬戶餘額為1000元 |
T5 |
|
匯入100元把餘額改為1100元 |
T6 |
|
提交事務 |
T7 |
取出100元把餘額改為900 元 |
|
T8 |
撤銷事務 |
|
T9 |
餘額恢複為1000元(丟失更新) |
|
dirtyread髒讀(讀到了另一個事務在處理中還未提交的數據)
時間 |
取款事務A |
存款事務B |
T1 |
開始事務 |
|
T2 |
|
開始事務 |
T3 |
|
查詢賬戶餘額為1000元 |
T4 |
|
匯入100元把餘額改為1100元 |
T5 |
查詢賬戶餘額為1100元(讀取髒數據) |
|
T6 |
|
回滾 |
T7 |
取款1100 |
|
T8 |
提交事務失敗 |
|
non-repeatableread 不可重複讀
時間 |
取款事務A |
存款事務B |
T1 |
開始事務 |
|
T2 |
|
開始事務 |
T3 |
查詢賬戶餘額為1000元 |
|
T5 |
|
匯入100元把餘額改為1100元 |
T5 |
|
提交事務 |
T6 |
查詢帳戶餘額為1100元 |
|
T8 |
提交事務 |
|
secondlost update problem 第二類丟失更新(不可重複讀的特殊情況)
時間 |
取款事務A |
存款事務B |
T1 |
|
開始事務 |
T2 |
開始事務 |
|
T3 |
|
查詢賬戶餘額為1000元 |
T4 |
查詢賬戶餘額為1000元 |
|
T5 |
|
取出100元把餘額改為900元 |
T6 |
|
提交事務 |
T7 |
匯入100元 |
|
T8 |
提交事務 |
|
T9 |
把餘額改為1100元(丟失更新) |
|
phantomread 幻讀
時間 |
查詢學生事務A |
插入新學生事務B |
T1 |
開始事務 |
|
T2 |
|
開始事務 |
T3 |
查詢學生為10人 |
|
T4 |
|
插入1個學生 |
T5 |
查詢學生為11人 |
|
T6 |
|
提交事務 |
T7 |
提交事務 |
|
c) 數據庫的事務隔離機製
i. 查看 java.sql.Connection 文檔
ii. 1:read-uncommitted 2:read-committed 4:repeatable read 8:serializable(數字代表對應值)
為什麼取值要使用 1 2 4 8而不是 1 2 3 4
1=0000 2=0010 4=01008=1000(位移計算效率高)
1. 隻要數據庫支持事務,就不可能出現第一類丟失更新
2. read-uncommitted(允許讀取未提交的數據) 會出現dirty read, phantom-read,
non-repeatableread 問題
3. read-commited(讀取已提交的數據項目中一般都使用這個)不會出現dirty read,因為隻有另
一個事務提交才會讀出來結果,但仍然會出現 non-repeatable read 和 phantom-read
使用read-commited機製可用悲觀鎖樂觀鎖來解決non-repeatable read和 phantom-read問題
4. repeatableread(事務執行中其他事務無法執行修改或插入操作 較安全)
5. serializable解決一切問題(順序執行事務不並發,實際中很少用)
d) 設定hibernate的事務隔離級別(使用hibernate.connection.isolation配置取值1、2、4、8)
i. hibernate.connection.isolation= 2(如果不設 默認依賴數據庫本身的級別)
ii. 用悲觀鎖解決repeatable read的問題(依賴於數據庫的鎖)
(詳見項目 hibernate_3100_Hibernate_Concurrency_Pessimistic_Lock)
1. select ... for update
2. 使用另一種load方法--load(xx.class , i , LockMode.Upgrade)
a) LockMode.None無鎖的機製,Transaction結束時,切換到此模式
b) LockMode.read在査詢的時候hibernate會自動獲取鎖
c) LockMode.write insert updatehibernate 會自動獲取鎖
d) 以上3種鎖的模式,是hibernate內部使用的(不需要設)
e) LockMode.UPGRADE_NOWAIT是 ORACLE 支持的鎖的方式
e) Hibernate(JPA)樂觀鎖定(ReadCommitted)
(詳見項目hibernate_3200_Hibernate_Concurrency_Optimistic_Lock)
實體類中增加version屬性(數據庫也會對應生成該字段,初始值為0),並在其get方法前加
@Version注解,則在操作過程中沒更新一次該行數據則version值加1,即可在事務提交前判斷該數據是否被其他事務修改過.
@Version
時間 |
轉賬事務A |
取款事務B |
T1 |
|
開始事務 |
T2 |
開始事務 |
|
T3 |
查詢學生為10人 |
查詢賬戶餘額為1000 version=0 |
T4 |
查詢賬戶餘額為1000 version=0 |
|
T5 |
|
取出100 把餘額改為900 version=1 |
T6 |
|
提交事務 |
T7 |
匯入100元 |
|
T8 |
提交事務 ? version>0 throw Exception |
|
T9 |
把餘額改為1100元(丟失更新) |
|
最後更新:2017-04-02 16:48:17