什麼是Database Transaction

一個transaction,就是一組一連串對資料庫進行Read和Write的動作
只有Read和Write這2種

  1. Read
  2. Write

因為我也想不到其他種動作了
Delete也算在Write裡面喔

wiki上寫說:
A transaction comprises a unit of work performed within a database management system (or similar system) against database. 

老實說
我查了很久「a unit of work」在中文是什麼意思
他的意思應該是
Transaction包含1個單元,
什麼樣的1個單元
1個工作的單元

看到這裡不太懂沒關係
我也是猜測的
了解Transaction真正的意思就好
一個transaction,就是一組一連串對資料庫進行Read和Write的動作

一個transaction長這樣
我用pseudo code表示

因為一個transaction只有2種結局
全部SQL執行成功 -> commit;
只要有一個SQL失敗 -> rollback; 
所以我最後面有個判斷式
看完pseudo code會解釋transaction的2種結局

Begin Transactionread();
write();read();
write();if (success) {commit;
} else {rollback;
}

實際運用上
如果是在資料庫中
一個transaction就是commit和commit中間
全部的SQL
就是一個transaction

commit;
insert into member (account, englishName, chineseName) values ('karenten10', 'karen', '吳佳儒');update member 
set englishName = 'Karen Wu' 
where account = 'karenten10';commit;

以上面這個例子來說
這個transaction包含2個動作
一個insert
一個update

如果在程式碼中
以java來說
也是commit和commit中間
全部的SQL

...前面程式省很大
conn.commit();
stmt.execute("insert into member ( "+ " account, englishName, chineseName) values ("+ " 'karenten10', 'karen', '吳佳儒'");stmt.execute("update member "+ " set englishName = 'Karen Wu'" + " where account = 'karenten10'");
conn.commit();

以上面這個例子來說
這個transaction包含2個動作
一個insert
一個update

transaction的2種結局

  1. commit
    一個transaction要嘛就是
    裡面SQL全部執行成功
    然後將執行結果提交給資料庫 --> 也就是commit

  2. rollback
    不然只要裡面SQL只要有一個失敗
    就要把前面做過的事情全部還原
    當作什麼都沒發生過 --> 這就是rollback

寫到這裡佳儒不禁捫心自問
為什麼transaction要這樣設計啊
一定有它的道理
因為就算沒有全部SQL執行成功
至少他也執行到某個程度了啊
為什麼不要把這部分的成果提交出去呢

佳儒想到了一個現實生活案例:
假如佳儒今天到商店去買東西
選好東西後
到櫃檯作結賬
這時候過程的pseudo code如下

Begin Transaction收銀員刷條碼,告知佳儒價格為$728元;
佳儒從錢包掏出錢,交給收銀員;
收銀員確認錢足夠,開始打發票,找零錢給佳儒;
佳儒把東西帶回家;if (success) {commit;
} else {rollback;
}

假如佳儒在付賬時
發現錢帶不夠
例如我已拿出$500給收銀員時
才發現錢包只剩下$10呢

這時現實生活中會怎麼做
當然是收銀員會把$500退還給我
然後把商品收回去,重新放回架上
一切當作沒發生過一樣
這樣才合理嘛
所以database transaction也是這樣設計的

另外如果只有1個使用者在存取資料庫資料
我們可以不必考慮其他使用者
是否同時在修改相同一筆資料

多個使用者存取資料庫時
如果交易不能併行
那也不用考慮其他使用者
是否同時在修改同一筆資料
就像是收銀員一次只為一位顧客服務

然而在可以多使用者&多交易
可同時進行的資料庫系統中
可能有多位使用者
同時修改同一筆資料
因此如何維持資料的正確性和一致性
就是資料庫系統最大的課題

這時候資料庫系統比較像是麵攤的老闆
他會同時煮好幾位顧客的麵
但是都可以正確上菜

以上案例
也是說明為什麼
transaction必須符合這4個特性

交易的4個特性 - ACID

先來看一下這張圖
資料庫的 異動管理.gif

  • 要維持Atomicity和Durability要靠Failure Recovery機制
  • 要確保Isolation和Concurrency要靠Concurrency Control機制

這2個機制合起來便是資料庫的「異動管理」

這2個機制稍後在之後的文章再說明
先來說transaction的4個特性

