InnoDB中的select .. for update語句:線程
1)select .. for update語句僅適用於InnoDB 2)select .. for update語句必須在事務中才能生效。 3)在執行事務中的select .. for update語句時,MySQL會對查詢結果集中的每行數據都添加排他鎖(行鎖、表鎖),其它線程對鎖定行的 更新、刪除、select .. for update查詢 這3種操做都會被阻塞,通常的select語句不會被阻塞。 4)查看自動提交是否開啓(1表示開啓,0表示關閉,默認開啓): select @@autocommit 5)InnoDB行級鎖的實現:InnoDB的行級鎖是經過在索引上加鎖來實現的,因此只有經過明確的索引來查找數據時纔會使用行級鎖。
排它鎖的選擇:rest
若where條件中明確指定了主鍵,且該行數據存在,則只鎖定該行,故排它鎖爲行鎖(row lock)。 若where條件中明確指定了主鍵,可是該行數據不存在,則不會加鎖。 若where條件中明確指定了索引,且該行數據存在,則只鎖定該行,故排它鎖爲行鎖(row lock)。 若where條件中明確指定了索引,可是該行數據不存在,則不會加鎖。 若where條件中未明確指定主鍵或索引,則會鎖定全表,故排它鎖爲表鎖(table lock)。 注:未明確指定 即 未指定(主鍵/索引) 或 指定的是(主鍵/索引)的範圍
eg: # 只鎖定message_id爲1的行 set autocommit=0; begin; select * from t_message where message_id=1 for update; # message_id爲主鍵 commit;code
# 鎖定全表 set autocommit=0; begin; select * from t_message where message_id>1 for update; # message_id爲主鍵 commit; # 鎖定全表 set autocommit=0; begin; select * from t_message where type='good' for update; # good非索引列 commit; 其它線程由於等待(排它鎖)超時而報錯: update t_message set title='asdf' where message_id=1; [Err] 1205 - Lock wait timeout exceeded; try restarting transaction