Mysql

InnoDB 和隔離級別 - 可重複讀取不是一件壞事嗎?

  • December 2, 2014

我正在閱讀有關InnoDB's 隔離級別的內容,這在很大程度上是有道理的,但我不明白為什麼是unrepeatable reads一件壞事?不應該反過來嗎?

舉些例子:

假設我們有一個用於銷售產品的庫存列,每次有人購買一件商品時,我們都會從該列中取出一件商品,使用Repeatable readserializable隔離級別不會破壞數據完整性嗎?

例如:

TX A: start transaction;
TX B: set session transaction isolation level repeatable read;
TX B: start transaction;
TX A: select stock from products;               -- val = 8
TX B: select stock from products;               -- val = 8
TX A: update products set stock = stock - 1;    -- val = 7
TX B: select stock from products;               -- val = 8
TX A: commit
TX B: select stock from products;               -- val = 8, incorrect!
TX B: commit;
TX B: select stock from products;               -- val = 7

除非它在執行更新時使用正確的值?

InnoDB 隔離級別不是“壞”或“好”,這取決於您的應用程序在隔離方面需要什麼。

在您的範例中,通過使用可重複讀取,您可以確保一旦完成第一次選擇,從該事務的角度來看,沒有其他事務可以修改數據庫的狀態。換句話說,就好像您START TRANSACTION WITH CONSISTENT SNAPSHOT在第 5 行之前執行了“”。在某些情況下可能需要這樣做,讓我舉個例子:

TX A: START TRANSACTION;
TX A: SELECT * FROM products WHERE stock BETWEEN 4 AND 6; -- I see rows 4 and 6 only,
                                                         --  and I want to update those only   
TX B: START TRANSACTION;
TX B: INSERT INTO products (stock) VALUES (5);

TX A: UPDATE products SET stock = 3 WHERE stock BETWEEN 4 AND 6;
TX A: COMMIT; -- race condition
TX B: COMMIT;

通過設置 InnoDB’s REPEATABLE READ,幻讀消失,因為 TX B 將在插入時被鎖定,直到 A 送出。但是,如果我們這樣做READ COMMITTED,我們將獲得不同的輸出,這取決於 A 還是 B 先送出,這違反了 ACID 屬性,並且我們的應用程序可能不會期望。

特別是,STATEMENT基於 - 的複制不需要幻讀,這就是為什麼READ COMMITTED它是預設級別,甚至比READ COMMITTED其他數據庫(需要可序列化才能獲得 InnoDB 行為)具有更嚴格的行為。如果第一個選擇是更新,則獨立執行這些事務將導致不同的結果(漂移從屬)。請注意,事務是以原子方式和串列方式寫入二進制日誌的。

我同意您的觀點,大多數應用程序可能不需要這樣做,因為您將在應用程序級別處理這些情況。如果是這種情況,請使用ROW基於複製並將預設事務隔離級別設置為READ COMMITTED. 在大多數情況下,您還將獲得更好的並發性。

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