Transaction事務(交易),我喜歡將它翻譯成事務,
因為他與買賣交易完全無關係,
代表的其實是要將一段SQL丟進資料庫系統中,最後取得回覆。
至於Transaction事務在資料庫系統中是如何運作的呢?
需要符合哪些規則,讓我們一步一步的了解。
我們知道在電腦之中(這裡的電腦指的是馮紐曼架構的電腦),
每個指令(這裡的"指令"是指機器碼machine code)都會使用到I/O與CPU,
逃離不了Fetch、Decode、Execute
想當然爾,資料庫的CRUD同樣逃離不了該命運。
當循序操作時(同一個時間裡整台電腦就只能執行該指令),
一個指令一個指令的輸入,當該指令I/O或CPU閒置時,
無法讓其他指令使用,將造成許多浪費,且效率極差。
就是因為循序操作(Serialized),所以造成了I/O與CPU的浪費,這裡我們稱為idle,俗稱占著茅坑不拉屎。
因此我們可以透過pipelining的技術,讓同一時間不只有一個指令。 達到指令A有idle時,可以將資源讓出來給其他需要的指令,這樣的交錯操作(interleaved),可以增加throughput。
但隨之而來的將會面臨著並發(Concurrency)問題,可能會有多個指令同時操作著同一筆資料,造成覆蓋等問題。
所以,目標就是在交錯操作(interleaved)的設計之下,必須讓每個操作都如同循序操作(Serialized)般的如其效果。
要讓同一個資料避免同一個時間被兩個指令修改,第一個想法就是在操作該筆資料時,加上鎖,讓其他也想操作該筆資料的指令先在外面等,等前面的指令使用完了,再將該筆資料讓出來給下一個指令操作。
在程式之中可能會這樣寫。
wLock.lock();
try{
// do some instructions
}finally{
wLock.unlock();
}
可以發現我們在執行指令的上下加上了lock,以確保在操作這些指令時,所使用到的所有資料與變數都為自己所用,並且在此期間不被其他指令污染。
再來可以發現,我們的try{...}
其實可以塞入很多指令,塞到滿出來想要塞多少都可以。這裡我們稱為c.s. (Critical section臨界區段)
。
剛剛看到了在撰寫程式時的lock。
wLock.lock();
try{
// do some instructions
}finally{
wLock.unlock();
}
聰明的小夥伴們是否覺得非常熟悉啊,長相幾乎跟資料庫之中的transaction非常類似。
tx.start()
try {
// some sql instructions
} finally {
tx.commit();
}
其實,Transaction說明白的就是一種Critical section,裡面可以放1~n個SQL instructions組成一個Transaction,確保該Transaction運行之中資料不被污染。
SQL instructions主要操作就是CRUD,更簡化的操作就是讀/寫與cpu的操作,
先問個問題
當我們操作DB時,大部分都只是"單句"的CRUD,
單句的CRUD大約佔了80%的使用量,
在資料庫中,何時會使用到tx。
A. 因為是單句CRUD,所以剩下的20%使用tx。
B. 100%全部都使用到tx。
C. 0%使用tx,我都直接在應用層上鎖。
D. 以上皆非。
其實在db內是100%使用tx。
就算只有一句也是tx,
因為資料庫系統中的default值是把auto commit=ture
所以丟進來後會自動幫忙加上tx start、tx commit,
因此tx才是資料庫真正的操作單位,每一次的sql instructions都是一次的tx。
我們前面講解了Transaction其實就是為了避免在交錯操作(interleaved)的設計之下Sql指令之間污染資料,因此加上類似lock的設計,誕生了Transaction這個名詞。
理念就是想要:
所以同時達到了事務隔離(Isolation)
:當有多個TX並發時,TX之間如預期的不相互污染。
有了上面的概念,自然就可以理解資料庫系統為了增加Transaction的throughput,讓一般的麻瓜也能輕易的達到高效能的CRUD操作。
這兩項性質。
交易
但其實跟現實生活中的買賣交易完全無關。