MySQL AUTO_INCREMENT 値がロールバックされない理由と、それを解決する 4 つの方法
MySQL AUTO_INCREMENT とトランザクションのロールバック
MySQL の AUTO_INCREMENT
は、PRIMARY KEY
カラムに自動的に一意の値を生成する便利な機能です。しかし、トランザクションがロールバックされた場合でも、AUTO_INCREMENT で生成された値は元に戻らないという点に注意が必要です。
原因
AUTO_INCREMENT
値は、レコード挿入時に InnoDB データファイル に直接書き込まれます。トランザクションがロールバックされても、データファイルへの変更は元に戻らないため、AUTO_INCREMENT
値も元に戻りません。
影響
AUTO_INCREMENT
値がロールバックされない影響は以下の通りです。
- 連番が重複する可能性
- データの整合性が失われる可能性
対策
SEQUENCE
オブジェクトを使用する- アプリケーション側で独自の連番管理を行う
AUTO_INCREMENT
値は、InnoDB ストレージエンジン でのみ使用できます。SEQUENCE
オブジェクトは、MySQL 5.1
以降で利用可能です。
用語解説
- MySQL: オープンソースのデータベース管理システム
- トランザクション: 一連のデータベース操作をひとまとまりとして扱う機能
- InnoDB: MySQL で最もよく使用されるストレージエンジン
- PRIMARY KEY: テーブル内のレコードを一意に識別するカラム
- SEQUENCE: 連番を生成するためのオブジェクト
-- テーブル作成
CREATE TABLE animals (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255)
);
-- SEQUENCE オブジェクト作成
CREATE SEQUENCE animal_seq START WITH 1;
-- INSERT 文で SEQUENCE オブジェクトを使用
INSERT INTO animals (name)
VALUES ('rabbit')
SEQUENCE animal_seq NEXT VALUE;
-- ロールバック
ROLLBACK;
-- 確認
SELECT * FROM animals;
結果
id | name
------- | --------
1 | rabbit
解説
-- テーブル作成
CREATE TABLE animals (
id INT PRIMARY KEY,
name VARCHAR(255)
);
-- アプリケーション側で連番を生成
SET @next_id = (SELECT MAX(id) + 1 FROM animals);
-- INSERT 文でアプリケーション側で生成した連番を使用
INSERT INTO animals (id, name)
VALUES (@next_id, 'rabbit');
-- ロールバック
ROLLBACK;
-- 確認
SELECT * FROM animals;
id | name
------- | --------
1 | rabbit
BEFORE INSERT
トリガーを使用して、AUTO_INCREMENT
値を一時的に保存し、トランザクションがコミットされた場合にのみ永続化するようにすることができます。
外部キーを使用する
AUTO_INCREMENT
値を別のテーブルの外部キーとして使用することで、AUTO_INCREMENT
値の重複を防ぐことができます。
innodb_autoinc_lock_mode 設定を変更する
innodb_autoinc_lock_mode
設定を変更することで、AUTO_INCREMENT
値のロック方法を変更することができます。
これらの方法はそれぞれメリットとデメリットがあり、使用例に合わせて選択する必要があります。
mysql transactions innodb