mita2 database life

主にMySQLに関するメモです

MySQL Clone Plugin を利用してスレーブが簡単に作れた

お題

  • MySQL 8.0 で導入された、Clone Plugin を利用してスレーブを作ってみる dev.mysql.com

やってみる

Clone プラグインをマスターとスレーブ、両方に設定しておきます。

MySQL 8.0 から plugin-load-add という書き方がサポートされました。従来のplugin-loadと比較して設定ファイルが見やすく書けますね。

$ sudo vi /etc/my.cnf
plugin_load_add                     = mysql_clone.so

SHOW PLUGINSプラグインがインストールできたことが確認できる。

mysql> pager grep -i clone
PAGER set to 'grep -i clone'

mysql> SHOW PLUGINS;
| clone                           | ACTIVE   | CLONE              | mysql_clone.so     | GPL     |
47 rows in set (0.01 sec)

clone用のユーザを作ります。BACKUP_ADMIN権限が必要です。

mysql> CREATE USER clone_user IDENTIFIED BY 'Password123!';
Query OK, 0 rows affected (0.05 sec)

mysql> GRANT BACKUP_ADMIN ON *.* TO clone_user;
Query OK, 0 rows affected (0.03 sec)

マスターの gtid_executed は以下です。CLONE INSTANCE でデータを正しくコピーできれば、スレーブの gtid_executedも以下になるはずです。

mysql> SHOW GLOBAL VARIABLES LIKE 'gtid_executed';
+---------------+------------------------------------------+
| Variable_name | Value                                    |
+---------------+------------------------------------------+
| gtid_executed | e9ec3499-62a3-11ea-8abd-901b0e97e768:1-3 |
+---------------+------------------------------------------+
1 row in set (0.00 sec)

スレーブでCLONE INSTANCEを実行しマスターのデータをコピーします。

mysql> SET GLOBAL clone_valid_donor_list = '192.168.10.3:3306';
Query OK, 0 rows affected (0.00 sec)

mysql> CLONE INSTANCE FROM clone_user@192.168.10.3:3306 IDENTIFIED BY 'Password123!';
Query OK, 0 rows affected (9.60 sec)

データがコピーされ、gtid_executed も一致しました。

mysql> SHOW GLOBAL VARIABLES LIKE 'gtid_executed';
+---------------+------------------------------------------+
| Variable_name | Value                                    |
+---------------+------------------------------------------+
| gtid_executed | e9ec3499-62a3-11ea-8abd-901b0e97e768:1-3 |
+---------------+------------------------------------------+
1 row in set (0.00 sec)

あとは、いつもどおり、CHANGE MASTER するだけ。

mysql> CHANGE MASTER TO MASTER_HOST='master', MASTER_PORT=3306,
MASTER_USER='repl', MASTER_PASSWORD='replpassword', MASTER_AUTO_POSITION=1, 
MASTER_HEARTBEAT_PERIOD=2, 
MASTER_CONNECT_RETRY=2, 
MASTER_RETRY_COUNT=86400,
MASTER_SSL=1;

mysqldump したり、手で物理コピーするのに比べて遥かに簡単にスレーブが作れてしまいました。ぱちぱちぱち。

ROW_FORMATとCHECKSUM TABLEの結果の違い

お題

  • CHECKSUM TABLEROW_FORMAT が異なっても同じ値を出すときがある。
    • どういう場合に、ROW_FORMAT が異なっていても、チェックサムが一致するのか?

CHECKSUM TABLE(おさらい)

CHECKSUM TABLE はテーブルの中身のチェックサムを取得するコマンドです。 比較対象のデータベースサーバで、静止点を設けられないとデータの比較ができないわけですが、 pt-table-checksum と違って、コマンド1つでデータを比較できるので手軽ですね。

データは一致しているのにCHECKSUMの結果が違うパターン

MySQLのバージョンによる違い

こちらはマニュアルにも書いてあります。5.6で TIME, DATETIME, TIMESTAMP 型の実装が変わりました。 5.5 と 5.6以降で時刻を含むテーブルのCHECKSUMの値は一致しなくなりました。

The checksum value depends on the table row format. If the row format changes, the checksum also changes.

For example, the storage format for temporal types such as TIME, DATETIME, and TIMESTAMP changed in MySQL 5.6 prior to MySQL 5.6.5, so if a 5.5 table is upgraded to MySQL 5.6, the checksum value may change.

