InnoDB
でのエラー処理は、必ずしも SQL
スタンダードに明記されている通りではありません。スタンダードによると、SQL
ステートメントでエラーが発生した場合は、その
SQL
ステートメントでロールバックを実行するように記述されています。InnoDB
では、ステートメントの一部のみ、またはトランザクション全体がロールバックされることがあります。次の項目は、InnoDB
でのエラー処理の仕様を説明しています:
テーブル領域内でファイル領域を使い果たすと、MySQL
の Table is full
エラーが発生し、InnoDB
が SQL ステートメントをロールバックします。
トランザクションデッドロックが発生すると、InnoDB
がトランザクション全体をロールバックします。これが発生した場合は通常、トランザクションの全体を再試行すべきです。
ロック待ちタイムアウトが発生した場合、InnoDB
は、ロック待機中にタイムアウトが発生した単一のステートメントのみをロールバックします。(トランザクション全体をロールバックさせるには、MySQL
5.1.15 以降で利用可能な
--innodb_rollback_on_timeout
オプションを指定してサーバーを起動する。)通常、現在の動作を使用している場合はステートメントを再試行し、--innodb_rollback_on_timeout
を使用している場合はトランザクション全体を再試行すべきです。
デッドロックとロック待ちタイムアウトはどちらもビジー状態のサーバーでは普通のことであるため、それらは起こりうる問題であり、発生時にはそれらを再試行することで解決する必要があることを意識したつくりにアプリケーションがなっている必要があります。それらの発生確率を低くするには、ロックの保持時間と対象となる行数が最小になるよう、トランザクションの最初のデータ変更からコミットまでの間に行う作業の量を極力減らします。作業を複数のトランザクションに分割することが、実用的で役に立つ場合もあります。
トランザクションロールバックが、デッドロックやロック待ちタイムアウトによって引き起こされると、それはトランザクション内のステートメントの効果をキャンセルします。しかし、トランザクション開始ステートメントが
START
TRANSACTION
か
BEGIN
ステートメントであると、ロールバックはこのステートメントをキャンセルしません。さらなる
SQL は、暗黙のコミットを引き起こす
COMMIT
、ROLLBACK
、またはいくつかの
SQL
ステートメントが発生するまでの間トランザクションの一部になります。
ステートメント内で
IGNORE
オプションを指定しなければ、重複キーエラーは
SQL ステートメントをロールバックします。
row too long error
は SQL
ステートメントをロールバックします。
その他のエラーは主に MySQL のコードレイヤ
(InnoDB
ストレージエンジンレベルの上)
によって検出され、対応する SQL
ステートメントがロールバックされます。ロックは単一
SQL
ステートメントのロールバック内でリリースされません。
暗黙のロールバックの最中に、明示的な
ROLLBACK
SQL
ステートメントの実行の最中と同じように、SHOW
PROCESSLIST
は関連する接続の
State
カラム内で
Rolling back
を表示します。