select for update

zhegeMaw發表於2024-08-13

select …… for update 是一種分散式鎖,為了在查詢時,避免其他使用者以該表進行增、刪、改等操作,造成表的不一致性。一般不加資料庫鎖,比較重(太底層,影響廣泛),可以使用分散式鎖 / sychorized / Lock。

一、例子

  • select status from t_goods where id=1 for update;

此時在t_goods表中,id為1的那條資料就被我們鎖定了,其它的事務必須等本次事務提交之後才能執行。這樣我們可以保證當前的資料不會被其它事務修改。

注:1、與普通查詢不一樣的是,我們使用了select…for update的方式,這是透過資料庫實現的一種悲觀鎖

2、需要注意的是,在事務中,只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 相同資料時會等待其它事務結束後才執行,一般SELECT ... 則不受此影響。拿上面的例項來說,當我執行select status from t_goods where id=1 for update;後。我在另外的事務中如果再次執行select status from t_goods where id=1 for update;則第二個事務會一直等待第一個事務的提交,此時第二個查詢處於阻塞的狀態,但是如果我是在第二個事務中執行select status from t_goods where id=1;則能正常查詢出資料,不會受第一個事務的影響。

二、使用要求

儲存引擎:僅適用於InnoDB引擎

加鎖粒度:InnoDB預設是行級別的鎖(當有明確指定的主鍵時候,是行級鎖,否則是表級別)

走索引:InnoDB行鎖是透過給索引上的索引項加鎖來實現的,只有透過索引欄位檢索資料,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖

事務:並且必須開啟事務,在begin與commit之間才生效。

三、幾種句式

select * from t for update 會等待行鎖釋放之後,返回查詢結果。
select * from t for update nowait 不等待行鎖釋放,提示鎖衝突,不返回結果
select * from t for update wait 5 等待5秒,若行鎖仍未釋放,則提示鎖衝突,不返回結果
select * from t for update skip locked 查詢返回查詢結果,但忽略有行鎖的記錄

四、涉及的鎖

悲觀鎖、樂觀鎖

悲觀鎖:每次使用都加鎖。適合頻繁寫入的場景(會堵塞,讀多的話效率低,所以寫多更合適)

樂觀鎖:平時不加鎖,需要再加鎖 。適合頻繁讀取的場景(加鎖少,所以讀取效率高)

讀鎖(共享)、寫鎖(排他)

讀鎖:讀的時候,其他人也可以讀,不可以寫

寫鎖:讀的時候,其他人不可以讀,不可以寫

詳細瞭解-select...from... for update

https://blog.csdn.net/ll594317566/article/details/103869619(select...for update使用方法)

相關文章