Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ぼくらが8.0に至ったみちのり(踏破) -replise-

yoku0825
August 19, 2019

ぼくらが8.0に至ったみちのり(踏破) -replise-

2019/08/19 日本MySQLユーザ会会 2019年8月
- https://mysql.connpass.com/event/142299/

yoku0825

August 19, 2019
Tweet

More Decks by yoku0825

Other Decks in Technology

Transcript

  1. パラレルIndex READ 8.0.14から 8.0.17現在、 CHECK TABLE くらいしか目立った恩恵はな いっぽい そのうち mysqldump

    や mysqlpump でも使ってくれるように なるんではないか Clustered Indexのパラレル読み込みだから、分析系のクエ リーはきっと使わないけれども 5/147
  2. 式デフォルト 8.0.13から 今までは DATETIME とかそれ系に CURRENT_TIMESTAMP しか使 えなかった関数デフォルトが解禁 これにより、 GEO系のデータ型にデフォルト値が突っ込め

    るようになったり、今までデフォルトが持てなかった BLOB 型にデフォルトが設定できるようになったり DEFAULT CURRENT_DATE() + INTERVAL 1 YEAR) ‐ DEFAULT RAND() * RAND() ‐ DEFAULT UUID_TO_BIN(UUID()) ‐ 7/147
  3. Clone Plugin 全国1.000000人のDBAが待ち望んだ機能 なんとこの2行だけでオンライン物理バックアップが取れる mysql80 672> INSTALL PLUGIN clone SONAME

    'mysql_clone.so'; Query OK, 0 rows affected (0.02 sec) mysql80 672> CLONE LOCAL DATA DIRECTORY '/tmp/clone'; Query OK, 0 rows affected (0.39 sec) 9/147
  4. CLONE LOCAL DATA $ ll /tmp/clone total 161800 drwxr-x--- 2

    yoku0825 yoku0825 85 Aug 19 16:39 #clone drwxr-x--- 2 yoku0825 yoku0825 19 Aug 19 16:39 d1 -rw-r----- 1 yoku0825 yoku0825 12582912 Aug 19 16:39 ibdata1 -rw-r----- 1 yoku0825 yoku0825 50331648 Aug 19 16:39 ib_logfile0 -rw-r----- 1 yoku0825 yoku0825 50331648 Aug 19 16:39 ib_logfile1 drwxr-x--- 2 yoku0825 yoku0825 6 Aug 19 16:39 mysql -rw-r----- 1 yoku0825 yoku0825 24117248 Aug 19 16:39 mysql.ibd drwxr-x--- 2 yoku0825 yoku0825 27 Aug 19 16:39 sys -rw-r----- 1 yoku0825 yoku0825 14680064 Aug 19 16:39 undo_001 -rw-r----- 1 yoku0825 yoku0825 13631488 Aug 19 16:39 undo_002 10/147
  5. Clone Plugin 全国1.000000人のDBAが待ち望んだ機能 まずはマスター側にアカウントを作成 Cloneプラグインはインストール済みとして ‐ mysql80 674> CREATE USER

    cloner IDENTIFIED WITH mysql_native_pass word BY 'secret'; Query OK, 0 rows affected (0.04 sec) mysql80 674> GRANT BACKUP_ADMIN ON *.* TO cloner; Query OK, 0 rows affected (0.01 sec) 11/147
  6. CLONE INSTANCE 次いでスレーブになる側 mysql> INSTALL PLUGIN clone SONAME 'mysql_clone.so'; Query

    OK, 0 rows affected (0.01 sec) mysql> SET GLOBAL clone_valid_donor_list = '127.0.0.1:64080'; Query OK, 0 rows affected (0.00 sec) mysql> CLONE INSTANCE FROM [email protected]:64080 IDENTIFIED BY 'secret'; Query OK, 0 rows affected (1.55 sec) /* ここでいちどRESTARTがかかる */ 12/147
  7. CLONE INSTANCE あとは CHANGE MASTER TO するだけ。情報は performance_schema.clone_status にある mysql>

    SELECT * FROM performance_schema.clone_status\G *************************** 1. row *************************** ID: 1 PID: 0 STATE: Completed BEGIN_TIME: 2019-08-19 16:59:53.658 END_TIME: 2019-08-19 17:00:00.131 SOURCE: 127.0.0.1:64080 DESTINATION: LOCAL INSTANCE ERROR_NO: 0 ERROR_MESSAGE: BINLOG_FILE: bin.000011 BINLOG_POSITION: 195 GTID_EXECUTED: 552f89cd-aded-11e9-9af8-0201a32caf75:1-21 1 row in set (0.00 sec) 13/147
  8. CLONE INSTANCE こんなエラーで START GROUP_REPLICATION に失敗しても 2019-08-19T09:24:12.214486Z 0 [Warning] [MY-013470]

    [Repl] Plugin group_replication reported: 'As no ONLINE member has the missing data for recovering in its binary logs, this member will use clo ning as its recovery strategy.' 2019-08-19T09:24:13.251773Z 0 [ERROR] [MY-013464] [Repl] Plugin g roup_replication reported: 'There was an issue when configuring t he remote cloning process: The clone plugin is not present or act ive in this server.' 2019-08-19T09:24:13.251836Z 0 [ERROR] [MY-013467] [Repl] Plugin g roup_replication reported: 'No valid or ONLINE members exist to g et the missing data from the group. For cloning check if donors o f the same version and with clone plugin installed exist. For dis tributed recovery check if you have donors where the required dat a was not purged from the binary logs.' 14/147
  9. CLONE INSTANCE Cloneを使えばさっくりと mysql> INSTALL PLUGIN clone SONAME 'mysql_clone.so'; Query

    OK, 0 rows affected (0.11 sec) mysql> SET GLOBAL clone_valid_donor_list= '172.17.0.3:3306'; Query OK, 0 rows affected (0.00 sec) mysql> CLONE INSTANCE FROM [email protected]:3306 IDENTIFIED BY 'ccc'; ERROR 3707 (HY000): Restart server failed (mysqld is not managed by supervisor pro cess). mysql> CHANGE MASTER TO master_user= 'gr', master_password= 'ccc' FOR CHANNEL 'gro up_replication_recovery'; Query OK, 0 rows affected, 2 warnings (0.02 sec) mysql> SET GLOBAL group_replication_group_seeds= '172.17.0.3:13306,172.17.0.4:1330 6'; Query OK, 0 rows affected (0.00 sec) mysql> start group_replication; Query OK, 0 rows affected (3.88 sec) 15/147
  10. MySQL 8.0 mysql80 160> SELECT CURDATE() /* JST */; +------------+

    | CURDATE() | +------------+ | 2018-04-20 | +------------+ 1 row in set (0.00 sec) mysql80 160> SELECT @@version; +-----------+ | @@version | +-----------+ | 8.0.11 | +-----------+ 1 row in set (0.00 sec) 20/147
  11. MySQL 8.0 mysql80 671> SELECT CURDATE() /* JST */; +------------+

    | CURDATE() | +------------+ | 2019-08-19 | +------------+ 1 row in set (0.00 sec) mysql80 671> SELECT @@version; +-----------+ | @@version | +-----------+ | 8.0.17 | +-----------+ 1 row in set (0.00 sec) 21/147
  12. MySQL 8.0 ナッツシェル( What is New in MySQL 8.0 の章)が何故か

    どんどん増える $ curl -L -s https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshe ll.html | perl -nlE 'if ($_ =~ /(8\.0\.\d+)/) { say $1 }' | sort -t "." -k 3 -n | uniq -c 1 8.0.0 3 8.0.2 3 8.0.3 2 8.0.4 2 8.0.12 6 8.0.13 6 8.0.14 8 8.0.16 8 8.0.17 8.0.15はガチで8.0.14のリグレッションを1件だけ直した「メンテナンスリリース」だった。よってWhat is Newの中にはない 22/147
  13. MySQL 8.0 「メンテナンスリリース」 だと言い張る The MySQL 8.0.12 Maintenance Release is

    Generally Available | MySQL Server Blog ‐ The MySQL 8.0.13 Maintenance Release is Generally Available | MySQL Server Blog ‐ The MySQL 8.0.14 Maintenance Release is Generally Available | MySQL Server Blog ‐ The MySQL 8.0.16 Maintenance Release is Generally Available | MySQL Server Blog ‐ The MySQL 8.0.17 Maintenance Release is Generally Available | MySQL Server Blog ‐ 8.0.15はガチで8.0.14のリグレッションを1件だけ直した「メンテナンスリリース」だった。よって公式ブログに記事は無い() 24/147
  14. ぼくらが8.0に至ったみちのり(踏破) -reprise- ぼくらが8.0にいたるまでのみちのり(未到) Oracle MySQL Innovation Day 2018 秋 \-

    connpass ‐ ぼくらが8.0に至ったみちのり(踏破) Middlewares Deep Talks\-Tokyo\-20190523 ‐ 27/147
  15. インスタンスの特徴 2011年にMySQL 5.5でサービス開始 文字コードは (3バイト) UTF-8 ‐ 接続元アプリケーションはJava ‐ テーブルは

    ほぼ InnoDBストレージエンジン ‐ 2016年、MySQL 5.6バージョンアップ 2018年、アプリケーションのフルスクラッチリファクタリ ング(?)が決定 接続元アプリケーションはPHP(Laravel)に変更 ‐ MySQLも8.0にバージョンアップすることが決定 ‐ 30/147
  16. インスタンスの特徴 2011年にMySQL 5.5でサービス開始 文字コードは (3バイト) UTF-8 ‐ 接続元アプリケーションはJava ‐ テーブルは

    ほぼ InnoDBストレージエンジン ‐ 2016年、MySQL 5.6バージョンアップ 2018年、アプリケーションのフルスクラッチリファクタリ ング(?)が決定 接続元アプリケーションはPHP(Laravel)に変更 ‐ MySQLも8.0にバージョンアップすることが決定 ‐ 31/147
  17. インスタンスの特徴 2011年にMySQL 5.5でサービス開始 文字コードは (3バイト) UTF-8 ←救いだった ‐ 接続元アプリケーションはJava ‐

    テーブルは ほぼ InnoDBストレージエンジン ‐ 2016年、MySQL 5.6バージョンアップ 2018年、アプリケーションのフルスクラッチリファクタリ ング(?)が決定 接続元アプリケーションはPHP(Laravel)に変更 ‐ MySQLも8.0にバージョンアップすることが決定 ‐ 32/147
  18. インスタンスの特徴 2011年にMySQL 5.5でサービス開始 文字コードは (3バイト) UTF-8 ←救いだった ‐ 接続元アプリケーションはJava ‐

    テーブルは ほぼ InnoDBストレージエンジン ‐ 2016年、MySQL 5.6バージョンアップ 2018年、アプリケーションのフルスクラッチリファクタリ ング(?)が決定 接続元アプリケーションはPHP(Laravel)に変更 ‐ MySQLも8.0にバージョンアップすることが決定 ← 5.7どこ行っ た? ‐ 33/147
  19. インスタンスの特徴 2011年にMySQL 5.5でサービス開始 文字コードは (3バイト) UTF-8 ←救いだった ‐ 接続元アプリケーションはJava ‐

    テーブルは ほぼ InnoDBストレージエンジン ‐ 2016年、MySQL 5.6バージョンアップ 2018年、アプリケーションのフルスクラッチリファクタリ ング(?)が決定 接続元アプリケーションはPHP(Laravel)に変更 ‐ MySQLも8.0にバージョンアップすることが決定 ← 5.7どこ行っ た? データ作り直しだからいいんじゃね? ‐ 34/147
  20. 今までMySQLのバージョンアップでやられたこと? 4.0とそれ以前 ⇒ 4.1とそれ以降 timestamp型の変更、varchar型が文字コードをサポートしたことによる地 獄 5.5 ⇒ 5.6 datetime,

    time, timestamp型の内部の変更、InnoDBのパラメーター変 遷、ICPが積極的に選ばれて憤死、良かれと思って設定した explicit_defaults_for_timestamp が略、 mysql_old_password 認証プラグ インがデフォルトでOFFられててあぼん 5.6 ⇒ 5.7 Condition Fanout Filterが変に選ばれて略、sql_modeの暗黙のデフォルト を変え忘れて死 37/147
  21. 8.0へのレプリケーションがガンガン止まる あっ、ハイ、8.0でなくなるやつですよね NO_AUTO_CREATE_USER で5.7上でもエラーにできればいいのに…! ‐ Last_Errno: 1064 Last_Error: Error 'You

    have an error in your SQL syntax; check th e manual that corresponds to your MySQL server version for the ri ght syntax to use near 'IDENTIFIED WITH 'mysql_native_password' A S '*4266488C892EA7950486FEC0A1CFFC1BD95' at line 1' on query. Def ault database: ''. Query: 'GRANT USAGE ON *.* TO 'yoku0825'@'%' I DENTIFIED WITH 'mysql_native_password' AS '*4266488C892EA7950486F EC0A1CFFC1BD9543F7B'' 41/147
  22. 8.0へのレプリケーションがガンガン止まる あっ予約語だ! binlog_format= ROW にする? (これまでは MIXED ) ‐ 片っ端からオブジェクト名をバッククォートして回る?

    生SQLでなければこんな心配要らない予感 ‐ Last_SQL_Errno: 1064 Last_SQL_Error: Error 'You have an error in your SQL syntax; chec k the manual that corresponds to your MySQL server version for th e right syntax to use near 'rank) VALUES (4)' at line 1' on query . Default database: 'd1'. Query: 'INSERT INTO t1 (rank) VALUES (4 )' 42/147
  23. 8.0へのレプリケーションがガンガン止まる 止まるかな? と思って打ったら止まった。今は反省してい る。 FLUSH ステートメントの一部はバイナリーログに記録されるのです ‐ Last_SQL_Errno: 1064 Last_SQL_Error:

    Error 'You have an error in your SQL syntax; chec k the manual that corresponds to your MySQL server version for th e right syntax to use near 'QUERY CACHE' at line 1' on query. Def ault database: ''. Query: 'FLUSH QUERY CACHE' 43/147
  24. レプリケーションを止めがちな「削除された機能」 Using GRANT to create users ✓ Using GRANT to

    modify account properties other than privilege assignments ✓ IDENTIFIED BY PASSWORD ‘hash_string’ syntax ✓ The PASSWORD() function. ✓ MySQL :: MySQL 8.0 Reference Manual :: 1.4 What Is New in MySQL 8.0 46/147
  25. GRANT で直接ユーザーを作れなくなった 5.7からワーニングは出てたじゃろ? GRANT でパスワードを変えたり MAX_USER_CONNECTIONS を変えたりも できなくなった ‐ IDENTIFIED

    BY PASSWORD は IDENTIFIED WITH .. AS .. に変わる ‐ SET PASSWORD 構文はもうイコールの後ろに PASSWORD() 関数を噛ま せられない ‐ mysql> CREATE USER yoku0825@'%' IDENTIFIED BY 'plain_password'; mysql> GRANT DRINK beer.* TO yoku0825@'%'; mysql> ALTER USER yoku0825@'%' IDENTIFIED WITH mysql_native_passw ord AS '*hashed_password'; mysql> SET PASSWORD FOR yoku0825@'%' = 'plain_password'; 47/147
  26. インスタンスの特徴 2018年、アプリケーションのフルスクラッチリファクタリ ング(?)が決定 接続元アプリケーションはPHP(Laravel)に変更 ‐ MySQLも8.0にバージョンアップすることが決定 ← 5.7どこ行っ た? データ作り直しだからいいんじゃね?

    ‐ 2018年秋、既存のデータもアプリも捨てられないことが確 定 MySQL 5.6から8.0へのレプリケーションでのデータ移行 ‐ しかも2011年から継ぎ足され続けた秘伝のJavaがつなぎに来る ‐ 48/147
  27. 開発開始時 master(5.6) schema1 schema2 slave(5.6) schema1 schema2 slave(5.6) schema1 schema2

    slave(5.6) schema1 schema2 slave(8.0) schema1 schema2 schema3 57/147
  28. 上げて master(5.6) schema1 schema2 slave(5.7) schema1 schema2 slave(5.7) schema1 schema2

    slave(5.6) schema1 schema2 slave(8.0) schema1 schema2 schema3 59/147
  29. 上げて master(5.6) schema1 schema2 slave(5.7) schema1 schema2 slave(5.7) schema1 schema2

    slave(5.7) schema1 schema2 slave(8.0) schema1 schema2 schema3 60/147
  30. 開発が終わり master(5.6) schema1 schema2 slave(5.7) schema1 schema2 slave(5.7) schema1 schema2

    slave(5.7) schema1 schema2 slave(8.0) schema1 schema2 schema3 61/147
  31. カットーバー当日 master(5.6) schema1 schema2 slave(5.7) schema1 schema2 slave(5.7) schema1 schema2

    slave(5.7) schema1 schema2 slave(8.0) schema1 schema2 schema3 63/147
  32. ガシャッ master(5.7) schema1 schema2 slave(5.7) schema1 schema2 slave(5.7) schema1 schema2

    slave(5.7) schema1 schema2 slave(8.0) schema1 schema2 schema3 65/147
  33. SELECT .. FOR UPDATE SKIP LOCKED mysql80 28> SELECT *

    FROM t1 ORDER BY num LIMIT 1 FOR UPDATE; +-----+------+ | num | val | +-----+------+ | 1 | one | +-----+------+ 1 row in set (0.00 sec) mysql80 29> SELECT * FROM t1 ORDER BY num LIMIT 1 FOR UPDATE; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql80 29> SELECT * FROM t1 ORDER BY num LIMIT 1 FOR UPDATE SKIP LOCKED; +-----+------+ | num | val | +-----+------+ | 2 | two | +-----+------+ 1 row in set (0.00 sec) 76/147
  34. JSON_TABLE関数 SELECT DISTINCT tweet_id, LEFT(REPLACE(text, '\n', '\\n'), 16) AS text

    FROM t2, JSON_TABLE(t2.j, '$.statuses[*]' COLUMNS ( tweet_id NUMERIC(32) PATH '$.id', text VARCHAR(300) PATH '$.text' ) ) AS json; +---------------------+----------------------+ | tweet_id | text | +---------------------+----------------------+ | 1131026738492739584 | @ikaneko MySQLメイ | | 1131025041070497792 | LAMP環境\n\nLinux, | | 1131024962121281536 | RT @OracleDev_JP | | 1131026921276317697 | RT @sirius_gener | +---------------------+----------------------+ 4 rows in set (0.00 sec) 80/147
  35. Window関数 たくさんあるたまごパックの在庫から、賞味期限が古い方か ら順番に100個使う mysql80 51> SELECT * FROM t1 LIMIT

    3; +---------+------------+----------------+ | pack_id | egg_amount | expiration_day | +---------+------------+----------------+ | 1 | 4 | 2019-05-23 | | 2 | 1 | 2019-05-25 | | 3 | 4 | 2019-05-25 | +---------+------------+----------------+ 3 rows in set (0.00 sec) 84/147
  36. Window関数 たくさんあるたまごパックの在庫から、賞味期限が古い方か ら順番に100個使う mysql80 51> SELECT pack_id, egg_amount, expiration_day, SUM(egg_a

    mount) OVER (ORDER BY expiration_day, pack_id) AS egg_total FROM t1 LIMIT 3; +---------+------------+----------------+-----------+ | pack_id | egg_amount | expiration_day | egg_total | +---------+------------+----------------+-----------+ | 1 | 4 | 2019-05-23 | 4 | | 27 | 2 | 2019-05-23 | 6 | | 33 | 4 | 2019-05-23 | 10 | +---------+------------+----------------+-----------+ 3 rows in set (0.01 sec) 85/147
  37. Window関数 たくさんあるたまごパックの在庫から、賞味期限が古い方か ら順番に100個使う mysql80 51> WITH list AS (SELECT pack_id,

    egg_amount, expiration_day, SUM(egg_amoun t) OVER (ORDER BY expiration_day, pack_id) AS egg_total FROM t1), -> last_one AS (SELECT * FROM list WHERE egg_total >= 100 ORDER BY eg g_total LIMIT 1) -> SELECT * FROM list WHERE egg_total < 100 -> UNION ALL -> SELECT * FROM last_one; +---------+------------+----------------+-----------+ | pack_id | egg_amount | expiration_day | egg_total | +---------+------------+----------------+-----------+ | 1 | 4 | 2019-05-23 | 4 | | 27 | 2 | 2019-05-23 | 6 | | 33 | 4 | 2019-05-23 | 10 | .. | 489 | 3 | 2019-05-23 | 96 | | 491 | 5 | 2019-05-23 | 101 | +---------+------------+----------------+-----------+ 41 rows in set (0.04 sec) 86/147
  38. CTE(WITH句) FROM句にいっぱい書き連ねるようなクエリーを WITH で先 頭にくくりだせる SELECT MAX(txt), MIN(txt) FROM (

    SELECT concat(cte2.txt, cte3.txt) as txt FROM ( SELECT CONCAT(cte1.txt,'is a ') as txt FROM ( SELECT 'This ' as txt ) as cte1 ) as cte2, ( SELECT 'nice query' as txt UNION SELECT 'query that rocks' UNION SELECT 'query' ) as cte3 ) as cte4; 90/147
  39. CTE(WITH句) FROM句にいっぱい書き連ねるようなクエリーを WITH で先 頭にくくりだせる WITH cte1(txt) AS (SELECT "This

    "), cte2(txt) AS (SELECT CONCAT(cte1.txt,"is a ") FROM cte1), cte3(txt) AS (SELECT "nice query" UNION SELECT "query that rocks" UNION SELECT "query"), cte4(txt) AS (SELECT concat(cte2.txt, cte3.txt) FROM cte2, cte3) SELECT MAX(txt), MIN(txt) FROM cte4; 91/147
  40. 式インデックス 事前に計算できる(= NOW() とかはダメ)値に対して式を通し た値をインデックスにできる 5.7ではgenerated columnを作ってそれにインデックスを足してい たが、カラムなしでインデックスだけドスンと作れる ‐ mysql>

    ALTER TABLE t1 ADD KEY idx_exp ((age > 20)); mysql> EXPLAIN SELECT .. FROM t1 WHERE age > 20; +----+-------------+-------+------------+------+---------------+------+---------+------+-------+---- ------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | fil tered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+-------+---- ------+-------------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 10195 | 33.33 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+-------+---- ------+-------------+ 1 row in set, 1 warning (0.00 sec) 95/147
  41. 式インデックス…? mysql> EXPLAIN SELECT .. FROM t1 WHERE age >

    20; +----+-------------+-------+------------+------+---------------+- -----+---------+------+-------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+- -----+---------+------+-------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 10195 | 33.33 | Using where | +----+-------------+-------+------------+------+---------------+- -----+---------+------+-------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) 97/147
  42. MySQL 8.0に期待していたこと SELECT .. FOR UPDATE SKIP LOCKED JSON_TABLE 関数

    Window関数 CTE(WITH句) 式インデックス 100/147
  43. 新しいデータディクショナリー 全てのテーブルへのアクセスのベースになるので、 「新機 能 使わなければ 大丈夫」 といった五七五が効かない 何かあった時に回避が難しい ‐ ド新規で作ったテーブルはちゃんとテストされているだろう

    けど、特にMySQL 5.7未満からアップグレードを重ねてき たMySQLには㌧でもないテーブル定義が埋まっていたりす る 何故かテーブルコメントがSJISで書かれたテーブル ‐ lower_case_table_names= 1と相性が悪い… ‐ 103/147
  44. SQLパーザーのリファクタリング 地味に(?)リファクタしたらしい MySQL 8.0: Refactoring and Improving the Parser |

    MySQL Server Blog ‐ それはそれで良いんだけど、これも全アクセスの礎になって 回避しようがない部分… Window関数やCTEの追加でごりっと手を入れるからついで に(?)リファクタなのかなあ 5.7の時もパーザーのリファクタはやりたいって言ってたしなあ ‐ 108/147
  45. SET PERSIST SET GLOBAL は現在の設定値を更新するだけで mysqld を再起 動すると揮発する 永続化させたければ自分で my.cnf

    を更新しないといけない ‐ SET PERSIST は現在の設定値を更新した上で $datadir/ mysqld-auto.cnf に変更内容を記録する SQLインターフェイスだけで設定の永続化までやってくれる ‐ 112/147
  46. SET PERSIST /etc/my.cnf と $datadir/mysqld-auto.cnf に同じパラメー ターに対する設定があった場合、優先されるのはどっち? my.cnf 系が読み込まれた後に mysqld-auto.cnf

    が読まれる ‐ MySQLのパラメーター設定は 後勝ち ‐ つまり mysqld-auto.cnf の方が強い ‐ 「my.cnf編集して再起動したんですけど、 max_connections増えてない…」「それ、mysqld- auto.cnfから読んでるんじゃ?」みたいなことはありそう 113/147
  47. SET PERSIST MySQL開発チームの中の人とかは、「my.cnfを編集できな い、SQLインターフェイスしかないマネージドなMySQLで も設定変更を可能に」的なことを言っていたけど そもそも SET GLOBAL や SET

    PERSIST に必要なSuper権限を認めてい ないマネージドMySQLとか ‐ 提供している側からすれば「どっちが優先されるの問題」でエンド ユーザーに混乱を招く原因になりかねないとか ‐ 稼働中にいきなり着火する系ではないのが救い 114/147
  48. utf8mb4_0900_ai_ci character_set_server のデフォルトが latin1 から utf8mb4 に こっちはそのまま使ってる日本人は少ないと思うので別にいいと思う けど ‐

    character_set_server= utf8mb4 の時のデフォルトの照合順 序が変更になった utf8mb4_general_ci から utf8mb4_0900_ai_ci に ‐ 117/147
  49. utf8mb4_0900_ai_ci collation mysql = MySQL ハハ != パパ びょういん !

    = びようい ん != MySQL = M ySQL = != ≠ utf8mb4 _genera l_ci o o o x x o utf8mb4 _0900_ ai_ci o x x o o x utf8mb4 _ja_090 0_as_cs x o o o o o utf8mb4 _bin x o o o x o 118/147
  50. utf8mb4_0900_ai_ci kamipoのハハ=パパ問題 ActiveRecordでデフォルトの照合順序を変更する \- Qiita ‐ びょういん=びよういん問題 MySQL Bugs: #79977:

    utf8mb4_unicode_520_ci don’t make sense for Japanese FTS ‐ イコールイコールノットイコール問題 MySQL Bugs: #92899: Incorrect uniqueness determination with equality symbols ‐ 問題 https://twitter.com/tmtms/status/546925668424896512 ‐ MySQL Bugs: #76553: Sushi\-Beer issue of MySQL with utf8mb4 ‐ 119/147
  51. utf8mb4_0900_ai_ci 問題になりそうな場合は collation_server の変更を忘れず に 個人的には utf8mb4_bin, メールアドレスとかで大文字小文字を握り つぶしたいなら utf8mb4_general_ci

    かなぁ… ‐ これはMySQL 8.0の最初期から言ってきたことなので、み んな既に知っていることだといいな… 120/147
  52. Instant ADD COLUMN MySQL 5.6とそれ以降の「オンラインALTER TABLE」とは 違うもの オンラインで(= テーブルへの書き込みを許容しながら)実行できる 点は一緒

    ‐ 「既存の行の再構築を行わずにメタデータの調整だけでカラ ムを追加する」という超絶技術 128/147
  53. Instant ADD COLUMN 100万行, 100MBくらいのテーブルに対して mysql80 20> ALTER TABLE t1

    ADD c1 int, ALGORITHM= INSTANT; Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql80 20> ALTER TABLE t1 ADD c2 int, ALGORITHM= INPLACE; Query OK, 0 rows affected (3.43 sec) Records: 0 Duplicates: 0 Warnings: 0 129/147
  54. INSTANT ADD COLUMN ALGORITHM = INSTANT ----system---- ----total-cpu-usage---- -dsk/total- ---system--

    ------mem ory-usage----- --io/total- | time | usr sys idl wai hiq siq | read writ | int csw | used buff cach free | read writ | | 20-11 16:44:56 | 2 1 97 1 0 0 | 0 6409k | 877 996 | 692M 0 172M 127M | 0 222 | | 20-11 16:44:57 | 3 1 96 0 0 0 | 128k 394k | 1545 2509 | 692M 0 172M 127M | 8.00 63.0 | | 20-11 16:44:58 | 2 0 98 0 0 0 | 0 6410k | 901 982 | 692M 0 172M 127M | 0 225 | | 20-11 16:44:59 | 2 1 97 1 0 0 | 3260k 972k | 908 927 | 692M 0 175M 124M | 54.0 41.0 | | 20-11 16:45:00 | 2 0 98 0 0 0 | 0 0 | 641 772 | 692M 0 175M 124M | 0 0 | 17338 buffer_pages_written 2018-11-20 16:44:56 17347 buffer_pages_written 2018-11-20 16:44:57 17547 buffer_pages_written 2018-11-20 16:44:58 17577 buffer_pages_written 2018-11-20 16:44:59 17577 buffer_pages_written 2018-11-20 16:45:00 130/147
  55. INSTANT ADD COLUMN ALGORITHM = INPLACE ----system---- ----total-cpu-usage---- -dsk/total- ---system--

    ------memory-usage----- --io/total- | time | usr sys idl wai hiq siq | read writ | int csw | used buff ca ch free | read writ | | 20-11 16:45:00 | 2 0 98 0 0 0 | 0 0 | 641 772 | 692M 0 17 5M 124M | 0 0 | | 20-11 16:45:01 | 35 5 49 10 0 0 | 14M 78M | 14k 34k | 692M 0 17 5M 124M | 897 2150 | | 20-11 16:45:02 | 13 5 49 32 0 0 | 37M 51M | 9577 16k | 701M 0 20 5M 85.1M | 1213 3318 | | 20-11 16:45:03 | 19 8 49 23 0 0 | 14M 51M | 12k 18k | 693M 0 20 6M 91.7M | 245 5287 | | 20-11 16:45:04 | 3 2 85 10 0 0 | 6028k 31M | 6985 13k | 693M 0 21 1M 87.7M | 142 3098 | | 20-11 16:45:05 | 2 0 98 0 0 0 | 0 419k | 681 817 | 693M 0 21 1M 87.7M | 0 20.0 | 17577 buffer_pages_written 2018-11-20 16:45:00 18047 buffer_pages_written 2018-11-20 16:45:01 19139 buffer_pages_written 2018-11-20 16:45:02 21147 buffer_pages_written 2018-11-20 16:45:03 21591 buffer_pages_written 2018-11-20 16:45:04 21604 buffer_pages_written 2018-11-20 16:45:05 131/147
  56. INSTANT ADD COLUMN どういう黒魔術使ってるんだってくらい速い MySQL 8.0: InnoDB now supports Instant

    ADD COLUMN | MySQL Server Blog ‐ Tencent Gamesがパッチを寄贈したらしい ぼく「さすが自分たちで使い倒している企業は俺たちが欲しいものをよくわかって いる」 ‐ バッファプールも全然触らなくてすごい 楽しくて笑えてくるレベル ‐ ENUM型の定義変更も ALGORITHM = INSTANT でできるらしい ですよ!!!1 132/147
  57. ROLE IPアドレス単位でアカウント作ってる人にはわかってもらえ るかしらん MySQL側ではホスト部を指定せずに、セキュリティーグループとか で接続元を絞ってる場合はそんなに嬉しくないと思う ‐ mysql> CREATE USER apuser@apserver1;

    mysql> GRANT ALL ON ap_db.* TO apuser@apserver1; mysql> CREATE USER apuser@apserver2; mysql> GRANT ALL ON ap_db.* TO apuser@apserver2; mysql> CREATE USER apuser@apserver3; mysql> GRANT ALL ON ap_db.* TO apuser@apserver3; .. 135/147
  58. ROLE 「すいません、新機能はサーバーもわけることになりまし た。既存のアカウントは今まで通りap_dbだけ、新サーバー 用のアカウントはap_dbの読み取りとnew_dbの読み書き権 限を」 ( ゚д゚) えっえっ mysql> REVOKE

    ALL ON new_db.* FROM apuser@apserver1; mysql> REVOKE ALL ON new_db.* FROM apuser@apserver2; mysql> REVOKE ALL ON new_db.* FROM apuser@apserver3; .. mysql> CREATE USER apuser@apserver11; mysql> GRANT ALL ON new_db.* TO apuser@apserver11; mysql> GRANT SELECT ON ap_db.* TO apuser@apserver11; .. 137/147
  59. ROLE mysql> CREATE ROLE ap_rw; mysql> GRANT ALL ON ap_db.*

    TO ap_rw; mysql> CREATE USER apuser@apserver1 DEFAULT ROLE ap_rw; mysql> CREATE USER apuser@apserver2 DEFAULT ROLE ap_rw; mysql> CREATE USER apuser@apserver3 DEFAULT ROLE ap_rw; .. 139/147
  60. ROLE mysql> GRANT ALL ON new_db.* TO ap_rw; mysql> REVOKE

    ALL ON new_db.* FROM ap_rw; mysql> CREATE ROLE ap_ro; mysql> GRANT SELECT ON ap_db.* TO ap_ro; mysql> CREATE ROLE new_rw; mysql> GRANT ALL ON new_db.* TO new_rw; mysql> GRANT ap_ro TO new_rw; mysql> CREATE USER apuser@apserver11 DEFAULT ROLE new_rw; .. 140/147