MariaDBでAUTO_INCREMENTの値が戻る罠

GMOアドマーケティングのT.Kです。
MariaDBでAUTO_INCREMENTの値が戻る現象に遭遇したので、紹介したいと思います。
発生条件はパーティションを使っているテーブルに対して、並列トランザクションでINSERTを行い、片方のトランザクションで払い出したAUTO_INCREMENTの値を使わなかった場合です。
- 検証環境
OS: CentOS 7
DB: MariaDB 10.4.13
各種設定はデフォルト値 - 再現手順
- テーブルテーブル作成MySQL12345678910111213CREATETABLE`hoge_report`(`id`BIGINT(20)UNSIGNEDNOT NULLAUTO_INCREMENT,`hoge_id`INT(10)NOT NULL,`request`INT(10)NOT NULL,`report_date`dateNOT NULL,PRIMARY KEY(`id`,`report_date`),UNIQUEKEY(`hoge_id`,`report_date`))ENGINE=InnoDBPARTITION BYRANGE COLUMNS(`report_date`)(PARTITION`p202002`VALUESLESS THAN('2020-03-01'),PARTITION`p202003`VALUESLESS THAN('2020-04-01'));
- transaction1transaction1MySQL12>INSERTINTOhoge_report(hoge_id,request,report_date)VALUES(1,10,'2020-02-29');QueryOK,1rowaffected(0.001sec)
- transaction2
ロック待ちにするために、transaction1と同じUNIQUE KEYを使用します。transaction 2MySQL1>INSERTINTOhoge_report(hoge_id,request,report_date)VALUES(1,15,'2020-02-29'); - transaction1transaction1MySQL12345678910111213>INSERTINTOhoge_report(hoge_id,request,report_date)VALUES(2,20,'2020-02-29');QueryOK,1rowaffected(0.001sec)MariaDB[test]>SELECTAUTO_INCREMENTfrominformation_schema.`TABLES`WHERETABLE_NAME='hoge_report';+----------------+|AUTO_INCREMENT|+----------------+| 4|+----------------+1rowinset(0.001sec)MariaDB[test]>commit;QueryOK,0rowsaffected(0.002sec)
- transaction21ERROR1062(23000):Duplicateentry'1-2020-02-29'forkey'hoge_id'
- テーブル
- 状態の確認
ここまでは想定通りの動作のように見えます。
しかし、改めてAUTO_INCREMENTを確認すると「2」に戻っています。123456>SELECTAUTO_INCREMENTfrominformation_schema.`TABLES`WHERETABLE_NAME='hoge_report';+----------------+|AUTO_INCREMENT|+----------------+| 2|+----------------+
追加でデータをINSERTすると、しっかり「2」が使われています。123456789101112>INSERTINTOhoge_report(hoge_id,request,report_date)VALUES(10,100,'2020-02-29');QueryOK,1rowaffected(0.001sec)MariaDB[test]>select *fromhoge_report;+----+---------+---------+-------------+|id|hoge_id|request|report_date|+----+---------+---------+-------------+| 1| 1| 10|2020-02-29 || 2| 10| 100|2020-02-29 || 3| 2| 20|2020-02-29 |+----+---------+---------+-------------+3rowsinset(0.000sec)
AUTO_INCREMENTは「3」に増えて、更に同じ日のデータをINSERTしようとするとDuplicate entryエラーが発生します12345678910>SELECTAUTO_INCREMENTfrominformation_schema.`TABLES`WHERETABLE_NAME='hoge_report';+----------------+|AUTO_INCREMENT|+----------------+| 3|+----------------+1rowinset(0.002sec)MariaDB[test]>INSERTINTOhoge_report(hoge_id,request,report_date)VALUES(11,110,'2020-02-29');ERROR1062(23000):Duplicateentry'3-2020-02-29'forkey'PRIMARY' - 対策
- 案1
AUTO_INCREMENTの代わりにSEQUENCEを使う - 案2
MariaDB 10.2以下を使う(10.3も値が戻る)
- 案1
- まとめ
実際のシステムではON DUPLICATE KEY UPDATE を使っていたため、
エラーは発生せず、データの不整合が起きて、調査に時間がかかりました。
動作検証の段階で問題に気づけたのは良かったです。
互換性があるという思い込みが危険だということを改めて認識しました。







