1. 程式人生 > 其它 >SELECT FOR UPDATE語句

SELECT FOR UPDATE語句

技術標籤:SQL【更新中】

悲觀鎖實現:以下例項使用MySQL官方資料庫sakila

--關閉自動提交事務
SET autocommit=0;
--city表中city_id的行資料會被鎖定,其它的事務必須等本次事務提交之後才能執行。
START TRANSACTION;
SELECT * FROM city WHERE city_id=1 FOR UPDATE;
SELECT sleep(10);
COMMIT;

NOTE:只有SELECT ... FOR UPDATELOCK IN SHARE MODE 相同資料時會等待其它事務結束後才執行,一般SELECT ... 則不受此影響。
比如,我先執行上述語句,然後再次執行SELECT
* FROM city WHERE city_id=1 FOR UPDATE時會被鎖住。 但是,當執行SELECT * FROM city WHERE city_id=1時並不會被鎖住。(見下圖例項)

在這裡插入圖片描述

關於Row Lock和Table Lock問題:
MySQL InnoDB預設Row-Level Lock,所以只有「明確」地指定主鍵,MySQL 才會執行Row lock (只鎖住被選取的資料) ,否則MySQL 將會執行Table Lock (將整個資料表單給鎖住)。

--case1:當指定範圍主鍵時,會鎖住該範圍;下圖中city_id=2時沒有鎖住,而city_id=12時被鎖住
SET
autocommit=0; START TRANSACTION; SELECT * FROM city WHERE city_id>10 FOR UPDATE; SELECT sleep(10); COMMIT;

在這裡插入圖片描述
在這裡插入圖片描述

--case2:country_id列並不是主鍵,但是有索引;也是Row Lock而不是Table Lock!
SET autocommit=0;
 
START TRANSACTION;
SELECT * FROM city WHERE country_id=100 FOR UPDATE;
SELECT sleep(10);
COMMIT;

在這裡插入圖片描述

--case3:既不指定主鍵,也不指定索引列;會鎖住全表
SET autocommit=0; START TRANSACTION; SELECT * FROM city WHERE city='Aden' FOR UPDATE; SELECT sleep(10); COMMIT;

在這裡插入圖片描述