サーバにインストールされているMySQLのバージョンでなく、データファイルが作られた時のバージョンに依存する点に注意です。 5.5をアップグレードし5.5の時に作成されたデータファイルを引き継いでいる場合は、CHECKSUMの値は、5.5のままです。

ROW_FORMATの違い

The checksum value depends on the table row format. If the row format changes, the checksum also changes.

と記載のあるように、ROW_FORMATが違う場合は、データが同じでも異なるチェックサムになる可能性があります。

実際に試します

COMPACTDYNAMICで比較してみます。 FLOAT, DOUBLE型の場合、ROW_FORMATの違いによりチェックサムが異なりました。

mysql> CREATE TABLE t_float_compact (syousu FLOAT) ENGINE=InnoDB ROW_FORMAT=COMPACT;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t_float_dynamic (syousu FLOAT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t_float_compact VALUES(1.11111);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO t_float_dynamic VALUES(1.11111);
Query OK, 1 row affected (0.00 sec)
mysql> CHECKSUM TABLE t_float_compact EXTENDED;
+-------------------+-----------+
| Table             | Checksum  |
+-------------------+-----------+
| t.t_float_compact | 108074716 |
+-------------------+-----------+
1 row in set (0.00 sec)

mysql> CHECKSUM TABLE t_float_dynamic EXTENDED;
+-------------------+------------+
| Table             | Checksum   |
+-------------------+------------+
| t.t_float_dynamic | 1104243724 |
+-------------------+------------+
1 row in set (0.00 sec)

しかし、VARCHAR は問題ないようです。

mysql> CHECKSUM TABLE t_varchar_compact EXTENDED;
+---------------------+------------+
| Table               | Checksum   |
+---------------------+------------+
| t.t_varchar_compact | 4048785154 |
+---------------------+------------+
1 row in set (0.00 sec)

mysql> CHECKSUM TABLE t_varchar_dynamic EXTENDED;
+---------------------+------------+
| Table               | Checksum   |
+---------------------+------------+
| t.t_varchar_dynamic | 4048785154 |
+---------------------+------------+
1 row in set (0.00 sec)

一通りの型を試すと以下のようになりました。

ROW_FORMAT=COMPACT/DYNAMIC による CHECKSUM 値の違い
CHAR あり
VARCHAR なし
TEXT なし
INT なし
DATETIME あり
TIMESTAMP あり
FLOAT あり
DOUBLE あり

複雑な条件がありそう

上記のように型に依存してCHECKSUMへの影響の有無が判断できるかというと、そうでもなさそうです。 以下は、VARCHARDATETIME を組み合わせた場合です。CHECKSUMの値は一致しています。

mysql> CREATE TABLE t_datetime_compact (c1 varchar(250) NOT NULL, hiduke DATETIME) ENGINE=InnoDB ROW_FORMAT=COMPACT;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t_datetime_dynamic (c1 varchar(250) NOT NULL, hiduke DATETIME) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO t_datetime_compact VALUES('aaaa', '2020-01-01 10:00:00');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO t_datetime_dynamic VALUES('aaaa', '2020-01-01 10:00:00');
Query OK, 1 row affected (0.00 sec)

mysql> CHECKSUM TABLE t_datetime_compact EXTENDED;
+----------------------+------------+
| Table                | Checksum   |
+----------------------+------------+
| t.t_datetime_compact | 1594517058 |
+----------------------+------------+
1 row in set (0.00 sec)

mysql> CHECKSUM TABLE t_datetime_dynamic EXTENDED;
+----------------------+------------+
| Table                | Checksum   |
+----------------------+------------+
| t.t_datetime_dynamic | 1594517058 |
+----------------------+------------+
1 row in set (0.00 sec)

しかし、DATETIME型、単体だと、CHECKSUMが異なります・・・

mysql> CREATE TABLE t_datetime_compact (hiduke DATETIME) ENGINE=InnoDB ROW_FORMAT=COMPACT;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t_datetime_dynamic (hiduke DATETIME) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t_datetime_compact VALUES('2020-01-01 10:00:00');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO t_datetime_dynamic VALUES('2020-01-01 10:00:00');
Query OK, 1 row affected (0.00 sec)

mysql> CHECKSUM TABLE t_datetime_compact EXTENDED;
+----------------------+------------+
| Table                | Checksum   |
+----------------------+------------+
| t.t_datetime_compact | 1668604533 |
+----------------------+------------+
1 row in set (0.00 sec)

mysql> CHECKSUM TABLE t_datetime_dynamic EXTENDED;
+----------------------+------------+
| Table                | Checksum   |
+----------------------+------------+
| t.t_datetime_dynamic | 3856699611 |
+----------------------+------------+
1 row in set (0.00 sec)

FLOAT型も同様でした。

まとめ

  • ROW_FORMATが違う場合は 型によってCHECKSUM TABLEの結果が異なる場合がある
  • しかし、型の組み合わせによっては、同じチェックサムになる場合がある

TRIGGERの権限とDEFINER

お題

  • トリガーってどの権限で動くんだっけ? 定義したユーザの権限? トリガーを引いたユーザの権限?
  • プロシージャと違って、SQL SECURITY の指定がない

TLDR;

  • トリガーはDEFINERに指定したユーザで動作する
  • DEFINERをナシにすることはできない、省略した場合はCREATE TRIGGERを実行したユーザがDEFINERに入る
  • SQL SECURITYは指定できない。トリガーを引いたユーザで、トリガーを実行することはできない。DEFINERで指定したユーザで必ず実行される
  • SUPERを持っているのに、read_onlyのDBに書き込めない場合は、トリガーを疑うべし

試します

適当にテーブルを作ります。

-- トリガーを仕掛けるテーブル
mysql> CREATE TABLE tbl_p (pk SERIAL PRIMARY KEY, var1 VARCHAR(100), updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.02 sec)

-- トリガーによって更新するテーブル
mysql> CREATE TABLE tbl_c (pk SERIAL PRIMARY KEY, triggered_by VARCHAR(100), updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.02 sec)

tbl_p に行をINSERTすると、tbl_c に行をINSERTするトリガーを作ります。 このときに、triggered_by カラムにどのユーザで実行されたかを INSERT INTO tbl_c (triggered_by) VALUES(CURRENT_USER()) のようにして、記録しておきます。

delimiter //
 CREATE TRIGGER trg_t BEFORE INSERT ON tbl_p
       FOR EACH ROW
       BEGIN
           INSERT INTO tbl_c (triggered_by) VALUES(CURRENT_USER());
    END; //
delimiter ;
mysql> SHOW CREATE TRIGGER t.trg_t \G
*************************** 1. row ***************************
               Trigger: trg_t
              sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
SQL Original Statement: CREATE DEFINER=`user1`@`%` TRIGGER `trg_t` BEFORE INSERT ON `tbl_p` FOR EACH ROW BEGIN
           INSERT INTO tbl_c (triggered_by) VALUES(CURRENT_USER());
    END
  character_set_client: utf8mb4
  collation_connection: utf8mb4_0900_ai_ci
    Database Collation: utf8mb4_general_ci
               Created: 2020-03-06 16:16:50.90
1 row in set (0.00 sec)

DEFINERを省略すると、CREATE TRIGGERを実行したユーザがDEFINERとなりますね。 DEFINERを省略するということはできないようです。

トリガーの動作確認。トリガーがDEFINERの user1 で動作することが確認できました。

mysql> INSERT INTO tbl_p (var1) VALUES('test');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM tbl_c;
+----+--------------+---------------------+
| pk | triggered_by | updated_at          |
+----+--------------+---------------------+
|  1 | user1@%      | 2020-03-06 16:18:53 |
+----+--------------+---------------------+
1 row in set (0.00 sec)

念の為、root でトリガーを引いてみます。 root でトリガーを引いても、user1の権限で tbl_c に INSERTが行われたことが分かりました。

mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

mysql> INSERT INTO tbl_p (var1) VALUES('test');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM tbl_c;
+----+--------------+---------------------+
| pk | triggered_by | updated_at          |
+----+--------------+---------------------+
|  1 | user1@%      | 2020-03-06 16:18:53 |
|  2 | user1@%      | 2020-03-06 16:19:27 |
+----+--------------+---------------------+
2 rows in set (0.00 sec)

read only のときの挙動

read_only でも SUPER 権限があれば書き込むことができます。 しかし、上述のようにTRIGGERはDEFINERの権限で動作するため、read_only状態でトリガーのある書き込もうとすると、エラーとなります。

mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

-- トリガーのないテーブルには書き込める
mysql> INSERT INTO tx1 VALUES(1);
Query OK, 1 row affected (0.01 sec)

-- superを持たないユーザが作ったトリガーがあると書き込めない
mysql> INSERT INTO tbl_p (var1) VALUES('I am super');
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement

MySQLのスロークエリログにはエラーになったクエリが含まれる?

お題

  • エラーになったクエリはスロークエリログに記録されるのか?
  • されるとしたら、エラーになったクエリであることは判別可能なのか?

試してみます

1. 文法エラー

まずは、文法エラー。

mysql> UPDATE t.tx1 SET c1  100;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds 
to your MySQL server version for the right syntax to use near '100' at line 1

文法エラーでも、ログに落ちました。文法エラーでログが落ちるということは、どんなエラーでも、スロークエリログにクエリが書かれる予感がします(早速、答えが出てしまった)。

# Time: 2020-02-25T21:13:22.700729+09:00
# User@Host: root[root] @ localhost []  Id:    15
# Query_time: 0.000100  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 0 Thread_id: 15 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 162 Read_first: 0 Read_last: 0 Read_key: 0 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Start: 2020-02-25T21:13:22.700629+09:00 End: 2020-02-25T21:13:22.700729+09:00
SET timestamp=1582632802;
UPDATE t.tx1 SET c1  100;

2. 制約違反

Duplicate Entry の場合。

mysql> INSERT INTO t.tx1 VALUES(1, 100);
ERROR 1062 (23000): Duplicate entry '1' for key 'tx1.PRIMARY'

制約違反でもログに落ちました。MySQL 8.0 で登場した log_slow_extra を 有効にして、スロークエリログに記録される項目を増やしています。 Errno0(エラーなし扱い) のままみたいです。

# Time: 2020-02-25T22:05:24.647928+09:00
# User@Host: root[root] @ localhost []  Id:    84
# Query_time: 0.000537  Lock_time: 0.000235 Rows_sent: 0  Rows_examined: 0 Thread_id: 84 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 54 Read_first: 0 Read_last: 0 Read_key: 0 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Start: 2020-02-25T22:05:24.647391+09:00 End: 2020-02-25T22:05:24.647928+09:00
SET timestamp=1582635924;
INSERT INTO t.tx1 VALUES(1, 100);

3. ロックタイムアウト

mysql> UPDATE t.tx1 SET c1 = 100;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

ハイ、こちらもログに落ちます。しかし、相変わらず、Errno0 です。

# Time: 2020-02-25T21:11:55.309032+09:00
# User@Host: root[root] @ localhost []  Id:    14
# Query_time: 4.001521  Lock_time: 4.001169 Rows_sent: 0  Rows_examined: 1 Thread_id: 14 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 67 Read_first: 1 Read_last: 0 Read_key: 1 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 2 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Start: 2020-02-25T21:11:51.307511+09:00 End: 2020-02-25T21:11:55.309032+09:00
SET timestamp=1582632711;
UPDATE t.tx1 SET c1 = 100;

4. 中断

エラーではありませんが、Ctrl-C で中断したパターンも試してみます。

mysql> SELECT SLEEP(10);
^C^C -- query aborted
+-----------+
| SLEEP(10) |
+-----------+
+-----------+
1 row in set (2.61 sec)

相変わらず、Errno0 です。 Errno はいつ 0 以外の値になるんですかねぇ・・・

# Time: 2020-02-25T21:02:38.084781+09:00
# User@Host: root[root] @ localhost []  Id:     9
# Query_time: 2.612076  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 1 Thread_id: 9 Errno: 0 Killed: 0 Bytes_received: 0 Bytes_sent: 57 Read_first: 0 Read_last: 0 Read_key: 0 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 Sort_merge_passes: 0 Sort_range_count: 0 Sort_rows: 0 Sort_scan_count: 0 Created_tmp_disk_tables: 0 Created_tmp_tables: 0 Start: 2020-02-25T21:02:35.472705+09:00 End: 2020-02-25T21:02:38.084781+09:00
SET timestamp=1582632155;
SELECT SLEEP(10);

まとめ

  • エラーになったクエリはスロークエリログに記録されるのか?→YES
  • されるとしたら、エラーになったクエリであることは判別可能なのか?→NO
    • Errno にエラー番号が書かれないケースがありそう(というか、Errno書かれるケースが不明)

参考

tom__bo さんが、先日、スロークエリログに関するエントリーを書いてました。 こちらもあわせてどうぞ。

tombo2.hatenablog.com

MySQL 8.0 で無理矢理ダウングレードを試みる(未完了)

以前も書きましたが、MySQL のバージョンが 8.0 になってからダウングレードが出来なくなりました。マイナーバージョンであってもダウングレードすることが出来ません。ダウングレードするには、古いバージョンをインストールしたサーバを用意し、mysqldumpでデータを投入しなおす必要があります。

mita2db.hateblo.jp

バイナリハックで無理矢理ダウングレード

mysqldump するのが面倒。。。ということで、データファイルをいじって、どうにか古いバージョンで起動できないかやってみます。 結論から言うと、まだ攻略できずにいます。

以下、作業記録。

ダウングレードした際のエラーメッセージから、mysql.ibd にバージョン情報が含まれていることが推測できます。 mysql.ibdに記録されているバージョンを古いバージョンに無理矢理書き換えることができれば、古いバイナリでも起動できる可能性がありそうです。

2020-02-09T05:03:23.282471Z 1 [ERROR] [MY-013171] [InnoDB] Cannot boot server version 80018 on data directory built by version 80019. Downgrade is not supported
mysqld: Can't open file: 'mysql.ibd' (errno: 0 - )

経験からだいたい、データファイルの先頭のヘッダ部分にこういったメタ情報が(バイナリで)書かれているであろうと推測できます。 8.0.19を示す、80019 を 16進数にした値を頭にいれておきます。mysql.ibdにこのバイナリ列がどこかにあるはずです。

# printf %x 80019
13893

やっぱり、先頭の9バイト目〜12バイトの4バイトにバージョンが書かれていそうです。

# xxd mysql.ibd | head -n2
0000000: d42f 71ae 0000 0000 0001 3893 0000 0001  ./q.......8.....
                             ^^^^^^^^^
0000010: 0000 0000 6e1d 5d0e 0008 0000 0000 0000  ....n.].........

