一.什么是事務
?? ? 事務是應用程序中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所作的所有更改都會被撤消。也就是事務具有原子性,一個事務中的一系列的操作要么全部成功,要么一個都不做。
?? 事務的結(jié)束有兩種,當事務中的所以步驟全部成功執(zhí)行時,事務提交。如果其中一個步驟失敗,將發(fā)生回滾操作,撤消撤消之前到事務開始時的所以操作。
二.事務的
ACID
事務具有四個特征:原子性( Atomicity )、一致性( Consistency )、隔離性( Isolation )和持續(xù)性( Durability )。這四個特性簡稱為 ACID 特性。
1 、原子性
???
事務是數(shù)據(jù)庫的邏輯工作單位,事務中包含的各操作要么都做,要么都不做
2 、一致性
????? 事務執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫從一個一致性狀態(tài)變到另一個一致性狀態(tài)。因此當數(shù)據(jù)庫只包含成功事務提交的結(jié)果時,就說數(shù)據(jù)庫處于一致性狀態(tài)。如果數(shù)據(jù)庫系統(tǒng)運行中發(fā)生故障,有些事務尚未完成就被迫中斷,這些未完成事務對數(shù)據(jù)庫所做的修改有一部分已寫入物理數(shù)據(jù)庫,這時數(shù)據(jù)庫就處于一種不正確的狀態(tài),或者說是不一致的狀態(tài)。 ?
3 、隔離性
???
一個事務的執(zhí)行不能其它事務干擾。即一個事務內(nèi)部的操作及使用的數(shù)據(jù)對其它并發(fā)事務是隔離的,并發(fā)執(zhí)行的各個事務之間不能互相干擾。
4 、持續(xù)性
?? 也稱永久性,指一個事務一旦提交,它對數(shù)據(jù)庫中的數(shù)據(jù)的改變就應該是永久性的。接下來的其它操作或故障不應該對其執(zhí)行結(jié)果有任何影響。
二.事務的屬性
一個事務的屬性控制了事務的使用范圍。 EJB 、 Spring 以及.net下的事務屬性都很類似的, 事務屬性有如下幾種:
Required:
如果在一個事務中調(diào)用,就把該方法加到此事務中來
如果還沒有啟動事務,就啟動一個新事務
RequiredNew:
不管當前有沒有事務,都會啟動一個新事務,如果當前有事務,會被掛起直到方法結(jié)束。
NotSupported:
不能在事務中執(zhí)行此方法。如果有事務,將會被掛起直到方法結(jié)束。
Supports:
如果當前有事務,此方法會加到當前事務,如果沒有,容器也不會啟動新事務。
Mandatory:
必須在事務中調(diào)用此方法,否則拋出異常。
Never:
必須不在事務中調(diào)用此方法,否則拋出異常。
三.事務的回滾
CMT 在以下兩中情況下,事務將回滾。第一,如果產(chǎn)生一個系統(tǒng)異常,容器將自動回滾該事務。第二,通過調(diào)用 EJBContext 接口 SetRollbackOnly 方法, Bean 方法通知容器回滾該事務。如果 Bean 拋出一個應用異常,事務將不會自動回滾,但可以調(diào)用 SetRollbackOnly 回滾。
四.事務超時
對于 EJB 中的容器管理事務,事務超時間隔是通過設置 default.properties 文件中 ransaction.timeout 屬性的值來確定的,該文件在 J2EE SDK 安裝目錄的 config 子目錄下。如下例將事務超時間隔設置為 5 秒鐘: transaction.timeout=5 ,這樣,當事務在 5 秒鐘內(nèi)還沒有完成,容器將回滾該事務。
J2EE SDK 安裝后,超時間隔的缺省值為 0 ,表示不計算超時,無論事務執(zhí)行多長時間,除非異常出錯回滾,一直等待事務完成。
只有使用容器管理事務的企業(yè) Bean 才會受到 transaction.timeout 屬性值的影響。 Bean 管理的 JTA 事務使用 UserTransaction 接口的 setTransactionTimeout 方法來設置事務超時間隔。
五.隔離級別
事務不僅保證事務界限內(nèi)的數(shù)據(jù)庫操作全部完成(或回滾)同時還隔離數(shù)據(jù)庫更新語句。隔離級別描述被修改的數(shù)據(jù)對其他事物的可見度。隔離級別的控制會跟具體的 DBMS 廠商不同而不同。
??? ? 隔離級別與并發(fā)性是互為矛盾的:隔離程度越高,數(shù)據(jù)庫的并發(fā)性越差;隔離程度越低,數(shù)據(jù)庫的并發(fā)性越好。
通過一些現(xiàn)象,可以反映出隔離級別的效果。這些現(xiàn)象有:
l???????? 更新丟失( lost update ):當系統(tǒng)允許兩個事務同時更新同一數(shù)據(jù)是,發(fā)生更新丟失。
l???????? 臟讀( dirty read ):當一個事務讀取另一個事務尚未提交的修改時,產(chǎn)生臟讀。
l????????
非重復讀(
nonrepeatable read
):事務多次讀取同一行中的數(shù)據(jù)卻得到不同數(shù)值時。例如:事務1讀取了一行數(shù)據(jù),而事務2改變或刪除了那些行并提交了修改。如果事務1再次讀取了那一行,那么,事務1就得到了不同的數(shù)值(被更新或刪除)。
l???????? 幻像讀( phantom read ):一行數(shù)據(jù)滿足搜索規(guī)則,卻在開始沒有被看到。例如:事務1讀取了一系列滿足搜索規(guī)則的行,而事務2插入或刪除了一個滿足事務1搜索規(guī)則的行。如果事務1再次執(zhí)行查詢語句,就會得到不同的一系列行。
SQL-99 標準定義了下列隔離級別:
l???????? 未提交讀( read uncommitted )(隔離事務的最低級別,只能保證不讀取物理上損壞的數(shù)據(jù))
l???????? 已提交讀( read committed )(數(shù)據(jù)庫引擎 ? 的默認級別)當一個事務運行在這個隔離級別時, 一個 SELECT 查詢只能看到查詢開始之前提交的數(shù)據(jù),而永遠 無法看到未提交的數(shù)據(jù),或者是在查詢執(zhí)行時其他并行的事務提交做的改變。
l???????? 可重復讀( repeatable read ),不會臟讀和非重復讀,可能發(fā)生幻像讀
l????????
可串行化(
serializable
)(隔離事務的最高級別,事務之間完全隔離)
??????????????????????
ANSI/ISO SQL
隔離級別
隔離級別 |
臟讀(DirtyRead)
|
不可重復的讀(Non-Repeatable Read)
|
?
幻像
讀取(Phantom Read)
|
未提交讀
(Read uncommitted) |
可能 |
可能 |
可能 |
已提交讀
(Read committed) |
不可能 |
可能 |
可能 |
可重復讀(Repeatable read) |
不可能 |
不可能 |
可能 |
可串行化(Serializable ) |
不可能 |
不可能 |
不可能 |