3

我想知道为什么 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 语句中选择的行数与实际更新的行数不同。

4

1 回答 1

1

先生,在您的代码中,您可以使用ROW_COUNT()函数而不是SELECT count(*)

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

如果是 UPDATE、DELETE 或 INSERT,ROW_COUNT() 返回最后一条语句更改、删除或插入的行数。对于其他语句,该值可能没有意义。

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;
于 2013-10-28T08:11:17.920 回答