MySQL InnoDB 表在存储过程中锁定

标签 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 语句中选择的行数与实际更新的行数不同。

最佳答案

先生,在您的代码中您可以使用 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/

相关文章:

mysql - 获取有多少用户响应了调查

php - 独特值的 SQL 查询(条目)

php - Mysql 多子查询限制

mysql - 到 BLOB 还是不到 BLOB

带表锁定的 Mysql 事务

php - php中isset()和empty()的区别

MySQL触发器语法错误

MySQL插入与子选择慢

php - 记录在交易过程中被删除

mysql - 无法通过 mysql 命令行手动将读或写锁应用到 Innodb 表中