前言

在剛開始自學Springboot的時候,在service實作多個資料庫操作的時候,
會用到@Transactional,這個annotation是做什麼的呢?


什麼是Transaction

Transaction直翻中文是交易或事務,
在Springboot中如果在service的方法上加上@Transactional
就代表這個方法有被Springboot包成一個交易管理,發生錯誤時,讓資料庫操作自動回滾(rollback)。
rollback就是資料庫全部的操作都會取消,這樣的特性就是ACID中的Atomicity(原子性)。

那ACID又是什麼?


什麼是ACID原則

最早的概念是由Jim Gray提出的 DBMS Musings: Issue On ACID
簡單來說ACID代表資料庫交易的四大特性,目的是確保資料的正確,不會因為出現錯誤就導致資料異常。

ACID四大特性,分別為這幾個英文的縮寫:

Atomicity(原子性)

原子性簡單來說就是,一個交易中對於資料的更改,不是全部成功,就是全部失敗。
任何一個步驟失敗,整筆交易就會rollback。
舉例:
當A要轉帳給B,A扣了錢,這中間發生錯誤,B沒收到錢,這樣一定會被客戶罵,
所以這整筆交易一定要是全部成功或是全部失敗。

Consistency(一致性)

每一筆交易必須讓資料庫從一個「有效狀態」變到另一個「有效狀態」。
這裡的「有效」是指符合資料庫中已經設定好的各種規則,比如:

  1. 欄位約束(Constraints):像是欄位必須唯一、不能為空值等。
  2. 級聯操作(Cascades):當父資料變動時,子資料也要跟著變。
  3. 觸發器(Triggers):在特定條件下自動執行的資料庫邏輯。
  4. 其他:例如外鍵關聯、資料格式驗證等等。
    一致性只保證「資料符合規則」,但不保證業務邏輯是正確的。
    舉例:
    如果service層的程式邏輯有錯,導致錯誤地轉了太多錢,只要這個錯誤的轉帳仍然符合資料庫的規則(例如數值型態正確、欄位非空),資料庫仍然會允許它通過。

Isolation(隔離性)

多筆交易不會同時互相干擾,彼此看不到未完成交易的狀態。
資料庫在執行一些操作(insert/update/delete)的時候,會先把欄位鎖起來不給操作,這是為了避免dirty read。
舉例:
例如A在更新商品金額,B同時在查看,如果A還沒執行完商品的交易,那B看到的還是原始金額

Durability(持久性)

保證交易一旦送出,即使server當機、斷電等,資料也不會遺失。
舉例:
訂單如果完成整個交易,資料庫已存入訂單資訊,那麼這時突然網頁當掉,訂單的資料還是會存在。


結尾

要注意的是使用@Trasactional操作的資料庫必須有ACID的特性,基本上是RDBMS
NoSQL早期開發是偏向BASE理論,近年才有些NoSQL的新版本有支援ACID。

下一篇再寫 Transaction的應用、誤區以及特殊用法