MySQL是我們日常生活中常見的數據庫,他的innodb存儲引擎尤為常見,在事務方面使用的是扁平事務,即要么都執行,要么都回滾。而tidb數據庫則使用的是分布式事務。兩者都能保證數據的高一致性,但是在實現方式上是不一樣的。
我們先來看看MySQL的事務機制,采用redo log機制來保證事務更新的一致性和持久性。那我們來看看innodb重做日志的內部機制。
當更新數據時,innodb內部的操作流程是:
而tidb數據庫,在事務上采用的是樂觀鎖:
TiDB 使用樂觀事務模型,在執行 Update
、Insert
、Delete
等語句時,只有在提交過程中才會檢查寫寫沖突,而不是像 MySQL 一樣使用行鎖來避免寫寫沖突。類似的,諸如 GET_LOCK()
和 RELEASE_LOCK()
等函數以及 SELECT .. FOR UPDATE
之類的語句在 TiDB 和 MySQL 中的執行方式並不相同。所以業務端在執行 SQL 語句后,需要注意檢查 commit 的返回值,即使執行時沒有出錯,commit 的時候也可能會出錯。
TiDB 的事務模型采用樂觀鎖,只有在真正提交的時候,才會做沖突檢測,如果有沖突,則需要重試。這種模型在沖突嚴重的場景下,會比較低效,因為重試之前的操作都是無效的,需要重復做。舉一個比較極端的例子,就是把數據庫當做計數器用,如果訪問的並發度比較高,那么一定會有嚴重的沖突,導致大量的重試甚至是超時。但是如果訪問沖突並不十分嚴重,那么樂觀鎖模型具備較高的效率。所以在沖突嚴重的場景下,推薦在系統架構層面解決問題,比如將計數器放在 Redis 中。