データファイルのバイト列を書き換えます。まずは、xxd で16進数のテキストファイルに変換し、編集しやすくします。

# xxd -p mysql.ibd > mysql.ibd.hex
# head -n1 mysql.ibd.hex
d42f71ae000000000001389300000001000000006e1d5d0e000800000000

013893の部分を013892 に差し替えます。

# echo $(head -n1 mysql.ibd.hex | cut -b1-18)013892$(head -n1 mysql.ibd.hex | cut -b25-) > mysql.ibd.8018hex
# tail -n +2 mysql.ibd.hex >> mysql.ibd.8018hex

16進のテキストファイルからバイナリに戻します。

$ cat mysql.ibd.8018hex | xxd -r -p - - > mysql.ibd
$ chown mysql:mysql mysql.ibd

起動してみる

(゜д゜)<あらやだ!

先ほどのメッセージは出なくなったものの、checksum で弾かれてしまった。

2020-02-09T12:10:09.861801Z 1 [ERROR] [MY-012224] [InnoDB] Checksum mismatch in datafile: mysql.ibd, Space ID:4294967294, Flags: 18432. 
Please refer to http://dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting-datadict.html for how to resolve the issue.

checksum を無視しちゃいましょう。

$ vim /etc/my.cnf
innodb_checksum_algorithm=none

