事務(wù)用于在并發(fā)訪問期間提供數(shù)據(jù)完整性牢撼,正確的應(yīng)用程序語義和一致的數(shù)據(jù)視圖。 需要所有JDBC兼容驅(qū)動程序來提供事務(wù)支持刨沦。 JDBC API中的事務(wù)管理反映了SQL:2003規(guī)范仿便,并包含了這些概念
- 自動提交模式
- 事務(wù)隔離級別
- 保存點
本章介紹與單個Connection對象關(guān)聯(lián)的事務(wù)語義。 涉及多個Connection對象的事務(wù)在第12章“分布式事務(wù)”中討論慷丽。
10.1 交易界限和自動提交
什么時候開始一個新的事務(wù)是由JDBC驅(qū)動程序或底層數(shù)據(jù)源隱含的決定,雖然一些數(shù)據(jù)源實現(xiàn)了一個明確的“begin transaction”語句哪轿,但是沒有JDBC API可以實現(xiàn)盈魁,通常,當(dāng)當(dāng)前的SQL語句需要一個并且沒有事務(wù)已經(jīng)存在的時候窃诉,一個新的事務(wù)被啟動杨耙。 一個給定的SQL語句是否需要一個事務(wù)也由SQL:2003指定。
Connection屬性auto-commit指定何時結(jié)束事務(wù)飘痛。 一旦該語句完成珊膜,啟用自動提交會在每個單獨的SQL語句之后導(dǎo)致事務(wù)提交。 一個語句被認為是“完成”的點取決于SQL語句的類型以及應(yīng)用程序在執(zhí)行它之后執(zhí)行的操作:
- 對于“數(shù)據(jù)操作語言”(DML)語句(如“插入”宣脉,“更新”车柠,“刪除”和“DDL”語句),語句在執(zhí)行完畢后立即完成
- 對于Select語句,當(dāng)關(guān)聯(lián)的結(jié)果集關(guān)閉時竹祷,該語句將完成谈跛。
- 對于CallableStatement對象或返回多個結(jié)果的語句,當(dāng)所有關(guān)聯(lián)的結(jié)果集都已關(guān)閉時塑陵,該語句已完成感憾,并且已檢索所有更新計數(shù)和輸出參數(shù)
10.2 禁用自動提交模式
當(dāng)禁用自動提交時,每個事務(wù)必須通過調(diào)用Connection方法提交或通過調(diào)用Connection方法回滾來顯式回滾來顯式提交令花。 這適用于在驅(qū)動程序上方的層中進行事務(wù)管理的情況阻桅,例如
- 當(dāng)應(yīng)用程序需要將多個SQL語句組合成一個事務(wù)
- 當(dāng)事務(wù)由應(yīng)用程序服務(wù)器管理時
默認值是在創(chuàng)建Connection對象時啟用自動提交模式。 如果自動提交的值在事務(wù)中間更改兼都,則提交當(dāng)前事務(wù)嫂沉。 如果調(diào)用了setAutoCommit,并且auto-commit的值不會從當(dāng)前值更改扮碧,則被視為無操作
如第12章“分布式事務(wù)”所述趟章,為參與分布式事務(wù)的連接啟用自動提交是一個錯誤。
10.2 事務(wù)隔離等級
事務(wù)隔離級別指定事務(wù)中的語句“可見”哪些數(shù)據(jù)慎王。 它們通過定義在相同目標數(shù)據(jù)源之間的交易之間可以進行什么交互(如果有的話)直接影響并發(fā)訪問級別尤揣。 并發(fā)事務(wù)之間的可能交互分類如下:
當(dāng)允許事務(wù)查看未提交的數(shù)據(jù)更改時,會發(fā)生臟讀柬祠。 換句話說,交易之前所做的更改在提交之前在事務(wù)外部可見负芋。 如果更改回滾而不是提交漫蛔,則可以根據(jù)不正確的臨時數(shù)據(jù)完成其他事務(wù)的工作。
不可重復(fù)讀取時發(fā)生:
1.事務(wù)A讀取一行
2.事務(wù)B更改行
3,事務(wù)A第二次讀取相同的行并獲得不同的結(jié)果幻象讀取發(fā)生時
1.事務(wù)A讀取滿足WHERE條件的所有行
2.事務(wù)B插入一個滿足相同條件的附加行
3.事務(wù)A重新評估WHERE條件并拾取附加的“幻像”行
JDBC通過添加TRANSACTION_NONE來增強 SQL:2003定義的四個級別的事務(wù)隔離旧蛾。 從最少限制到最嚴格的交易隔離級別是:
1莽龟,TRANSACTION_NONE :表示驅(qū)動程序不支持事務(wù),這意味著它不是JDBC兼容的驅(qū)動程序锨天。
2毯盈,TRANSACTION_READ_UNCOMMITTED:允許事務(wù)查看未提交的數(shù)據(jù)更改。 這意味著臟的讀取病袄,不可重復(fù)的讀取和幻像讀取是可能的
3搂赋,TRANSACTION_READ_COMMITTED:意味著事務(wù)之前進行的任何更改在事務(wù)發(fā)生之前都不可見,直到事務(wù)被提交益缠。 這樣可以防止臟讀脑奠,但是不可重復(fù)的讀取和幻像讀取仍然是可能的。
4幅慌,TRANSACTION_REPEATABLE_READ:不允許臟讀和不可重讀讀宋欺。 幻影讀取仍然是可能的。
5,TRANSACTION_SERIALIZABLE:指定防止臟讀齿诞,不可重復(fù)讀取和幻像讀取酸休。
10.2.1 使用 setTransactionIsolation 方法
Connection對象的默認事務(wù)級別由提供連接的驅(qū)動程序決定。 通常祷杈,它是底層數(shù)據(jù)源支持的默認事務(wù)級別
提供了Connection方法setTransactionIsolation斑司,以允許JDBC客戶端更改給定Connection對象的事務(wù)隔離級別。 新的隔離級別對于會話的剩余部分或直到下一次調(diào)用setTransactionIsolation方法仍然有效
在事務(wù)中間調(diào)用setTransactionIsolation方法的結(jié)果是實現(xiàn)定義的
方法getTransactionIsolation的返回值應(yīng)該反映實際發(fā)生時隔離級別的變化吠式。 建議驅(qū)動程序?qū)崿F(xiàn)setTransactionIsolation方法來更改從下一個事務(wù)開始的隔離級別陡厘。 提交當(dāng)前事務(wù)以使效果立即也是有效的實現(xiàn)
給定的JDBC驅(qū)動程序可能不支持所有四個事務(wù)隔離級別(不計算TRANSACTION_NONE)。 如果驅(qū)動程序不支持在調(diào)用setTransactionIsolation中指定的隔離級別特占,則可以替換更高級別糙置,更嚴格的事務(wù)隔離級別。 如果驅(qū)動程序無法替代較高的事務(wù)級別是目,則會引發(fā)SQLException谤饭。 DatabaseMetaData方法supportsTransactionIsolationLevel可以用于確定驅(qū)動程序是否支持給定的級別
10.2.2 性能注意事項
隨著事務(wù)隔離級別的增加,需要更多的鎖定和其他DBMS開銷來確保正確的語義懊纳。 這反過來降低了可以支持的并發(fā)訪問的程度揉抵。 因此,當(dāng)應(yīng)用程序使用更高的事務(wù)隔離級別時嗤疯,應(yīng)用程序可能會看到降低的性能冤今。 因此,無論是應(yīng)用程序本身還是應(yīng)用程序服務(wù)器的一部分茂缚,事務(wù)管理器在確定哪個事務(wù)隔離級別合適時戏罢,應(yīng)該對數(shù)據(jù)一致性的需求與性能要求進行權(quán)衡。
10.3 Savepoints
保存點通過標記事務(wù)中的中間點來提供對事務(wù)的更細粒度的控制脚囊。 一旦設(shè)置了保存點龟糕,事務(wù)可以回滾到該保存點,而不影響以前的工作
DatabaseMetaData.supportsSavepoints方法可用于確定JDBC驅(qū)動程序和DBMS是否支持保存點
10.3.1 設(shè)置和回滾至 保存點
Connection.setSavepoint方法可用于在當(dāng)前事務(wù)中設(shè)置保存點悔耘。 如果調(diào)用了setSavePoint并且沒有活動的事務(wù)讲岁,則事務(wù)將被啟動。 Connection.rollback方法已被重載以獲取一個保存點參數(shù)
代碼示例10-2將一行插入到表中衬以,設(shè)置保存點svpt1缓艳,然后插入第二行。 當(dāng)事務(wù)稍后回滾到svpt1時看峻,第二個插入被撤消郎任,但是第一個插入保持不變。 換句話說备籽,當(dāng)交易被提交時舶治,只有包含“FIRST”的行將被添加到TAB1
conn.createStatement();
int rows = stmt.executeUpdate("INSERT INTO TAB1 (COL1) VALUES " +
"(’FIRST’)");
// set savepoint
Savepoint svpt1 = conn.setSavepoint("SAVEPOINT_1");
rows = stmt.executeUpdate("INSERT INTO TAB1 (COL1) " +
"VALUES (’SECOND’)");
...
conn.rollback(svpt1);
...
conn.commit();
10.3.4 釋放保存點
Connection.releaseSavepoint方法將Savepoint對象作為參數(shù)分井,并從當(dāng)前事務(wù)中刪除它和任何后續(xù)的保存點。
一旦保存點被釋放霉猛,嘗試在回滾操作中引用它將導(dǎo)致拋出SQLException尺锚。
在事務(wù)中創(chuàng)建的任何保存點將自動釋放,并在事務(wù)提交或整個事務(wù)回滾時變?yōu)闊o效惜浅。
將事務(wù)回滾到保存點將自動釋放并使無效的所有保存點之后創(chuàng)建的任何其他保存點無效