1. 程式人生 > >for update在mysql中使用

for update在mysql中使用

查詢 數據量 times strong code 開啟事務 使用 link tro

一問題

需求是異步給 IM 發送link消息,所以有一張消息表,每次查詢發送失敗的數據,並對這些行數據加鎖,(避免別的線程再次查詢出來發送消息)

select * from message where id > ?1 AND message_status = ?2 and send_times < ?3 order by create_time asc for update

然後調用 IM發送消息的接口 進行補發,發現數據量較多時會出現發送兩次消息的情況。

經過分析,發現原來是查出來發送失敗的數據時候加鎖失敗,研究發現,原來 for update鎖表必須開啟事務,在begin與commit之間才生效。

二總結

InnoDB默認是行級別的鎖,當有明確指定的主鍵時候,是行級鎖。否則是表級別。

例子: 假設表foods ,存在有id跟name、status三個字段,id是主鍵,status有索引。

例1: (明確指定主鍵,並且有此記錄,行級鎖)
SELECT * FROM foods WHERE id=1 FOR UPDATE;
SELECT * FROM foods WHERE id=1 and state=’待發送’ FOR UPDATE;

例2: (明確指定主鍵/索引,若查無此記錄,無鎖)
SELECT * FROM foods WHERE id=-1 FOR UPDATE;

例3: (無主鍵/索引,表級鎖)
SELECT * FROM foods WHERE state=’待發送’ FOR UPDATE;

例4: (主鍵/索引不明確,表級鎖)
SELECT * FROM foods WHERE id<>’3’ FOR UPDATE;
SELECT * FROM foods WHERE id LIKE ‘3’ FOR UPDATE;

註意,for update 僅適用於InnoDB,並且必須開啟事務,在begin與commit之間才生效。

行級鎖時,不查到記錄,無鎖。 表級鎖時,不管是否查詢到記錄,都會鎖定表。

for update在mysql中使用