ユーザーからデータを受け取ると、毎回入力の形式を検証します(PHP)。検証できない(または検証したくない)唯一のことは、制約(外部キーなど)違反です。DMLにエラーを発生させ、データベースドライバーに例外をスローさせます。それをキャッチした後、MySQLのエラーコードによっていくつかのエラーメッセージを出力します。
問題は、挿入が失敗した場合でも、autoincrement
シーケンスが成長し、増加することです。どうすればそれを防ぐことができますか?
ユーザーからデータを受け取ると、毎回入力の形式を検証します(PHP)。検証できない(または検証したくない)唯一のことは、制約(外部キーなど)違反です。DMLにエラーを発生させ、データベースドライバーに例外をスローさせます。それをキャッチした後、MySQLのエラーコードによっていくつかのエラーメッセージを出力します。
問題は、挿入が失敗した場合でも、autoincrement
シーケンスが成長し、増加することです。どうすればそれを防ぐことができますか?
これが、値とシーケンスの自動インクリメントの仕組みです。値が使用される場合、トランザクションが失敗してもその値は再利用されず、トランザクションはロールバックされます。
自動増分値を使用しているため、実際の値は重要ではないため、数値が欠落しているという美学を除けば、スペースは問題になりません。
ストアドプロシージャを使用して、挿入する前にエラーがあるかどうかを確認し、エラー条件ごとにRaise Application Errorを作成して、挿入プロセスでエラーが発生したときにauto_incrementが増加しないようにする必要があります。これは、ストアドプロシージャ内でエラーが発生した場合に、挿入プロセスを実行できる条件を設定できるためです。エラーアカウントがシグナル状態=1か何かを設定し、シグナル状態== 1の場合、ストアドプロシージャを終了し、挿入stmtを実行しません。そんな感じです。
そして2番目のオプションは、エラーが発生したときにauto_incrementをリセットすることです。
ALTER TABLE table_name AUTO_INCREMENT = ?
ただし、auto_incrementを設定するにはlast_idを知る必要があります。イベントでは、last_id値がauto_incrementであるかどうかを知る必要はありません。1に設定すると、MySQLは次のauto_incrementをレコードの最大キー+1に設定します。
データベースの最大IDが7であるとすると、2つの新しいレコードを挿入しようとしますが、どちらもエラーを返し、auto_incrementが増加して10になります。次にALTER TABLE table_name AUTO_INCREMENT = 1 ; auto_incrementは8に戻ります。
これらは両方とも、エラーが発生したときにauto_increment値を制御する方法であり、もちろん、アプリケーション層でデータベースに挿入する前に、検証ステップで処理する必要があるため、データベースに挿入するときに、アプリケーション層でこれを注意深く処理すれば、エラーは発生しません。
innodb_autoinc_lock_modeを0または2に設定する必要がある場合があります。