事務(二)、強一致性事務
前文講到程式設計師面對事務ACID特性如何實現一籌莫展,於是本文進入程式設計師窮開心的表演時間。
眾所周知,關係型資料庫天生就是解決具有複雜事務場景的問題,關係型資料庫完全滿足ACID的特性。資料庫是怎樣實現ACID的呢?
** 資料庫實現ACID的核心技術是併發控制和日誌技術 **
- 併發控制:保證併發操作的正確性(2PL)
- 日誌:保證故障場景下可恢復(Undo/Redo,WAL協議)
現代資料庫均基於Write ahead logging實現ACID,也就是預寫式日誌(WAL)。WAL的中心思想是對資料檔案的修改必須是隻能發生在這些修改已經記錄了日誌之後 – 也就是說,在日誌記錄沖刷到永久儲存器之後. 如果我們遵循這個過程,那麼我們就不需要在每次事務提交的時候 都把資料頁沖刷到磁碟,因為我們知道在出現崩潰的情況下, 我們可以用日誌來恢復資料庫:任何尚未附加到資料頁的記錄 都將先從日誌記錄中重做(這叫向前滾動恢復,也叫做 REDO) 然後那些未提交的事務做的修改將被從資料頁中刪除 (這叫向後滾動恢復 - UNDO)。
程式設計師窮開心假裝自己會寫資料庫核心程式碼:
開始
預寫式日誌[宣告一個事務的唯一標記]
檢視李雷是否有一百元
李雷賬號pk=1減少100元
韓梅梅賬號pk-=2增加100元
預寫式日誌[標明該事務提交]
結束
窮開心:如果你在一個數據庫中,可以直接使用資料庫的事務機制保證ACID。
開心:你說的我都不懂,可我用的就是Mysql,也是現代關係型資料庫RDBMS。可問題還是儲存。
窮開心:(-_-)~
那一定是你使用的姿勢不對。
開心:你胡說,我是按照csdn上直接照抄過來的(-_-)~
JAVA程式碼使用事務的正確姿勢
try{
//STEP 2: Register JDBC driver
Class.forName("com.mysql.jdbc.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
//STEP 4: Set auto commit as false.
conn.setAutoCommit(false);
//STEP 5: Execute a query to create statment with
// required arguments for RS example.
System.out.println("Creating statement...");
stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
//STEP 6: INSERT a row into Employees table
System.out.println("Inserting one row....");
String SQL = "INSERT INTO Employees " +
"VALUES (106, 28, 'Curry', 'Stephen')";
stmt.executeUpdate(SQL);
//STEP 7: INSERT one more row into Employees table
SQL = "INSERT INTO Employees " +
"VALUES (107, 32, 'Kobe', 'Bryant')";
stmt.executeUpdate(SQL);
//STEP 8: Commit data here.
System.out.println("Commiting data here....");
conn.commit();
//STEP 9: Now list all the available records.
String sql = "SELECT id, first, last, age FROM Employees";
ResultSet rs = stmt.executeQuery(sql);
System.out.println("List result set for reference....");
printRs(rs);
//STEP 10: Clean-up environment
rs.close();
stmt.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
// If there is an error then rollback the changes.
System.out.println("Rolling back data here....");
try{
if(conn!=null)
conn.rollback();
}catch(SQLException se2){
se2.printStackTrace();
}//end try
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}finally{
//finally block used to close resources
try{
if(stmt!=null)
stmt.close();
}catch(SQLException se2){
}// nothing we can do
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}//end finally try
}//end try
窮開心:看到沒,java中使用資料庫事務需要主動宣告。預設情況下資料庫連線配置是autoCommit=true。即使你不主動commit資料,每個操作都會自動提交。如果你有兩個操作,資料庫不會保證兩個操作在一個事務中。
開心:說得好像有道理。
開心:問題是JDBC是什麼年代的東西啊~~~~~,誰還在自己寫程式碼呼叫DB Connection?
窮開心:JDBC一點都不老土,現代絕大部分Java orm框架都是基於JDBC的,核心實現程式碼一樣是上面這段。當然我能理解你spring boot黨的感受,剛才只是讓你漲漲見識。
開心:(-_-)~
springboot的事務支援
在使用JPA作為資料訪問技術的時候,spring boot 為我們定義了JpaTransactionManager的bean,並預設開啟了度宣告式事務的支援。所以在springboot專案中無需顯示開啟使用@EnableTransactionManagement註解。
因為Spring的預設的事務規則是遇到執行異常(RuntimeException)和程式錯誤(Error)才會回滾。如果想針對非檢測異常進行事務回滾,需要在@Transactional 註解裡使用
rollbackFor 屬性明確指定異常。
@Transactional(rollbackFor = Exception.class)
public void addMoney() throws Exception {
//先增加餘額
accountMapper.addMoney();
//然後遇到故障
throw new SQLException("發生異常了..");
}
在springboot中明明什麼都沒做,也能實現事務完整性是因為spring boot為我們默默的做了很多。但如果在spring boot中事務完整性被破壞了,有可能是因為事務中發生了非檢測異常,也有可能是異常被吃掉導致沒有觸發回滾。
比如這個程式碼:
//錯誤程式碼
@Transactional(rollbackFor = Exception.class)
public void addMoney() throws Exception {
//先增加餘額
accountMapper.addMoney();
//謹慎:儘量不要在業務層捕捉異常並處理
try {
throw new SQLException("發生異常了..");
} catch (Exception e) {
e.printStackTrace();
}
}
相關推薦
事務(二)、強一致性事務
前文講到程式設計師面對事務ACID特性如何實現一籌莫展,於是本文進入程式設計師窮開心的表演時間。 眾所周知,關係型資料庫天生就是解決具有複雜事務場景的問題,關係型資料庫完全滿足ACID的特性。資料庫是怎樣實現ACID的呢? ** 資料庫實現ACID的核心技術是併
事務(三)、弱一致性事務
書接上回,程式設計師窮開心通過資料庫實現了轉賬事務的強一致性。滄海桑田,世事變幻,話說李雷又要向韓梅梅轉賬100元,但事情有了變化。 故事的發展 李雷賬戶在火星人民銀行,韓梅梅搬到了水星,賬戶在水星人民銀行。程式設計師窮開心在海綿寶第三方支付公司寫程式。由於C
什麼是分散式事務(二):分散式事務特性、2PC、3PC
但是如果第三階段的確認訊息傳送失敗了怎麼辦?RocketMQ會定期掃描訊息叢集中的事物訊息,如果發現了prepare狀態的訊息,它會向訊息傳送者確認本地事務是否已執行成功,如果成功是回滾還是繼續傳送確認訊息呢。RocketMQ會根據傳送端設定的策略來決定是回滾還是繼續傳送確認訊息。這樣就保證了訊息傳送與本地事
MySQL事務(二)事務隔離的實現原理:一致性讀
今天我們來學習一下MySQL的事務隔離是如何實現的。如果你對事務以及事務隔離級別還不太瞭解的話,這裡[左轉](https://www.cnblogs.com/liang24/p/14111897.html)。 好的,下面正式進入主題。事務隔離級別有4種:讀未提交、讀提交、可重複讀和序列化。首先我們來說一下讀
mysql事務(二)——控制語句使用
spa alt ted clas 數據行 ble 事務提交 一般來說 tran 事務控制 一般來說,mysql默認開啟了事務自動提交功能,每條sql執行都會提交事務。可以使用如下語句關閉事務自動提交功能。 show session variables like ‘auto
springCloud分布式事務實戰(二) 分布式事務處理器的編譯和運行之Redis安裝
安裝 water 客戶端測試 server 分布式 log 運行 -o 啟動 一、分布式事務處理器的編譯和運行1)Redis 的安裝和啟動(1)下載redis 解壓縮 (2) 啟動和測試redis 1進入redis 目錄 2 雙擊redis-server.exe 程序
深入資料庫事務(二)事務的隔離級別
深入資料庫事務(二)事務的隔離級別 本文詳細介紹四種事務隔離級別,並通過舉例的方式說明不同的級別能解決什麼樣的讀現象。並且介紹了在關係型資料庫中不同的隔離級別的實現原理。 在DBMS中,事務保證了一個操作序列可以全部都執行或者全部都不執行(原子性),從一個狀態轉變到
分散式事務(二)Spring事務傳播行為
public class ServiceA { @Autowired private ServiceB b; @Transactional public void method() { // 資料庫操作
分散式事務(1)訊息傳送一致性解決方案
訊息傳送一致性 是指產生訊息的業務動作與訊息傳送的一致。(如果業務操作成功,那麼由這個業務操作所產生的訊息一定要成功投遞出去,否則就丟訊息) 訊息傳送一致性如何保障: 場景: 1.業務處理成功,執行傳送訊息的時候 應用故障,導致沒有傳送訊息(後續服務沒有收到訊息處理業務
【Spring】(二)使用Spring進行事務管理的幾種方式
Spring既是SSH中的一員,也是SSM中的一員。不管是在SSH,還是在SSM中,Spring都起到了十分重要的“管理”作用,不論是對action的管理,還是對Controller的管理
事務(一)、事務概念入門
事務(Transaction) 是由一系列對系統中資料進行訪問與更新的操作所組成的一個程式執行線邏輯單元;是指作為單個邏輯工作單元執行的一系列操作,要麼完全地執行,要麼完全地不執行。 事務處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向資料
基於可靠訊息方案的分散式事務(二):Java中的事務
前言:在上一篇文章 基於可靠訊息方案的分散式事務:Lottor介紹 中介紹了常見的分散式事務的解決方案以及筆者基於可靠訊息方案實現的分散式事務元件Lottor的原理,並展示了應用的控制檯管理。在正式介紹Lottor的具體實現之前,本文首先將會介紹Java中的事務
Linux學習筆記(十八) vim(二)、編輯模式、vim實踐練習
編輯模式 命令模式 vim實踐 一、 編輯模式 命令行模式替換時如果需要替換的字符中有/符號,那麽可以將分隔符換成#或者@ :1,100s#/good/weer/#well#g 將前一百行中的/good/weer/替換為well,:nohl 取消搜索時的高亮顯示,:x也是保存並退出,但是如果並
Go語言開發(二)、Go語言基礎
Go 語言 基礎 Go語言開發(二)、Go語言基礎 一、Go語言程序結構 Go語言程序基本結構如下:A、包聲明B、引入包C、函數D、變量E、語句 & 表達式F、註釋 package main //包聲明 import "fmt" //引入包 func main(){ //main函數
Redis學習(二)、JAVA操作Redis
enc main package 服務 clas redis學習 static out edi Redis學習(二)、JAVA操作Redis 一、測試連接Redis是否連通 1、導包 <dependency> <groupId>redis.c
Struts2筆記(二)、Struts2的配置檔案
1、struts-default.xml 該檔案是Struts2框架的基本配置檔案,由框架自動載入。 作用:配置了bean,interceptor,result等 位置:org/apache/struts2/struts-default.xml 這個檔案我們需要關注一個地方 這裡定義
【知識積累】(二)、深入Regex(正則表示式)
\:將下一個字元標記符、或一個向後引用、或一個八進位制轉義符。例如,“\\n”匹配\n。“\n”匹配換行符。序列“\\”匹配“\”而“\(”則匹配“(”。即相當於多種程式語言中都有的“轉義字元”的概念。 ^:匹配輸入字串的開始位置。如果設定了RegExp物件的Multiline屬性,^也匹配“\n
nodeJS教程(二)、nodejs除錯
一、基於nodejs內建的除錯 node.js本身支援除錯,在js檔案中加上debbuger或者在cmd中通過setBreakpoint()可以新增斷點。 要使用nodejs的除錯服務,只要在啟動命令時加上debug。如:node debug web.js。 這時候
Java多執行緒(二)、執行緒的生命週期和狀態控制
、執行緒的生命週期 執行緒狀態轉換圖: 1、新建狀態 用new關鍵字和Thread類或其子類建立一個執行緒物件後,該執行緒物件就處於新生狀態。處於新生狀態的執行緒有自己的記憶體空間,通過呼叫start方法進入就緒狀態(runnable)。 注意:不能對已經啟動的
《MySQL必知必會》學習筆記(二)、MySQL資料庫中資料的檢索與搜尋
一、對檢索結果排序 1.1 簡單排序 在MySQL中使用ORDER BY子句對檢索出的資料進行排序,而且預設為遞增排序。若想以遞減方式排序,需要在排列資料後面加上DESC關鍵字。利用《MySQL必知必會》中的資料表,實驗如下: SELE