一,事務的4個基本特征
Atomic(原子性):
事務中包含的操作被看做一個邏輯單元,這個邏輯單元中的操作要
么全部成功,要么全部失敗。
Consistency(一致性):
只有合法的數(shù)據(jù)可以被寫入數(shù)據(jù)庫,否則事務應該將其回滾到最初
狀態(tài)。
Isolation(隔離性):
事務允許多個用戶對同一個數(shù)據(jù)進行并發(fā)訪問,而不破壞數(shù)據(jù)的正
確性和完整性。同時,并行事務的修改必須與其他并行事務的修改
相互獨立。
Durability(持久性):
事務結束后,事務處理的結果必須能夠得到固化。
以上屬于廢話
二,為什么需要對事務并發(fā)控制
如果不對事務進行并發(fā)控制,我們看看數(shù)據(jù)庫并發(fā)操作是會有那些異常情形
Lost update:
兩個事務都同時更新一行數(shù)據(jù),但是第二個事務卻中途失敗退出,
導致對數(shù)據(jù)的兩個修改都失效了。
Dirty Reads:
一個事務開始讀取了某行數(shù)據(jù),但是另外一個事務已經(jīng)更新了此數(shù)
據(jù)但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作
都被回滾。
Non-repeatable Reads:
一個事務對同一行數(shù)據(jù)重復讀取兩次,但是卻得到了不同的結果。
Second lost updates problem:
無法重復讀取的特例。有兩個并發(fā)事務同時讀取同一行數(shù)據(jù),然后其
中一個對它進行修改提交,而另一個也進行了修改提交。這就會造成
第一次寫操作失效。
Phantom Reads:
事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查
詢中未出現(xiàn)的數(shù)據(jù)(這里并不要求兩次查詢的SQL語句相同)。這是
因為在兩次查詢過程中有另外一個事務插入數(shù)據(jù)造成的。
三, 數(shù)據(jù)庫的隔離級別
為了兼顧并發(fā)效率和異??刂?,在標準SQL規(guī)范中,定義了4個事務隔
離級別,(ORACLE和SQLSERER對標準隔離級別有不同的實現(xiàn) )
Read Uncommitted:
直譯就是"讀未提交",意思就是即使一個更新語句沒有提交,但是別
的事務可以讀到這個改變.這是很不安全的.
Read Committed:
直譯就是"讀提交",意思就是語句提交以后即執(zhí)行了COMMIT以后
別的事務就能讀到這個改變.
Repeatable Read:
直譯就是"可以重復讀",這是說在同一個事務里面先后執(zhí)行同一個
查詢語句的時候,得到的結果是一樣的.
Serializable:
直譯就是"序列化",意思是說這個事務執(zhí)行的時候不允許別的事務
并發(fā)執(zhí)行.
四,隔離級別對并發(fā)的控制
下表是各隔離級別對各種異常的控制能力。
LU DR NRR SLU PR
RU Y Y Y Y Y
RC N N Y Y Y
RR N N N N Y
S N N N N N
(注:LU:丟失更新;DR:臟讀;NRR:非重復讀;SLU:二類丟失更新;PR:幻像讀)
順便舉一小例。
MS_SQL:
--事務一 set transaction isolation level serializable begin tran insert into test values('xxx') --事務二 set transaction isolation level read committed begin tran select * from test --事務三 set transaction isolation level read uncommitted begin tran select * from test
在查詢分析器中執(zhí)行事務一后,分別執(zhí)行事務二,和三。結果是事務二會等待,而事務三則會執(zhí)行。
ORACLE:
--事務一 set transaction isolation level serializable; insert into test values('xxx'); select * from test; --事務二 set transaction isolation level read committed--ORACLE默認級別 select * from test
執(zhí)行事務一后,執(zhí)行事務二。結果是事務二只讀出原有的數(shù)據(jù),無視事務一的插入操作。
讀者是否發(fā)現(xiàn)MS_SQL和ORACLE對并發(fā)控制的處理有所不同呢?
五,鎖
下表是鎖的兼容或沖突情形。
現(xiàn)有 S U X
請求
S Y Y N
U Y N N
X N N N
現(xiàn)有 S U X
申請
S Y Y N
U Y N N
X N N N
oracle:
六,注意點
一般處理并發(fā)問題時的步驟:
1、開啟事務。
2、申請寫權限,也就是給對象(表或記錄)加鎖。
3、假如失敗,則結束事務,過一會重試。
4、假如成功,也就是給對象加鎖成功,防止其他用戶再用同樣的方式打開。
5、進行編輯操作。
6、寫入所進行的編輯結果。
7、假如寫入成功,則提交事務,完成操作。
8、假如寫入失敗,則回滾事務,取消提交。
9、(7.8)兩步操作已釋放了鎖定的對象,恢復到操作前的狀態(tài)。
對多表的操作最好一起取得鎖,或則保證處理順序;個人感覺還是前者好,雖然效率低一些
七,附
查看鎖
ORACLE:
select object_name,session_id,os_user_name,oracle_username,process,locked_mode,status from v$locked_object l, all_objects a where l.object_id=a.object_id;
MS_SQL:
EXEC SP_LOCK