2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Auto_incrementとパーティションでバグった…MySQL5.7

Last updated at Posted at 2017-11-22

#はじめに
多分これは運用上、あんまり起こらない事であることをお伝えします。起こるとしたら以下の条件を満たした場合…だと考えられます。

  • MySQL5.7であること(他のはいつか検証します)
  • auto_increment(仮にidカラムとしましょうか)を指定したカラムを含む複合PKのテーブルである事。
  • auto_incrementカラム以外のPKカラム(日付で試したのでcreated_dateとします)に対してパーティションが組まれている事。
  • 複合PKに含まれるカラム(created_date)の値をupdateすること。

そもそもPKの値をupdateするなんて!!っていうのはごもっともな話。あくまで検証中の事故で気付いたので…ご勘弁ください。弁護するなら、パーティションを張るために本来であれば複合PKにしなくても良いカラムをしている場合もあるとは思います…。

#検証準備
以下のテーブルを用意します。

CREATE TABLE `t_log_test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `created_date` datetime NOT NULL DEFAULT '1999-01-01 00:00:00',
  PRIMARY KEY (`id`,`created_date`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
/*!50500 PARTITION BY RANGE  COLUMNS(created_date)
(PARTITION p1711 VALUES LESS THAN ('2017-12-01') ENGINE = InnoDB,
 PARTITION p1712 VALUES LESS THAN ('2018-01-01') ENGINE = InnoDB,
 PARTITION pmaster VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) */;

t-log_testテーブルについて以下のデータを入れます。

insert into t_log_test(created_date) VALUES("2017-12-01 10:15");

もちろん、正常に入ります。
パーティション的にはp1712に入っているはずです。

#検証実行

mysql> select * from t_log_test;
+----+---------------------+
| id | created_date        |
+----+---------------------+
|  1 | 2017-12-01 10:15:00 |
+----+---------------------+
1 row in set (0.00 sec)

入ってます。
ここで禁断の…created_dateをupdateします。(通常の運用では作った日付けとかよりもupdated_dateとかの方を更新することにはなると思いますが)

mysql> UPDATE t_log_test SET created_date='2017-11-30 10:15:34' where id=1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from t_log_test;
+----+---------------------+
| id | created_date        |
+----+---------------------+
|  1 | 2017-11-30 10:15:34 |
+----+---------------------+
1 row in set (0.00 sec)

このレコードが「入っていた」p1712を削除します。データはp1711に移動しているはずです。

mysql> ALTER TABLE t_log_test DROP PARTITION p1712;
Query OK, 0 rows affected (0.23 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> select * from t_log_test;
+----+---------------------+
| id | created_date        |
+----+---------------------+
|  1 | 2017-11-30 10:15:34 |
+----+---------------------+
1 row in set (0.00 sec)

うん消えていない。
もう一度レコードを挿入します。

mysql> select LAST_INSERT_ID( );
+-------------------+
| LAST_INSERT_ID( ) |
+-------------------+
|                 1 |
+-------------------+
1 row in set (0.00 sec)

mysql> insert into t_log_test(created_date) VALUES("2017-11-30 12:15:13");
Query OK, 1 row affected (0.04 sec)

LAST_INSERT_ID()関数でも見てますが想定ではIDが2になるはず。
結果は…

mysql> select * from t_log_test;
+----+---------------------+
| id | created_date        |
+----+---------------------+
|  1 | 2017-11-30 10:15:34 |
|  1 | 2017-11-30 12:15:13 |
+----+---------------------+
2 rows in set (0.00 sec)

ものの見事にauto_incrementの値が"リセット"されてしまってます。idを外部キーとして扱うシステムならこれで重大な問題につながります。
試しにDELETEで同じことをしてみたのですが再現はしませんでした。
恐らくauto_incrementの管理機能のバグではないかと思うのですが…単なる仕様かもしれません。

そもそもPKの更新などと言う恐ろしいことを実行する人はいないと思うのですが…まぁご参考程度に…。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?