MySQL 8.0.19 new features roundup!
この記事では、2020/01/18時点の最新リリースである8.0.19で実装された新機能の一部についてご紹介します。
8.0.19新機能の完全なリストは以下をご確認ください。
Changes in MySQL 8.0.19 (2020-01-13, General Availability)
また、弊社では OSSニュースにMySQLを主とした各製品のリリースノートの翻訳記事を投稿しています。
こちらでより網羅的な内容を確認することができますので、ぜひご確認ください!
これまでの記事は以下をご参照ください。
過去の記事
MySQL 8.0.18 new features roundup!
ユーザアカウントへのログイン失敗許容回数の設定
これまでにも明示的にアカウントをロックすることはできましたが、ログイン失敗回数を条件にロックすることが可能となりました。
Failed-Login Tracking and Temporary Account Locking
CREATE/ALTER USER文に以下の2つの構文を使用します。
構文 | 説明 |
---|---|
FAILED_LOGIN_ATTEMPTS N | ログイン失敗回数の上限。この数を超えてログインに失敗した場合、一定期間アカウントはロックされる |
PASSWORD_LOCK_TIME {N or UNBOUNDED} | FAILED_LOGIN_ATTEMPTS に達したアカウントをロックする期間。Nは日数です。UNBOUNDEDは明示的にロックを解除するまでロックされることを意味します。 |
1 2 |
mysql> create user u1 identified by 'mypass' failed_login_attempts 2 password_lock_time 1; Query OK, 0 rows affected (0.02 sec) |
現在のところPASSWORD_LOCK_TIMEには整数しか指定できないようで、最低1日はロックされるようです。
1 2 |
mysql> create user u1 identified by 'mypass' failed_login_attempts 2 password_lock_time 0.003; ERROR 1064 (42000): Only integers allowed as number here near '0.003' at line 1 |
実際にログインに失敗してみるとこのようになります。
1日はログインできない状態となりました。
1 2 3 4 5 6 |
$ mysql -uu1 -pblahblah ERROR 1045 (28000): Access denied for user 'u1'@'localhost' (using password: YES) $ mysql -uu1 -pblahblah ERROR 3955 (HY000): Access denied for user 'u1'@'localhost'. Account is blocked for 1 day(s) (1 day(s) remaining) due to 2 consecutive failed logins. $ mysql -uu1 -pmypass ERROR 3955 (HY000): Access denied for user 'u1'@'localhost'. Account is blocked for 1 day(s) (1 day(s) remaining) due to 2 consecutive failed logins. |
しかしながら、mysql.userのaccount_lockedがYになっていませんでした。
そのため確認には実際にログインをしてみることが必要かもしれません。
1 2 3 4 5 6 |
mysql> select user, account_locked from mysql.user where user='u1'; +------+----------------+----------------------------------------------------------------------------------+ | user | account_locked | user_attributes | +------+----------------+----------------------------------------------------------------------------------+ | u1 | N | {"Password_locking": {"failed_login_attempts": 2, "password_lock_time_days": 1}} | +------+----------------+----------------------------------------------------------------------------------+ |
ロックに失敗した回数や、ロックされる日数等はACL_USERクラスの変数に持っているようです。
興味がありましたらWLもご確認ください
なお、ロック回数は以下の条件でクリアされます。
- サーバの再起動
- FLUSH PRIVILEGESの実行
- FAILED_LOGIN_ATTEMPTSに達する前にログインに成功
- ロック期間の経過
- ALTER USER ACCOUNT UNLOCKの実行
- ALTER USERによるユーザ属性の再設定
この設定を管理用のユーザ等に設定することでよりセキュアな運用ができそうです。
システム関連スキーマ内のInnoDBテーブルについてのステータス変数の追加
システムスキーマ(mysql)内のInnoDBテーブルへの操作をトラッキングするステータス変数が追加されました。
- Innodb_system_rows_read
- Innodb_system_rows_inserted
- Innodb_system_rows_deleted
既存のステータス変数(Innodb_rows_xxx)はシステムスキーマ、ユーザスキーマの操作は区別されていなかったため、頻繁にシステムスキーマのテーブルにアクセスされる環境では解析が難しくなる状況がありました。
特にレプリケーション環境においてrelay_log_info_repository/master_info_repository をTABLEに設定している場合に、利用されるslave_master_info/slave_replay_log_info/slave_worker_infoはmysqlスキーマに属しており、比較的頻繁にR/Wが行なわれるということがありました。
上記の変数を実装したことでInnodb_rows_xxxステータス変数にはユーザスキーマのInnoDBに対するオペレーションのみがカウントされるようになりました。
1 2 3 4 5 6 7 |
$ mysql -e "show status like 'innodb_%rows_inserted'" +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | Innodb_rows_inserted | 19 | | Innodb_system_rows_inserted | 503 | +-----------------------------+-------+ |
test.t1
はユーザスキーマですのでInnodb_rows_insertedに加算されます。
1 2 3 4 5 6 7 8 9 |
mysql> insert into test.t1 values (null); Query OK, 1 row affected (0.02 sec) mysql> show status like 'innodb_%rows_inserted'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | Innodb_rows_inserted | 20 | | Innodb_system_rows_inserted | 503 | +-----------------------------+-------+ |
システムスキーマへの更新を行うとInnodb_system_rows_inserted
が加算されます。
例としてテーブルを追加します。
テーブルを追加するとシステムスキーマ内の各テーブルへのR/Wが行われます。
1 2 3 4 5 6 7 8 9 |
mysql> create table t1( i int primary key auto_increment) engine innodb; Query OK, 1 row affected (0.02 sec) mysql> show status like 'innodb_%rows_inserted'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | Innodb_rows_inserted | 20 | | Innodb_system_rows_inserted | 515 | +-----------------------------+-------+ |
ロール関連情報の強化
INFORMATION_SCHEMAにいくつかのロールに関する情報を提供するテーブルが追加されました。
テーブル名 | 説明 |
---|---|
ADMINISTRABLE_ROLE_AUTHORIZATIONS | 他のユーザに適用可能であるかの情報を持つ現在のユーザが適用できるロールの一覧 |
APPLICABLE_ROLES | 現在のユーザに適用可能なロールの一覧 |
ENABLED_ROLES | 現在の接続で有効なロールの一覧 |
ROLE_COLUMN_GRANTS | 現在のユーザに適用されているロールがアクセス可能な列の一覧 |
ROLE_ROUTINE_GRANTS | 現在のユーザに適用されているロールがアクセス可能なルーチンの一覧 |
ROLE_TABLE_GRANTS | 現在のユーザに適用されているロールがアクセス可能なテーブルの一覧 |
今までは SHOW GRANTS FOR 'rolename'
を実行して権限を確認する必要がありましたので、より管理上の利便性が高まったのではないでしょうか。
1 2 3 4 5 6 7 |
mysql> SHOW GRANTS for 'myrole'; +------------------------------------------+ | Grants for myrole@% | +------------------------------------------+ | GRANT USAGE ON *.* TO <code>myrole</code>@<code>%</code> | | GRANT SELECT ON <code>test</code>.* TO <code>myrole</code>@<code>%</code> | +------------------------------------------+ |
ログローテーションがログイン不要に
8.0.19からは、SIGUSR1
シグナルをmysqldに実行することで、ログイン不要でログのフラッシュが可能となりました。
対象のログは、エラーログ、一般ログ、スロークエリログです。
そのためmysqlクライアントを使用する必要がなくなります。
これは地味に嬉しい機能です。
なお、これまでも SIGHUP
でフラッシュすることはできましたが、フラッシュ対象が広く運用中の実行は望ましくないものでした。
例として、これまでの/etc/logrotate.d/mysql
は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/var/log/mysql/error.log { create 644 mysql mysql : postrotate # just if mysqld is really running if test -x /usr/bin/mysqladmin && \ /usr/bin/mysqladmin ping -S/var/lib/mysql/mysql.sock &>/dev/null then /usr/bin/mysqladmin -urotate_user -protate_pass flush-logs fi endscript } |
8.0.19からは以下のようにすることが可能です。
1 2 3 4 5 6 7 8 9 |
/var/log/mysql/error.log { create 644 mysql mysql : postrotate [ -r /tmp/mysql.pid ] && kill -USR1 $(cat /tmp/mysql.pid) fi endscript } |
TABLE, VALUE ステートメントが実装
SQL標準に従いTABLE, VALUE ステートメントが実装されました。
TABLE句はSELECTから射影の部分を抜いたようなSQLで、例えば以下のSQLはいずれも同じ結果を返します。
- TABLE t ORDER BY c LIMIT 10 OFFSET 3;
- SELECT * FROM t ORDER BY c LIMIT 10 OFFSET 3;
実行例は以下です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
mysql> TABLE t ORDER BY i LIMIT 10 OFFSET 3; +----+ | i | +----+ | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | | 10 | | 11 | | 12 | | 13 | +----+ |
SELECTと同じように、他のSQLと組み合わせて使用する事も可能です。
1 |
mysql> CREATE TABLE t2 AS TABLE t ORDER BY i LIMIT 10 OFFSET 3; |
VALUES..ROW句は、INSERT等の値に複数レコードを指定する場合などに使用する句です。
1 2 3 4 5 6 7 8 9 |
mysql> INSERT INTO test.t VALUES ROW(1), ROW(2), ROW(3); mysql> SELECT * FROM test.t; +---+ | i | +---+ | 1 | | 2 | | 3 | +---+ |
また、VALUES..ROW句を使用して擬似的なテーブルを表現する事も可能です。
1 2 3 4 5 6 7 |
mysql> SELECT a,b FROM (VALUES ROW(1,2,3), ROW(4,5,6)) AS t(A,B,C); +---+---+ | a | b | +---+---+ | 1 | 2 | | 4 | 5 | +---+---+ |
その他の重要な新機能
- Windowsのmysqlクライアントでsystemコマンドが実行可能になりました。
- JSON_SCHEMA_VALID()でエラー詳細が提供されるようになりました
- Group Replication接続は、max_connectionsが考慮する接続から除外されました
- 以前のDuplicate entryエラーにはキー名と値のみが表示されていましたが、テーブル名が含まれるようになりました
- マルチスレッドスレーブ(slave_parallel_workers)の設定を行う際に、以前はスレーブ側でのlog_bin, log_slave_updatesの有効化が必要でしたが、これが不要となりました。これによりスレーブでバイナリログを出力する必要がなくなりました。
- レプリケーションチャネルの設定にREQUIRE_ROW_FORMAT(行形式のバイナリログのみを受け入れる)が追加されました。
- InnoDBテーブルの独自のサンプリング実装が行われました。これにより統計情報がより効率的に更新されるようになりました。
番外
MySQL Shell 8.0.19では、従来のレプリケーション環境をReplica Setとしてデプロイ、管理する機能が追加されています。
https://dev.mysql.com/doc/refman/8.0/en/mysql-innodb-replicasets-introduction.html
非常に興味深い機能ですので、いつか別の機会でご紹介できればと思います。
まとめ
今回ご紹介させて頂いた機能以外にも数多くの改善が行われています。
興味がありましたら、ぜひリリースノートを確認してみてください。
MySQL 8.0の進化はめざましく、今後も要チェックです!