それでも、まだエラーがでて、起動できませんね。。。ぐぬぬ

2020-02-09T12:16:22.837006Z 1 [ERROR] [MY-013326] [Server] Upgrading the server from server version '80019' is not supported.

エラーメッセージからソースコードを追っていきます。

# grep -B1 -r 'Upgrading the server' share/errmsg-utf8.txt
ER_SERVER_UPGRADE_VERSION_NOT_SUPPORTED
  eng "Upgrading the server from server version '%u' is not supported."

dd 、つまり Data Dictionary でチェックが入ってそうです。

# grep -r ER_SERVER_UPGRADE_VERSION_NOT_SUPPORTED *
share/errmsg-utf8.txt:ER_SERVER_UPGRADE_VERSION_NOT_SUPPORTED
sql/dd/impl/bootstrap/bootstrapper.cc:        LogErr(ERROR_LEVEL, ER_SERVER_UPGRADE_VERSION_NOT_SUPPORTED,
sql/dd/impl/bootstrap/bootstrapper.cc:        LogErr(ERROR_LEVEL, ER_SERVER_UPGRADE_VERSION_NOT_SUPPORTED,

ソースを辿っていくと、DDのテーブルごとのエントリーにバージョン情報が含まれていて、ここも書き換えないとダメそうです。 sql/dd/impl/tables/dd_properties.cc

 68   /*
 69     Initialize the descriptors of the valid keys. The keys are used for
 70     the following purposes:
 71
 72       DD_VERSION                Actual DD version.
 73       IS_VERSION                Actual I_S version.
 74       PS_VERSION                Actual P_S version.
 75       SDI_VERSION               Actual SDI version.
 76       LCTN                      L_C_T_N setting used during
 77                                 --initialize.
 78       MYSQLD_VERSION_LO         Lowest server version which has
 79                                 been using the data directory.
 80       MYSQLD_VERSION_HI         Highest server version which has
 81                                 been using the data directory.
 82       MYSQLD_VERSION            Current server version.
 83       MINOR_DOWNGRADE_THRESHOLD The current DD can be used by
 84                                 previous MRUs, unless their
 85                                 target DD version is less than
 86                                 the downgrade threshold.
 87       SYSTEM_TABLES             List of system tables with
 88                                 definitions.
 89       UPGRADE_TARGET_SCHEMA     Temporary schema used during
 90                                 upgrade.
 91       UPGRADE_ACTUAL_SCHEMA     Temporary schema used during
 92                                 upgrade.
 93       MYSQLD_VERSION_UPGRADED   The server version of the last
 94                                 completed successful upgrade.
 95   */
 96   m_property_desc = {

うーん、ちょっとこれは、一筋縄では行かない予感がしてきました。つづく?

MySQL Casual Talks vol.13 を開催しました

  今週、MySQL Casual Talks vol.13 を開催しました。

mysql-casual.connpass.com

コロナウィルスの件もあり、どれぐらいの方が参加してくれるか心配だったのですが、当日は雨にもかかわらず、30名以上の方が参加してくださいました。よかったです。

最初の「カシュッ」を忘れてしまったのが、反省点ですw

MySQL 8.0 のパラメータ

自分は、MySQL 8のパラメータについて話しました。

当日、紹介した @tmtms さんの MySQL Parameters 、またパワーアップしてました。

www.slideshare.net

Introduction to orchestrator (MySQL)

@tom__bo さん

Slide23 の Recovery hooks の図が非常にわかりやすい。

speakerdeck.com

「orchestratorとGTID運用を支える監視」の勉強

@kazeburo さん

そうだ!Errata GTIDの監視 やらないと!!ってなりました。GTIDの不一致状態のことをErrata GTIDって呼ぶのだと知れたのも収穫でした。

speakerdeck.com

MySQL 8.0 の薄い本を 1 年間更新し続けてみた話

@hmatsu47 さん

継続して更新しているのがすごい。あらためてまとめてみるとその大変さがわかりますね。。。

speakerdeck.com

文字コード変更対応している話

@_awache さん

slave_type_conversions っていうパラメータ知らなかったー! あと、絵文字とか特殊な記号を使わなければ、utf8 (utf8mb3) でも良いのかなと思ってましたが、一部の漢字はutf8mb4でないと扱えないということを知れて、勉強になりました。

speakerdeck.com

グラフで見るMySQL5.6と8.0

バージョンアップした前後でメトリックのグラフを見比べるの楽しそうです。 1日中、メトリックを眺めてたい!(忙しくて無理)

www.slideshare.net

MySQLと空間データ(GIS)~Software Design 誌へのGIS連載と、公開されている地理情報データをMySQLに取り込むお話

@sakaik さん

3/4 に 日本MySQLユーザ会の20周年記念パーティがあるとのこと! 20周年すごい! めでたい!

www.slideshare.net

MySQL explicit_defaults_for_timstamp ON と OFF の CREATE TABLE 時の挙動

explicit_defaults_for_timstampMySQL 8.0 からデフォルトで ON になりました。アプリケーションに影響が出る可能性があるため、要点を確認しました。 DML の挙動の変化は yoku0825 さんがまとめてます。

yoku0825.blogspot.com

CREATE TABLE の挙動の変化

DDL への影響を忘れずに、メモしておきたいと思います。 以下のようにTIMESTAMP型のデフォルト値を指定しなかった場合に、カラムの定義が異なります。

mysql> CREATE TABLE t_on (ts TIMESTAMP);

explicit_defaults_for_timstamp = OFF (〜5.7 までの挙動)

NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP が自動で設定されます。 よって、レコード更新時に自動で現在時刻が保存されます。

CREATE TABLE `t_off` (
  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) ENGINE=InnoDB

explicit_defaults_for_timstamp = ON (8.0〜の挙動)

NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP が設定されません。 この状態では、レコード更新時に自動で時刻が保存されません。更新クエリで、明示的に値を NOW() を指定して現在時刻に UPDATEするか、CREATE TABLE 時に NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP を明示的に指定する必要があります。

CREATE TABLE `t_on` (
  `ts` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT 

5.7 から DYNAMIC に変更できる

explicit_defaults_for_timstamp は 5.6 では 動的に変更できませんでした。 5.7 以降では 動的に設定変更が可能です。