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

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 コマンドは、行が 1 人のユーザーのみに属するのではなく、テーブル全体を更新します。
プロシージャ内の変数に、テーブル内の列名と同じ名前を使用しないでください。最も簡単な方法は、あいまいさを避けるために、変数名の前にいくつかのプレフィックスを追加することです。次に例を示します。

where u.user_id = var_user_id;
于 2013-10-28T08:11:17.920 に答える