MySQL InnoDB表锁定在存储过程中

时间:2013-10-27 13:35:54

标签: mysql innodb table-locking

我想知道为什么MySQL不允许在存储过程中锁定表。

我的存储过程中有以下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语句中选择的行数与实际更新的数量不同。

1 个答案:

答案 0 :(得分: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;

并且update命令更新整个表而不是仅属于一个用户的行 不要在过程中使用与表中列名相同的变量名称,最简单的方法是在变量名前加一些前缀以避免歧义,例如:

where u.user_id = var_user_id;