我想知道为什么 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 语句中选择的行数与实际更新的行数不同。
最佳答案
先生,在您的代码中您可以使用 ROW_COUNT()
函数代替 SELECT count(*)
根据文档:http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_row-count
ROW_COUNT() returns the number of rows changed, deleted, or inserted by the last statement if it was an UPDATE, DELETE, or INSERT. For other statements, the value may not be meaningful.
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;
关于MySQL InnoDB 表在存储过程中锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19618652/