遇到mysql資料庫事務隔離級別相關的小坑

2021-08-28 19:48:24 字數 2368 閱讀 7625

幾乎所有軟體工程師都知道,mysql有4種事務隔離級別,但是實際開發過程中可能有時候忽略這個小細節,有時候可能是本來就沒有考慮過,有時候也可能是其他的原因,比如我這次踩到的小坑。

事情還原:

1、需求一:是新建乙個商戶,但是客戶要求在建立商戶的時候要預設給他們開乙個管理員賬戶。其實很簡單,就是新建乙個商戶,然後再新建乙個賬戶,賬戶表中有乙個字段關聯商戶。但是一看資料庫隔離級別,是read committed(讀取提交內容)。當時想著,算了,應該是其他專案需求需要用到這樣的隔離級別,就先建立商戶,然後再新建賬戶。當然,這就免不了各種錯誤處理。

2、需求二:每個使用者會有乙個預設收貨位址,如果新增或者更新乙個收貨位址,且設定為預設的,那麼需要將其他收貨位址設定為非預設收貨位址。受到需求一的影響。沒看資料庫隔離級別,就直接按照read committed(讀取提交內容)這種隔離級別的方式開發,先插入(或者更新),如果是預設位址,將所有查出該使用者所有的收貨位址,將預設位址修改為非預設的位址。

結果:如果需求一和需求二是在同乙個資料庫中的時候,其實是沒問題的。因為事務隔離級別一致。但是剛好運維那邊給開發遷移資料庫的過程中,由於各種原因,事務隔離級別從read committed(讀取提交內容)修改為repeatable read(可重讀),這就會導致需求二中新插入或者更新的時候,會把先插入或者更新的記錄被讀取到,然後修改了。

教訓:

1、特定的專案對於的資料庫,最好約定好用同一種事務隔離級別。(這次採坑有個原因是同乙個資料庫,有多個專案一起用)

2、如果1條件不滿足,最好在使用事務前設定會話對應的事務隔離級別

設定會話隔離級別

檢視innodb儲存引擎 系統級的隔離級別 和 會話級的隔離級別:

mysql> select @@global.tx_isolation,@@tx_isolation;

+-----------------------+-----------------+

| @@global.tx_isolation | @@tx_isolation |

+-----------------------+-----------------+

| repeatable-read | repeatable-read |

+-----------------------+-----------------+

1 row in set (0.00 sec)

設定innodb的事務級別方法是:set 作用域 transaction isolation level 事務隔離級別,例如~

set [session | global] transaction isolation level

mysql> set global transaction isolation level read committed; //全域性的

mysql> set session transaction isolation level read committed; //當前會話

基礎知識

sql標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低階別的隔離級一般支援更高的併發處理,並擁有更低的系統開銷。

read uncommitted(讀取未提交內容)

在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因為它的效能也不比其他級別好多少。讀取未提交的資料,也被稱之為髒讀(dirty read)。
read committed(讀取提交內容)

這是大多數資料庫系統的預設隔離級別(但不是mysql預設的)。它滿足了隔離的簡單定義:乙個事務只能看見已經提交事務所做的改變。這種隔離級別 也支援所謂的不可重複讀(nonrepeatable read),因為同一事務的其他例項在該例項處理其間可能會有新的commit,所以同一select可能返回不同結果。
repeatable read(可重讀)

這是mysql的預設事務隔離級別,它確保同一事務的多個例項在併發讀取資料時,會看到同樣的資料行。不過理論上,這會導致另乙個棘手的問題:幻讀 (phantom read)。簡單的說,幻讀指當使用者讀取某一範圍的資料行時,另乙個事務又在該範圍內插入了新行,當使用者再讀取該範圍的資料行時,會發現有新的「幻影」 行。innodb和falcon儲存引擎通過多版本併發控制(mvcc,multiversion concurrency control)機制解決了該問題。
serializable(可序列化)

這是最高的隔離級別,它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每個讀的資料行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。

MySQL資料庫 innodb事務的隔離級別

1.髒讀 乙個事務,讀到另外一條未提交事務的資料 read uncommitted出現 2.不可重複讀 乙個事務多次讀取到的資料不一致 read committed出現 3.幻讀 事務ab,事務a插入一條資料,事務b修改所有的資料,發現修改的行數比之前多,好像產生了幻覺一樣 用一張表account來...

MySQL資料庫事務隔離

mysql資料庫事務隔離級別主要有四種 1,serializable 序列化,乙個事務乙個事務的執行 2,repeatable read 可重複讀,無論其他事務是否修改並提交了資料,在這個事務中看到的資料值始終不受其他事務影響 3,read committed 讀取已提交,其他事務提交了對資料的修改...

mysql資料庫事務隔離級別

1修改事務隔離級別 全域性修改 修改mysql.ini配置檔案 mysqlid transaction isolation repeatble read 對當前session修改 登入mysql客戶端後,執行命令set session transaction isolation level read...