併發程式設計的原子性 != 事務ACID的原子性

碼農談IT發表於2023-01-06


併發程式設計的原子性 != 事務ACID的原子性

這是Hollis的第 412 篇原創分享
作者 l Hollis
來源 l Hollis(ID:hollischuang)

關於原子性,很多人在多個地方都聽說過,大家也都背的很熟悉。

在事務的ACID中,有原子性的概念,在併發程式設計的原子性、可見性、有序性中也有原子性的概念。

有人認為他們是一樣的,甚至很多人在說原子性的時候也都是這麼說的:


原子性是指事務是一個不可再分割的工作單元,事務中的操作要麼都發生,要麼都不發生。

但是,其實,雖然都叫原子性,但是此原子性非彼原子性

在資料庫中的原子性,確實是一個不可拆分的工作單元,要麼都執行,要麼都不執行。因為事務可以Commit、也可以Rollback。

但是在併發程式設計中,一個操作是沒辦法rollback的,並且執行緒在執行過程中也是有可能失敗的,失敗了是沒辦法回滾的,難道就說一個操作沒辦法保證原子性了麼?

所以,在併發程式設計中,我們把一個或者多個操作在 CPU 執行的過程中不被中斷的特性稱為原子性。這裡的原子性是透過加鎖的方式來保證的,其實保證的就是一列操作,不可以被拆分執行,即執行過程中,需要互斥排他,不能有其他執行緒進行執行。

舉一個例子來說明一下這兩個原子性的區別。

Redis中的Lua指令碼到底能不能保證原子性?

網上很多文章,有人說能,有人說不能。要我說,都對,也都不對。就是因為因為大家搞混了這兩個原子性的區別。

我們都知道,當我們想要在一個事務中執行多個命令的時候,會選擇使用Lua指令碼。

Redis會將一個要執行的Lua指令碼封裝成一個單獨的事務,而指令碼執行器在執行這個事務的過程中,

如果有其他客戶端請求的時候,會把它暫存起來,等指令碼處理完以後,才會再把被暫存的請求恢復執行。

這樣就可以保證整個指令碼是作為一個整體執行的,中間不會被其他命令插入,這就是所謂的原子性中的”不可拆分”特性。

但是,如果事務執行過程中命令產生錯誤,事務是不會回滾的,也不會影響後續命令的執行。

也就是說,Redis保證以原子方式執行Lua指令碼,但是不保證指令碼中所有操作要麼都執行或者都會滾。

那就意味著,Redis中Lua指令碼的執行,可以保證併發程式設計中不可再拆分的這個原子性,但是沒有保證資料庫ACID中要麼都執行要麼都會滾的這個原子性。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024924/viewspace-2931136/,如需轉載,請註明出處,否則將追究法律責任。

相關文章