我對資料庫鎖定很陌生,并且有一個基本問題。我的理解是,任何 UPDATE 陳述句都會鎖定表中的行,因此,沒有其他事務可以讀取/寫入該行。如果是這樣,請考慮一個場景:
初始表:user_id = 1,count = 10
事務 1:
A: UPDATE table SET count = 20 WHERE user_id = 1
事務 2:
B. 變數 b = SELECT count FROM seat WHERE user_id = 1
C. UPDATE seat SET count = {b} 1 WHERE user_id = 1
如果執行順序是:2B - 1A - 2C,表中count的結果是11還是21?
如果我的理解是正確的,當執行 1A 陳述句時,資料庫會在該行上設定寫鎖,從而阻止 2C 的執行。現在我的問題是,一旦 1A 完成,
事務 2 是否會重新評估 T2 中與該鎖定行相關的所有查詢(2B 和 2C) - (這會將變數 b 的值重新評估為 20)
或
僅重新評估它的阻塞查詢(2B) - (這意味著變數 b 仍將具有其舊值 10)?
編輯:
如果 2B 和 2C 嵌套查詢怎么辦?類似于:
UPDATE seat SET count = (SELECT count FROM seat WHERE user_id = 1) 1 WHERE user_id = 1
uj5u.com熱心網友回復:
讓我們按照您描述的順序排列步驟:
Transaction 2:
B. variable b = SELECT count FROM seats WHERE user_id = 1
假設b現在的值為 10。
Transaction 1:
A: UPDATE table SET count = 20 WHERE user_id = 1
這將鎖定該行,直到事務 1 完成。
Transaction 2:
C. UPDATE seats SET count = {b} 1 WHERE user_id = 1
這也想要事務 1 持有的鎖,所以事務 2 必須等待。
Transaction 1:
D: COMMIT
事務 1 在提交時釋放它的鎖。
Transaction 2:
C. UPDATE seats SET count = {b} 1 WHERE user_id = 1
它現在可以繼續,因為它想要的鎖是免費的。
由于事務 1 已提交,該行現在的值為 20。但是事務 2 的客戶端在其變數中仍然具有值 10 b,因此它將行更新為 10 1 或 11。
這將覆寫事務 1 設定的值。第三個事務可能會在事務 1 提交之后和事務 2 提交之前進行查詢。然后它將讀取值 20。但是一旦事務 2 提交,它將很快被覆寫。
uj5u.com熱心網友回復:
答案是……這取決于。由于您標記了 MySQL,我假設您正在使用該 DBMS。但是哪個引擎?讓我們假設 InnoDB。
您是否明確開始交易?如果你不這樣做,默認情況下 InnoDB 將處于autocommit模式(除非你重置它)。這意味著每個陳述句本身都是一個事務,因此序列 2B - 1A - 2C 將顯示“錯誤”行為。
如果您在事務中顯式包含 2B 和 2C,它仍然取決于隔離級別。InnoDB 的默認隔離級別 REPEATABLE READ 將防止“錯誤”行為,SERIALIZABLE(最保守的級別)也是如此;但是兩個更樂觀的級別,READ COMMITTED 和 READ UNCOMMITTED,不會。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/467575.html
上一篇:轉到php站點中的先例頁面
下一篇:使用復合主鍵查詢表,不包括特定行
