2013-10-27 94 views
2

我想知道爲什麼MySQL不允許在存儲過程中鎖定表。MySQL存儲過程中的InnoDB表鎖定

我有我的存儲過程中的下列SQL語句:

-- Total amount of money for comments 
start transaction; 
select @num_comments := count(*) 
from `comment` c 
where 
    c.user_id = user_id and 
    c.payment_rejection = 'NO' and 
    c.is_recorded = 0; 
update `user` u set account_balance += u.comment_price * @num_comments where u.user_id = user_id; 
update `comment` c set is_recorded = 1 where c.user_id = user_id and c.payment_rejection = 'NO' and c.is_recorded = 0; 
commit; 

所以我要鎖表comment,以防止任何書面它可能會導致在第一個SQL語句所選擇的行數是不同於實際更新的數量。

+0

SHARE模式鎖定在你的SELECT查詢(不知道它是否和count(*)一起工作)..注意,如果INSERTS運行在鎖定記錄上並且更新需要很長時間,你將/可以獲得事務超時。 –

回答

1

先生,在你的代碼,你可以使用ROW_COUNT()函數代替SELECT count(*)

根據文檔:http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_row-count

ROW_COUNT()返回的行數改變,刪除或最後一條語句插入如果它是UPDATE,DELETE或INSERT。對於其他陳述,價值可能沒有意義。

start transaction; 

update `comment` c 
    set is_recorded = 1 
where c.user_id = v_user_id 
    and c.payment_rejection = 'NO' 
    and c.is_recorded = 0; 

SET @num_comments = row_count(); 

update `user` u 
    set account_balance += u.comment_price * @num_comments 
where u.user_id = v_user_id; 

commit; 

這樣就不需要鎖定表,行數不能語句之間變化,而獎金是整個交易的更高的速度。

一些評論:
user_id列在查詢含糊:

where u.user_id = user_id; 

和更新命令更新整個表,而不是行只屬於一個用戶。
不要在該過程,表中的列名使用變量相同的名稱,最簡單的方法就是前面加上前綴的一些變量名,以避免混淆,例如:

where u.user_id = var_user_id;