1. Atomicity (原子性)

  • 交易是不可分割的單元,就像原子一樣
  • 它不是全部執行,就是全部不執行
  • 全部執行 => commit,將結果永久儲存於資料庫中
  • 全部不執行 => 如果有一個SQL失敗,rollback,則將之前執行結果的全部回復,當作沒發生過一樣
  • rollback可能會由以下3種狀況觸發
    1. transaction自己發出的rollback 
      (1) 可能是提款金額大於存款金額 
      (2) 使用者輸入密碼錯誤 
      (3) 提款時按「取消」 
    2. 資料庫系統本身所發出的rollback 
      (1) 資料庫系統本身因為負載太大,而不得不先行rollback,待負載減輕時,再予以恢復 
      (2) 資料庫系統本身發生了Deadlock,而不得不先行rollback 
    3. 資料庫系統中途發生當機或無法抗拒的意外,這時候沒有人可以發出rollback的命令 
      (1) 當資料庫系統再度被啟用時,資料庫系統可以利用Transaction Log,判斷哪些Transaction要rollback,哪些Transaction要重新執行

2. Consistency (一致性)

指的是資料在交易前後必須保持一致,直接舉個例子來說明
例如:
A戶頭有300元
B戶頭有500元
A要轉賬100元給B

這時候會有以下動作

  1. A戶頭扣100元,A變成200元
  2. B戶頭加100元,B變成600元

要嘛這2個動作都成功,要嘛這2個動作都不要做
不可以有A戶頭已經扣掉100元
但B戶頭沒加上100元的狀況

不論transaction前後
2個戶頭加總起來是800元
這就是transaction的consistency

3. Isolation (隔離性)

隔離性就是一個transaction在進行時
它所用到的資料庫資料
或是產生的中間結果
不能讓其他transaction影響(寫入)或使用
直到該transaction結束為止(commit)

舉例來說:
如果有個遊戲設計成
會員如果買寶物,會扣10點的點數
會員如果玩遊戲,會扣1點的點數

如果會員同時開了2個視窗
1個視窗買寶物 -> transaction買寶物
1個視窗玩遊戲 -> transaction玩遊戲

Begin Transaction買寶物取得剩餘點數
檢查是否夠買寶物
如果足夠,點數扣10點
會員寶物清單新增1個寶物commit;
Begin Transaction玩遊戲取得剩餘點數
檢查是否夠玩遊戲
如果足夠,點數扣1點
遊戲開始commit;

那麼如果沒有把「會員點數」table中
那一筆會員的資料鎖定
一次只允許一個transaction進行
如果點數只剩下10點
那有可能會發生會員買了寶物
也玩了一次遊戲
因為系統以為有足夠的點數

佳儒所知道
實際上做到資料鎖定的方式是:
要自己下一個SQL來達成這樣的目的

會員額度的Table叫做memberAccount
(以oracle來說)

select *
from memberAccount
where account = 'karenten10'
for update

這樣karenten10的會員資料
就被鎖定住了
直到目前這個transaction commit後
另1個transaction才能開始使用該筆資料

其實隔離的層級有4種
待佳儒之後的文章再繼續介紹

4. Durability (持續性)

如果在commit的時候
系統發生錯誤
那麼在系統回復後
要繼續完成未完成的工作
這就是transaction的durability

還有許多主題沒有講
就待下幾篇文章繼續

本篇文章寫的出來
主要參考以下來源
感謝他們~

  1. 「資料庫系統之理論與實務」,華泰出版社, 曾守正 周韻寰編著
  2. http://en.wikipedia.org/wiki/Database_transaction
  3. http://openhome.cc/Gossip/EJB3Gossip/TransactionABC.html
  4. http://openhome.cc/Gossip/HibernateGossip/IsolationLevel.html
  5. http://structedtext.appspot.com/db/transaction.html
  6. http://openhome.cc/Gossip/JavaGossip-V2/StatementResultSet.htm
  7. http://sjchen.im.nuu.edu.tw/Database/98/Ch07_T.pdf
  8. http://cilab.csie.ncu.edu.tw/students/xiang/course_972/ES750/ES750-14.ppt
  9. http://courses.ywdeng.idv.tw/cust/2011/db/PPT/ch11.ppt?