Mysql

MySQL InnoDB 事務是否可序列化?

  • October 24, 2018

我對 MySQL 事務是否可序列化以及是否防止讀取異常感到困惑?

例如,如果我SELECT從一行中獲取一個值,那麼UPDATE該行通過遞增該值來實現。有可能對UPDATE正在讀取的行進行另一個查詢,從而導致不正確的更新。

但是,我的印像是,即使我將這兩個語句包裝在一個事務中,也不能保證我不會遇到競爭條件。請參閱此 StackOverflow 執行緒。因此,為了防止這種情況,我使用UPDATECOALESCE單個查詢,因此保證是原子的。這個假設正確嗎?或者交易是否會在這裡起作用以保證沒有競爭條件?

我從有關隔離級別的 MySQL 5.7 文件中看到事務預設情況下是,REPEATABLE_READ而不是SERIALIZABLE. 如果我將事務級別設置為SERIALIZABLE怎麼辦?我試圖閱讀文件,REPEATABLE_READ但它並沒有增加我對這個問題的理解。

根據MySQL 文件,SERIALIZABLE 是:

此級別類似於 REPEATABLE READ,但如果禁用自動送出,InnoDB 會將所有普通 SELECT 語句隱式轉換為 SELECT … FOR SHARE。如果啟用了自動送出,則 SELECT 是它自己的事務。因此,它是只讀的,並且如果作為一致(非鎖定)讀取執行並且不需要阻塞其他事務,則可以序列化。(如果其他事務修改了選定的行,要強制一個普通的 SELECT 阻塞,禁用自動送出。)

鎖定 FOR SHARE 行不等同於 SERIALIZABLE 事務,因為它不能防止由 SELECT 語句返回的競速事務插入行。

SERIALIZABLE 上的 PostgreSQL 文件提供了一個發生這種情況的範例。在您的特定情況下,我相信 MySQL 的 SERIALIZED 隔離級別不會保護您,因為兩個競爭事務都可以鎖定該行 FOR SHARE,然後都可以發出 UPDATE 增加值,一個事務將通過,下一個事務將等待第一個送出,然後通過。您將得到一個增量而不是兩個的淨值。

  • 盡量減少您在交易中的投入——以保持快速。
  • 始終檢查錯誤並重新啟動事務。

底線:競爭條件很少見,您將處理那些確實發生的情況。

至於SERIALIZABLE——那是最慢的模式;不要用它來提高速度

無論如何,您是否期望每秒有數千筆交易?

引用自:https://dba.stackexchange.com/questions/202665