デモの準備をしていて、MySQL5.7で動いていたページが以下のようにエラーになったので、今後の為にメモ。既にマニュアルやブログで確認してはいて、情報としては認識していたのですがMySQL8.0.4以降の変更点なので忘れてました。

■ 認証プラグインの変更について
MySQL 8.0では、mysql_native_passwordではなくcaching_sha2_passwordがデフォルトの認証プラグインです。
https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html

■ 変更理由はセキュリティ強化とパフォーマンス
caching_sha2_passwordおよびsha256_password認証プラグインは、mysql_native_passwordプラグインよりも安全なパスワード暗号化を提供し、caching_sha2_passwordはsha256_passwordよりも優れたパフォーマンスを提供します。
caching_sha2_passwordのこれらの優れたセキュリティとパフォーマンスの特性のため、これはMySQL 8.0.4以降の認証プラグインであり、mysql_native_passwordではなくデフォルトの認証プラグインでもあります。
https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password

現状では、コネクターが対応していない為、アカウント認証をMySQL8.0.4以前の認証方法に戻します。


[root@GA02 mysql]# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.4-rc-log MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select @@version;
+--------------+
| @@version    |
+--------------+
| 8.0.4-rc-log |
+--------------+
1 row in set (0.00 sec)

mysql> 


root@localhost [mysql]> SELECT user, host, plugin FROM user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| admin            | %         | caching_sha2_password |
| mysql.infoschema | localhost | mysql_native_password |
| mysql.session    | localhost | mysql_native_password |
| mysql.sys        | localhost | mysql_native_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)

root@localhost [mysql]> alter user 'admin'@'%' identified WITH mysql_native_password by 'password';
Query OK, 0 rows affected (0.00 sec)

root@localhost [mysql]> SELECT user, host, plugin FROM user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| admin            | %         | mysql_native_password |
| mysql.infoschema | localhost | mysql_native_password |
| mysql.session    | localhost | mysql_native_password |
| mysql.sys        | localhost | mysql_native_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)

root@localhost [mysql]> 

mysql_native_password認証に戻し、ページが問題無く表示される事を確認

caching_sha2_password互換のクライアントおよびコネクタ
caching_sha2_passwordについて知るように更新されたクライアントまたはコネクターが使用可能な場合は、それを使用すると、MySQL 8.0サーバに接続する際に互換性を保証する最良の方法です、それらはデフォルトの認証プラグインとしてcaching_sha2_passwordを使用して構成されています。これらのクライアントとコネクタは、caching_sha2_passwordをサポートするようにアップグレードされました:

MySQL 8.0.4以降のlibmysqlclientクライアントライブラリ。
mysqlやmysqladminなどの標準的なMySQLクライアントはlibmysqlclientベースである為、互換性があります。

MySQL Connector/J 8.0.9 or higher.
MySQL Connector/Net 8.0.10 or higher (through the classic MySQL protocol).
MySQL Connector/Node.js 8.0.9 or higher.

注意:2018年2月現在、caching_sha2_password互換クライアントはGAになってない為、
   MySQL8.0がGAになるまでしばらく進捗を確認する必要があります。

MySQL8.0.4以前に作成されたアカウントをcaching_sha2_passwordに切り替える必要がある場合
ユーザーはALTER USERステートメントを使用して変更できます。


ALTER USER user IDENTIFIED WITH caching_sha2_password BY 'password';

重要
MySQL 8.0.4より前のバージョンのクライアントに対応する必要があり、MySQL 8.0.4以降にアップグレードした後で互換性の問題が発生した場合、これらの問題に対処して8.0以前の互換性を復元する最も簡単な方法は、サーバを再設定しプラグイン(mysql_native_password)を利用します。
必要に応じて、オプションファイルに次の行を設定してください。


[mysqld]
default_authentication_plugin=mysql_native_password

MySQL8.0をアプリケーションで利用される場合はこちらを確認ください。
https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password


先日, MySQL Enterprise Auditの機能追加に関して確認したので、大きな変更は無いですが、Enterprise Firewallも再度機能確認してみました。データベースFirewallなので、XSSは防ぐ事は出来ませんが、SQL Injectionは防ぐ事が出来るのでEnterprise AuditとEnterprise Firewallの組み合わせで、重要な情報を扱うデータベースに追加する事で、セキュリティを更に強固にすることが可能です。

【利用例】

1) Webで公開しているアカウントにFirewallを設定して,外部からの入力フィルターをアプリケーションのフレームワークのEscape処理のみに依存しない。


2) 社内で利用しているアカウントにWHERE句を利用しない参照処理をさせないように制限する。(補足:MySQLでは列レベルの権限設定は可能)


3) IDSの代わりにFirewallを検知モードにしておいて、不正アクセスを検知したらEnterprise Monitorと連携してセキュリティ担当者にメールやSNMPで知らせる。

オフィシャルマニュアル
6.5.6 MySQL Enterprise Firewall

3年前のブログポスト
http://variable.jp/2015/04/13/mysql-enterprise-firewall/

Enterprise Firewallのデモ
1) Firewall OFFの状態 → 2) Firewall ONに設定

サイバーセキュリティ経営ガイドライン@経済産業省“に「指示5サイバーセキュリティリスクに対応するための仕組みの構築」に、新たに「攻撃の検知」を含めたリスク対応体制についての記載”が改定されていました。

MySQL Enterprise Firewallでブロックされる事が懸念としてある場合は、検知モードで設定する事も可能ですので検知する仕組みとして利用してみては如何でしょうか?


MySQL5.7.21からMySQL Enterprise Auditの機能が拡張されています。
主な変更点は、以下の4つになります。

1) 監査ログの圧縮
2) 監査ログの暗号化
3) JSONフォーマットの追加
4) audit_log_read関数による監査ログの確認

まだ、監査を実施してなくて、個人情報、機密情報、売上利益に関わるデータに監査が必用な場合は、MySQLのオプション機能として利用するを検討しても良いかもしれません。

MEMO: MySQL5.7.21から監査設定用のインストールスクリプトもMyISAMからInnoDBに変更されています。

[root@GA01 data]# cat /usr/local/mysql/share/audit_log_filter_linux_install.sql | grep engine
CREATE TABLE IF NOT EXISTS audit_log_filter(NAME VARCHAR(64) BINARY NOT NULL PRIMARY KEY, FILTER JSON NOT NULL) engine= InnoDB;
CREATE TABLE IF NOT EXISTS audit_log_user(USER VARCHAR(16) BINARY NOT NULL, HOST VARCHAR(60) BINARY NOT NULL, FILTERNAME VARCHAR(64) BINARY NOT NULL, PRIMARY KEY (USER, HOST), FOREIGN KEY (FILTERNAME) REFERENCES mysql.audit_log_filter(NAME)) engine= InnoDB;
[root@GA01 data]# 

※ MySQL Enterprise FirewallのスクリプトもEngineがInnoDBに変更されていました。

5.7.13~5.7.20でEnterprise Auditを利用されている方は、監査定義で利用するテーブルを以下のようにマニュアルでInnoDBに変更する事を推奨となっています。

ALTER TABLE mysql.audit_log_user ENGINE=InnoDB;
ALTER TABLE mysql.audit_log_filter ENGINE=InnoDB;

■ ログフィルター設定(ファイングレインオプション)
ユーザー、テーブル、クエリータイプ(SELECT, INSERT, UPDATE, DELETE等)

root@localhost [mysql]> select * from audit_log_user;
+---------+-----------+------------------+
| USER    | HOST      | FILTERNAME       |
+---------+-----------+------------------+
| admin   | %         | log_confidential |
| admin   | localhost | log_confidential |
| fw_user | localhost | log_confidential |
+---------+-----------+------------------+
3 rows in set (0.00 sec)

root@localhost [mysql]> select * from audit_log_filter;
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| NAME             | FILTER                                                                                                                                         |
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| log_confidential | {"filter": {"class": {"name": "table_access", "event": {"log": {"field": {"name": "table_name.str", "value": "card_info"}}, "name": "read"}}}} |
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

root@localhost [mysql]> 

■ MySQL Enterprise Auditのファンクションを利用してJSONのログを読み取る。

audit_log_read_bookmark()
最後に書き込まれた監査ログイベントのブックマークを表すJSON文字列を返します。
このブックマークはaudit_log_read()に渡して、読み込みを開始する場所を指定するのに適しています。

audit_log_read()
監査ログからイベントを読み取り、監査イベントの配列を含むJSON文字列を返します。

■ Audit用ファンクションのインストール


root@localhost [OU]> CREATE FUNCTION audit_log_read_bookmark RETURNS STRING SONAME 'audit_log.so';
Query OK, 0 rows affected (0.00 sec)

root@localhost [OU]> CREATE FUNCTION audit_log_read RETURNS STRING SONAME 'audit_log.so';
Query OK, 0 rows affected (0.00 sec)

/*** Edit my.cnf for adding audit_log_format=JSON ***/

root@localhost [(none)]> SELECT @@global.audit_log_format;
+---------------------------+
| @@global.audit_log_format |
+---------------------------+
| JSON                      |
+---------------------------+
1 row in set (0.00 sec)

root@localhost [(none)]> SELECT * FROM mysql.func WHERE name IN ('audit_log_read_bookmark', 'audit_log_read');
+-------------------------+-----+--------------+----------+
| name                    | ret | dl           | type     |
+-------------------------+-----+--------------+----------+
| audit_log_read          |   0 | audit_log.so | function |
| audit_log_read_bookmark |   0 | audit_log.so | function |
+-------------------------+-----+--------------+----------+
2 rows in set (0.00 sec)

■ 直近のAuditログを読み込む場合

root@localhost [(mysql)]> SET @bookmark = (SELECT audit_log_read_bookmark());
Query OK, 0 rows affected (0.00 sec)

root@localhost [(none)]> select @bookmark;
+-------------------------------------------------+
| @bookmark                                       |
+-------------------------------------------------+
| { "timestamp": "2018-02-13 06:47:23", "id": 0 } |
+-------------------------------------------------+
1 row in set (0.00 sec)

root@localhost [(mysql)]> SELECT audit_log_read(@bookmark)\G
*************************** 1. row ***************************
audit_log_read(@bookmark): [ {"timestamp":"2018-02-13 06:47:23","id":0,"class":"table_access","event":"read","connection_id":14,"account":{"user":"fw_user","host":"localhost"},"login":{"user":"fw_user","os":"","ip":"127.0.0.1","proxy":""},"table_access_data":{"db":"test","table":"card_info","query":"select id, fname,lname,cnumber from card_info where id = 5","sql_command":"select"}}, null ]
1 row in set (0.01 sec)

■ 特定のポイント以降のログを読み込む場合

root@localhost [(mysql)]> set @bookmark2 = JSON_OBJECT('timestamp','2018-02-13 06:33:33','id',0);
Query OK, 0 rows affected (0.01 sec)

root@localhost [(mysql)]> SELECT audit_log_read(@bookmark2)\G
*************************** 1. row ***************************
audit_log_read(@bookmark2): [ {"timestamp":"2018-02-13 06:33:33","id":0,"class":"table_access","event":"read","connection_id":8,"account":{"user":"fw_user","host":"localhost"},"login":{"user":"fw_user","os":"","ip":"127.0.0.1","proxy":""},"table_access_data":{"db":"test","table":"card_info","query":"select id, fname,lname,cnumber from card_info where id = 5","sql_command":"select"}}, {"timestamp":"2018-02-13 06:47:09","id":0,"class":"table_access","event":"read","connection_id":9,"account":{"user":"fw_user","host":"localhost"},"login":{"user":"fw_user","os":"","ip":"127.0.0.1","proxy":""},"table_access_data":{"db":"test","table":"card_info","query":"select id, fname,lname,cnumber from card_info where id = 1","sql_command":"select"}}, {"timestamp":"2018-02-13 06:47:12","id":0,"class":"table_access","event":"read","connection_id":10,"account":{"user":"fw_user","host":"localhost"},"login":{"user":"fw_user","os":"","ip":"127.0.0.1","proxy":""},"table_access_data":{"db":"test","table":"card_info","query":"select id, fname,lname,cnumber from card_info where id = 2","sql_command":"select"}}, {"timestamp":"2018-02-13 06:47:15","id":0,"class":"table_access","event":"read","connection_id":11,"account":{"user":"fw_user","host":"localhost"},"login":{"user":"fw_user","os":"","ip":"127.0.0.1","proxy":""},"table_access_data":{"db":"test","table":"card_info","query":"select id, fname,lname,cnumber from card_info where id = 3","sql_command":"select"}}, {"timestamp":"2018-02-13 06:47:17","id":0,"class":"table_access","event":"read","connection_id":12,"account":{"user":"fw_user","host":"localhost"},"login":{"user":"fw_user","os":"","ip":"127.0.0.1","proxy":""},"table_access_data":{"db":"test","table":"card_info","query":"select id, fname,lname,cnumber from card_info where id = 4","sql_command":"select"}}, {"timestamp":"2018-02-13 06:47:23","id":0,"class":"table_access","event":"read","connection_id":14,"account":{"user":"fw_user","host":"localhost"},"login":{"user":"fw_user","os":"","ip":"127.0.0.1","proxy":""},"table_access_data":{"db":"test","table":"card_info","query":"select id, fname,lname,cnumber from card_info where id = 5","sql_command":"select"}}, null ]
1 row in set (0.01 sec)

root@localhost [(none)]> 

■ ログフォーマットの追加

XMLフォーマット(従来からのフォーマット)

[root@GA01 data]# head -n 20 audit.20180124T012252.log
<?xml version="1.0" encoding="UTF-8"?>
<AUDIT>
 <AUDIT_RECORD>
  <TIMESTAMP>2018-01-19T03:39:20 UTC</TIMESTAMP>
  <RECORD_ID>1_2018-01-19T03:39:20</RECORD_ID>
  <NAME>Audit</NAME>
  <SERVER_ID>101</SERVER_ID>
  <VERSION>1</VERSION>
  <STARTUP_OPTIONS>/usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=GA01.err --open-files-limit=8192 --pid-file=/usr/local/mysql/data/GA01.pid --socket=/tmp/mysql.sock --port=3306</STARTUP_OPTIONS>
  <OS_VERSION>x86_64-linux-glibc2.12</OS_VERSION>
  <MYSQL_VERSION>5.7.20-enterprise-commercial-advanced-log</MYSQL_VERSION>
 </AUDIT_RECORD>
 <AUDIT_RECORD>
  <TIMESTAMP>2018-01-19T04:48:42 UTC</TIMESTAMP>
  <RECORD_ID>2_2018-01-19T03:39:20</RECORD_ID>
  <NAME>NoAudit</NAME>
  <SERVER_ID>101</SERVER_ID>
 </AUDIT_RECORD>
 <AUDIT_RECORD>
  <TIMESTAMP>2018-01-23T04:17:19 UTC</TIMESTAMP>
[root@GA01 data]# 

JSONフォーマット(MySQL5.7.21以降で追加されたフォーマットオプション)

[root@GA01 data]# head -n 20 audit.log 
[
{ "timestamp": "2018-02-13 05:20:48", "id": 0, "class": "audit", "event": "startup", "connection_id": 0, "startup_data": { "server_id": 101, "os_version": "x86_64-linux-glibc2.12", "mysql_version": "5.7.21-enterprise-commercial-advanced-log", "args": ["/usr/local/mysql/bin/mysqld", "--basedir=/usr/local/mysql", "--datadir=/usr/local/mysql/data", "--plugin-dir=/usr/local/mysql/lib/plugin", "--user=mysql", "--log-error=GA01.err", "--open-files-limit=8192", "--pid-file=/usr/local/mysql/data/GA01.pid", "--socket=/tmp/mysql.sock", "--port=3306" ] } },
{ "timestamp": "2018-02-13 05:26:12", "id": 0, "class": "table_access", "event": "read", "connection_id": 4, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 1", "sql_command": "select" } }[root@GA01 data]# 

■ ログの圧縮


root@localhost [(none)]> show variables like 'audit_log_compression';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| audit_log_compression | NONE  |
+-----------------------+-------+
1 row in set (0.02 sec)

root@localhost [(none)]> 

my.cnfに”audit_log_compression=GZIP”を追加

root@localhost [(none)]> show variables like 'audit_log_compression';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| audit_log_compression | GZIP  |
+-----------------------+-------+
1 row in set (0.00 sec)

root@localhost [(none)]> 

ログファイルがGZIPされている事が確認出来る

[root@GA01 data]# ls -l audit.*
-rw-r-----. 1 mysql mysql  702  2月  7 20:42 audit.20180207T114235.log
-rw-r-----. 1 mysql mysql  702  2月 13 14:20 audit.20180213T052043.log
-rw-r-----. 1 mysql mysql 1099  2月 13 14:47 audit.20180213T054746.log
-rw-r-----. 1 mysql mysql  624  2月 13 14:58 audit.20180213T055818.log.gz
-rw-r-----. 1 mysql mysql   20  2月 13 14:58 audit.log.gz
[root@GA01 data]# 



[root@GA01 data]# gzip -dc audit.20180213T055818.log.gz | tail
{ "timestamp": "2018-02-13 05:53:28", "id": 0, "class": "table_access", "event": "read", "connection_id": 7, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 10", "sql_command": "select" } },
{ "timestamp": "2018-02-13 05:53:39", "id": 0, "class": "table_access", "event": "read", "connection_id": 9, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 5", "sql_command": "select" } },{ "timestamp": "2018-02-13 05:54:37", "id": 0, "class": "table_access", "event": "read", "connection_id": 10, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 5", "sql_command": "select" } },
{ "timestamp": "2018-02-13 05:54:38", "id": 0, "class": "table_access", "event": "read", "connection_id": 11, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 5", "sql_command": "select" } },
{ "timestamp": "2018-02-13 05:55:36", "id": 0, "class": "table_access", "event": "read", "connection_id": 12, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 5", "sql_command": "select" } },
{ "timestamp": "2018-02-13 05:55:37", "id": 0, "class": "table_access", "event": "read", "connection_id": 13, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 5", "sql_command": "select" } },
{ "timestamp": "2018-02-13 05:57:28", "id": 0, "class": "table_access", "event": "read", "connection_id": 14, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 12", "sql_command": "select" } },
{ "timestamp": "2018-02-13 05:57:31", "id": 0, "class": "table_access", "event": "read", "connection_id": 15, "account": { "user": "fw_user", "host": "localhost" }, "login": { "user": "fw_user", "os": "", "ip": "127.0.0.1", "proxy": "" }, "table_access_data": { "db": "test", "table": "card_info", "query": "select id, fname,lname,cnumber from card_info where id = 2", "sql_command": "select" } },
{ "timestamp": "2018-02-13 05:58:18", "id": 0, "class": "audit", "event": "shutdown", "connection_id": 0, "shutdown_data": { "server_id": 101 } }
][root@GA01 data]# 

■ GZIPされていても、audit_log_readでログファイルを確認する事が可能なようだ。

root@localhost [mysql]> select @bookmark;
+-------------------------------------------------+
| @bookmark                                       |
+-------------------------------------------------+
| { "timestamp": "2018-02-13 07:17:12", "id": 0 } |
+-------------------------------------------------+
1 row in set (0.00 sec)

root@localhost [mysql]> SELECT audit_log_read(@bookmark)\G
*************************** 1. row ***************************
audit_log_read(@bookmark): [ {"timestamp":"2018-02-13 07:17:12","id":0,"class":"audit","event":"startup","connection_id":0,"startup_data":{"server_id":101,"os_version":"x86_64-linux-glibc2.12","mysql_version":"5.7.21-enterprise-commercial-advanced-log","args":["/usr/local/mysql/bin/mysqld","--basedir=/usr/local/mysql","--datadir=/usr/local/mysql/data","--plugin-dir=/usr/local/mysql/lib/plugin","--user=mysql","--log-error=GA01.err","--open-files-limit=8192","--pid-file=/usr/local/mysql/data/GA01.pid","--socket=/tmp/mysql.sock","--port=3306"]}}, null ]
1 row in set (0.00 sec)

root@localhost [mysql]> SELECT audit_log_read(@bookmark)\G
*************************** 1. row ***************************
audit_log_read(@bookmark): [ {"timestamp":"2018-02-13 07:17:12","id":0,"class":"audit","event":"startup","connection_id":0,"startup_data":{"server_id":101,"os_version":"x86_64-linux-glibc2.12","mysql_version":"5.7.21-enterprise-commercial-advanced-log","args":["/usr/local/mysql/bin/mysqld","--basedir=/usr/local/mysql","--datadir=/usr/local/mysql/data","--plugin-dir=/usr/local/mysql/lib/plugin","--user=mysql","--log-error=GA01.err","--open-files-limit=8192","--pid-file=/usr/local/mysql/data/GA01.pid","--socket=/tmp/mysql.sock","--port=3306"]}}, {"timestamp":"2018-02-13 07:18:33","id":0,"class":"table_access","event":"read","connection_id":5,"account":{"user":"fw_user","host":"localhost"},"login":{"user":"fw_user","os":"","ip":"127.0.0.1","proxy":""},"table_access_data":{"db":"test","table":"card_info","query":"select id, fname,lname,cnumber from card_info where id = 3","sql_command":"select"}}, null ]
1 row in set (0.00 sec)

root@localhost [mysql]> 

■ Auditログの暗号化

AESでAuditログを暗号化する機能が追加された。

root@localhost [(mysql)]> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM 
INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'keyring%';

+--------------+---------------+
| PLUGIN_NAME  | PLUGIN_STATUS |
+--------------+---------------+
| keyring_file | ACTIVE        |
+--------------+---------------+
1 row in set (0.00 sec)

root@localhost [(none)]> show variables like 'audit_log_encryption';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| audit_log_encryption | AES   |
+----------------------+-------+
1 row in set (0.02 sec)

root@localhost [(none)]> 

Auditログは暗号化されているため、先に複合化しないと読み込めない。

[root@GA01 data]# ls -l audit*.enc
-rw-r-----. 1 mysql mysql 32  2月 13 17:34 audit.log.gz.enc
[root@GA01 data]# 


[root@GA01 data]# gzip -dc audit.20180213T084836.log.gz.enc 

gzip: audit.20180213T084836.log.gz.enc: not in gzip format
[root@GA01 data]# 

参照:
7.5.5 Audit Log Logging Control


MySQL8.0.4 RCがリリースされたので、その中でJSON関連の関数JSON_TABLEがリリースされていたので、合わせて挙動を確認してみました。
MySQLにはJSON関数が30弱ありますが、便利なJSON関数が増えてきているので、これまで以上にNOSQL関連データを扱う処理の選択肢として活用出来そうです。

MySQL 8.0.4 Release Candidateの変更点
参照:https://mysqlserverteam.com/the-mysql-8-0-4-release-candidate-is-available/

多くの変更があるので、上記ブログを確認頂いた方が良さそうです。
一部抜粋:
Security:
caching_sha2_password default authentication mechanism
Dynamic Linking of OpenSSL in MySQL Server(yaSSL->OpenSSL)
JSON Functions:
JSON Table Functions
RLIKE/REGEXP:
ICU library to handle RLIKE/REGEXP
SQL DIGEST:
STATEMENT_DIGEST() and STATEMENT_DIGEST_TEXT()
Tablespaces:
ibd and system tablespace files can be moved from one location to another while the server is offline.

and so on ….. Pleases check mysqlserverteam blog.

JSON_TABLEの検証

JSON_TABLE詳細:
WL#8867: Add JSON table functions
https://dev.mysql.com/worklog/task/?id=8867

MySQL8.0.4をDockerにて起動

docker run --name mysql84 -v /docker/docker84:/var/lib/mysql -v /docker/option84:/etc/mysql/conf.d -v /docker/init_script:/docker-entrypoint-initdb.d -e MYSQL_ROOT_PASSWORD=mysql -d mysql/mysql-server:8.0



[root@DockerHost docker]# docker run --name mysql84 -v /docker/docker84:/var/lib/mysql -v /docker/option84:/etc/mysql/conf.d -v /docker/init_script:/docker-entrypoint-initdb.d -e MYSQL_ROOT_PASSWORD=mysql -d mysql/mysql-server:8.0
f314f67d547db50b89be395555fccf2c54dc1d390932a9666c7bfb40da25de1d
[root@DockerHost docker]# 

JSONデータを作成して、JSON_TABLE関数を利用してデータを抽出。
SONデータをそのまま、通常のリレーショナルなテーブルから列を抽出するように扱う事が出来る。JSONデータにWHERE句を利用した抽出も可能。おそらく、JSONデータと生成列を活用してINDEXを利用して参照した方が早いとは思いますが、使いどころは色々とあるかと思います。

[root@DockerHost docker]# docker exec -it mysql84 mysql --default-character-set=utf8mb4 -uroot -p 
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.4-rc-log MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sakila             |
| sys                |
+--------------------+
5 rows in set (0.13 sec)

mysql> select @@version;
+--------------+
| @@version    |
+--------------+
| 8.0.4-rc-log |
+--------------+
1 row in set (0.01 sec)

mysql> 



mysql> CREATE TABLE `T_JSON` (
    ->   `id` int(10) NOT NULL AUTO_INCREMENT,
    ->   `body` json DEFAULT NULL,
    ->   PRIMARY KEY (`id`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected (0.14 sec)

mysql> INSERT INTO T_JSON(body) VALUES ('{"id":1,"name":"washing machine","price":10000,"Conditions":["NEW",2015]}');
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO T_JSON(body) VALUES ('{"id":2,"name":"TV","price":30000,"Conditions":["USED",2013]}');
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO T_JSON(body) VALUES ('{"id":3,"name":"refrigerator","price":50000,"Conditions":["NEW",2015]}');
Query OK, 1 row affected (0.02 sec)


mysql> select * from T_JSON;
+----+-----------------------------------------------------------------------------------+
| id | body                                                                              |
+----+-----------------------------------------------------------------------------------+
|  1 | {"id": 1, "name": "washing machine", "price": 10000, "Conditions": ["NEW", 2015]} |
|  2 | {"id": 2, "name": "TV", "price": 30000, "Conditions": ["USED", 2013]}             |
|  3 | {"id": 3, "name": "refrigerator", "price": 50000, "Conditions": ["NEW", 2015]}    |
+----+-----------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

mysql> 


mysql> select * from T_JSON, JSON_TABLE(body,"$" COLUMNS
    -> ( 
    ->  product_name varchar(20) PATH "$.name",
    ->  product_price varchar(10) PATH "$.price")
    -> ) AS products
    -> where products.product_name in ('TV');
+----+-----------------------------------------------------------------------+--------------+---------------+
| id | body                                                                  | product_name | product_price |
+----+-----------------------------------------------------------------------+--------------+---------------+
|  2 | {"id": 2, "name": "TV", "price": 30000, "Conditions": ["USED", 2013]} | TV           | 30000         |
+----+-----------------------------------------------------------------------+--------------+---------------+
1 row in set (0.00 sec)

mysql> 


mysql> select products.* from T_JSON,JSON_TABLE(body,"$" COLUMNS
    -> (
    -> product_name varchar(20) PATH "$.name",
    -> product_price varchar(10) PATH "$.price")
    -> ) AS products
    -> where products.product_name in ('TV');
+--------------+---------------+
| product_name | product_price |
+--------------+---------------+
| TV           | 30000         |
+--------------+---------------+
1 row in set (0.00 sec)


mysql> select products.* from T_JSON,JSON_TABLE(body,"$" COLUMNS
    -> (
    -> id for ordinality,
    -> product_name varchar(20) PATH "$.name",
    -> product_price varchar(10) PATH "$.price")
    -> ) AS products
    -> where products.product_name in ('TV');
+------+--------------+---------------+
| id   | product_name | product_price |
+------+--------------+---------------+
|    1 | TV           | 30000         |
+------+--------------+---------------+
1 row in set (0.01 sec)

mysql> 

mysql> explain select products.* from T_JSON,JSON_TABLE(body,"$" COLUMNS
    -> (
    -> product_name varchar(20) PATH "$.name",
    -> product_price varchar(10) PATH "$.price")
    -> ) AS products
    -> where products.product_name in ('TV');
+----+-------------+----------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------------+
| id | select_type | table    | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra                                       |
+----+-------------+----------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------------+
|  1 | SIMPLE      | T_JSON   | NULL       | ALL  | NULL          | NULL        | NULL    | NULL  |    2 |   100.00 | NULL                                        |
|  1 | SIMPLE      | products | NULL       | ref  | <auto_key0>   | <auto_key0> | 83      | const |    1 |   100.00 | Table function: json_table; Using temporary |
+----+-------------+----------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

mysql>  

WORKLOG抜粋:
It’s used to extract data from a JSON document and form a relational table, that could be processed further using SQL. It’s a virtual table,
in this sense it’s like a derived table, with only difference in how result data is obtained. Just like a derived table, it’s specified in the FROM
clause, uses tmp table to store its result, and is able to provide generated indexes for ref access.

JSON_TABLEマニュアル
https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html

Please check additional details for MySQL8.0
http://mysqlserverteam.com/


5.6.1で既に実装されていてDefaultでONになっているので,5.6や5.7では普段殆ど気にしてませんでしたが、質問頂いたのでindex_condition_pushdownの条件を再確認。
DefaultはONになっています。あえて、OFFにするメリットはあまり無いかと思います。

Index Condition Pushdown(ICP): ストレージエンジンからフェッチしたレコードをMySQLが評価してWHERE区の条件による絞り込みを行っていたが、
インデックスが貼られたカラムを用いた評価については、ストレージエンジンへ条件式を渡し(プッシュダウン)、ストレージエンジン側で評価を行わせることによってオーバーヘッドの低減させる。

ICPの目標は、完全なレコードの読み取りの回数を減らし、それによって I/O 操作を減らすことです。InnoDB のクラスタ化されたインデックスの場合、完全なレコードはすでに InnoDB バッファーに読み込まれています。この場合に ICP を使用しても IO は削減されません。 その為、ICP はセカンダリインデックスにのみ使用されます。

インデックス条件をプッシュダウンしようとするのは以下の条件の場合:
0. テーブルには選択条件がある。
1. ストレージエンジンがICPをサポートする。
2. index_condition_pushdownスイッチがオンで、ICPの使用がNO_ICPヒントによって無効にされていない。
3. クエリーは、複数表の更新または削除ステートメントでは無い。この要件の理由は、選択/結合と更新の両方に同じハンドラが使用されるためです。プッシュされたインデックス条件は、更新部分を実行するときにストレージエンジンによって適用され、誤ったレコードを更新または更新するためのレコードを見つけられない結果になることがあります。
4. JOIN_TABは、”NULLキーをフル・スキャン”実行中にオンまたはオフにできる条件を保護しているサブクエリの一部ではありません。

       @see Item_in_optimizer :: val_int()
       @see subselect_single_select_engine :: exec()
       @see TABLE_REF :: cond_guards
       @see setup_join_buffering

5.結合タイプはCONSTまたはSYSTEMではありません。これらの結合タイプを除外する理由は、これらの結合タイプが、ストレージエンジンから一度だけレコードを読み取り、後でそれを再利用するように最適化されているためです。プッシュされたインデックス条件が結合シーケンスの前のテーブルからのフィールドを評価する結合では、プッシュされた条件は、レコード値が最初に必要とされたときにのみ評価されます。
6.インデックスはクラスタ化インデックスではありません。クラスタ化されたキーでインデックス条件をプッシュすると、クラスタ化されていないキーよりも大幅に低くなります。WL#6061が実装されている場合、この制限は再評価する必要があります。
7.仮想生成列の索引は、ICPではサポートされていません。

Ref Source:
https://github.com/mysql/mysql-server/blob/5.7/sql/sql_select.cc#L1723

index_condition_pushdown=offを意図的にOFFにした場合

root@localhost [world]> SET optimizer_switch='index_condition_pushdown=off';
Query OK, 0 rows affected (0.00 sec)

root@localhost [world]> explain select * from City3 where CountryCode ='JPN' and District like '%o%';
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | City3 | NULL       | ref  | idx_City3     | idx_City3 | 9       | const |  605 |    11.11 | Using where |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

root@localhost [world]> show status like 'Handler_read%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Handler_read_first    | 0     |
| Handler_read_key      | 1     |
| Handler_read_last     | 0     |
| Handler_read_next     | 605   |
| Handler_read_prev     | 0     |
| Handler_read_rnd      | 0     |
| Handler_read_rnd_next | 0     |
+-----------------------+-------+
7 rows in set (0.00 sec)

root@localhost [world]> 

Defaultの挙動 (index_condition_pushdown=on)

root@localhost [world]> SET optimizer_switch='index_condition_pushdown=on';
Query OK, 0 rows affected (0.00 sec)

root@localhost [world]> explain select * from City3 where CountryCode ='JPN' and District like '%o%';
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | City3 | NULL       | ref  | idx_City3     | idx_City3 | 9       | const |  605 |    11.11 | Using index condition |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

root@localhost [world]> show status like 'Handler_read%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Handler_read_first    | 0     |
| Handler_read_key      | 1     |
| Handler_read_last     | 0     |
| Handler_read_next     | 440   |
| Handler_read_prev     | 0     |
| Handler_read_rnd      | 0     |
| Handler_read_rnd_next | 0     |
+-----------------------+-------+
7 rows in set (0.01 sec)

参照:
http://nippondanji.blogspot.jp/2011/04/mysql-56.html
https://www.percona.com/blog/2014/01/03/multiple-column-index-vs-multiple-indexes-with-mysql-56/


MySQL Enterprise Edition on official docker image

商用版のライセンスを利用者が別途準備する事で(Bring Your Own License)商用版のMySQLをDockerで利用する事が可能です。
https://blogs.oracle.com/mysql/mysql-enterprise-edition-now-in-docker-store

MySQLライセンスについては此方を参照下さい。
https://www.mysql.com/jp/products/
物理サーバーライセンスなので、Dockerを複数立ち上げるような開発環境ではコストメリットが大きいかと思います。

STEP1: Dockerストアにアクセス
https://store.docker.com
https://store.docker.com/images/mysql-enterprise-server 

STEP2:Checkoutに進むと以下のように入力が画面が出てくるので、必要な入力項目を入れて下さい。

STEP3: Checkoutするとインストール方法とイメージのPULL用URLが表示されます。

STEP4: 利用可能パッケージの確認
自分のアカウントで利用可能な、パッケージが以下のURLにアクセスする事が出来ます。

https://store.docker.com/profiles/{DockerID}/content 

STEP5: ここからは実際にイメージをダウンロードして初期設定後に環境の確認をしてみます。

[root@DockerHost oracle]# docker login
Username: myaccount
Password: 
Email: my.private@variable.jp
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded
[root@DockerHost oracle]# docker pull store/oracle/mysql-enterprise-server:5.7
5.7: Pulling from store/oracle/mysql-enterprise-server
0a8af4fbe73a: Pull complete 
f8726cc27fe2: Pull complete 
fae37bbdd736: Pull complete 
39a334372a33: Pull complete 
f9c82196334c: Pull complete 
ef578d7130a0: Pull complete 
847fdfc5f5d7: Pull complete 
8e21b593de13: Pull complete 
5b0a6ab7d9e4: Pull complete 
99091fe3cf31: Pull complete 
483de1c4dc82: Pull complete 
f7d4675ff63d: Pull complete 
c41819234bbd: Pull complete 
Digest: sha256:09a6201fe690055c450f7e17a94efc4f10ae38b2607242abae191e3b283698f5
Status: Downloaded newer image for store/oracle/mysql-enterprise-server:5.7
[root@DockerHost oracle]# 

あとで、設定を適宜変更したいのでデータやオプションファイルのパスを指定してインスタンスの初期化を行っています。

[root@DockerHost oracle]# docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
store/oracle/mysql-enterprise-server   5.7                 c41819234bbd        13 days ago         246.9 MB
mysql/mysql-server                     8.0                 270395aafb1e        3 months ago        295.3 MB
mysql                                  5.7.15              3dd6dfe65426        15 months ago       383.4 MB
mysql/mysql-server                     5.7.15              de24da03ab76        15 months ago       369.1 MB
[root@DockerHost oracle]# 

[root@DockerHost docker57ee]# docker run --name=mysql57ee -v /docker/option57ee/my.cnf:/etc/my.cnf -v /docker/docker57ee:/var/lib/mysql -e MYSQL_RANDOM_ROOT_PASSWORD=true -e MYSQL_ONETIME_PASSWORD=true -d store/oracle/mysql-enterprise-server:5.7
9ea25f5c1df4a6045197d3adac2e123faa404b538919775cc6269e0d0556a921
[root@DockerHost docker57ee]# docker logs mysql57ee
[Entrypoint] MySQL Docker Image 5.7.20-1.1.2
<SNIP>
[Entrypoint] GENERATED ROOT PASSWORD: hUmv@v+EgFopmUcZIr-yqegLOn

[root@DockerHost docker57ee]# docker ps -a
CONTAINER ID        IMAGE                                      COMMAND                  CREATED             STATUS                      PORTS                 NAMES
38347f04b6b7        store/oracle/mysql-enterprise-server:5.7   "/entrypoint.sh mysql"   4 minutes ago       Up 4 minutes                3306/tcp, 33060/tcp   mysql57ee
ecd2156cdd36        mysql/mysql-server:8.0                     "/entrypoint.sh mysql"   12 weeks ago        Exited (0) 19 minutes ago                         mysql83
d92d218ffff6        mysql/mysql-server:5.7.15                  "/entrypoint.sh mysql"   15 months ago       Exited (0) 8 months ago                           multi_docker05
7e9de9a905ad        mysql/mysql-server:5.7.15                  "/entrypoint.sh mysql"   15 months ago       Exited (0) 15 months ago                          multi_docker04
fb1c8aaf8de7        mysql/mysql-server:5.7.15                  "/entrypoint.sh mysql"   15 months ago       Exited (0) 14 months ago                          multi_docker03
[root@DockerHost docker57ee]# 

ログインして、初期パスワードを変更後にバージョンとプラグインを確認。
現状ではプラグインを設定してないのでロードはされてませんが、モジュールが存在するところまで確認してあります。


[root@DockerHost docker57ee]# docker exec -it mysql57ee mysql --default-character-set=utf8mb4 -uroot -phUmv@v+EgFopmUcZIr-yqegLOn
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.20-enterprise-commercial-advanced-log

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

root@localhost [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED BY 'mysql';
Query OK, 0 rows affected (0.01 sec)

root@localhost [(none)]> select user,host from mysql.user;
+---------------+-----------+
| user          | host      |
+---------------+-----------+
| healthchecker | localhost |
| mysql.session | localhost |
| mysql.sys     | localhost |
| root          | localhost |
+---------------+-----------+
4 rows in set (0.00 sec)

root@localhost [(none)]> select @@version;
+-------------------------------------------+
| @@version                                 |
+-------------------------------------------+
| 5.7.20-enterprise-commercial-advanced-log |
+-------------------------------------------+
1 row in set (0.00 sec)

root@localhost [(none)]> show variables like 'plugin%';
+---------------+--------------------------+
| Variable_name | Value                    |
+---------------+--------------------------+
| plugin_dir    | /usr/lib64/mysql/plugin/ |
+---------------+--------------------------+
1 row in set (0.01 sec)

root@localhost [(none)]> system ls -l /usr/lib64/mysql/plugin/
total 4484
-rwxr-xr-x 1 root root   22336 Sep 13 17:12 adt_null.so
-rwxr-xr-x 1 root root  299944 Sep 13 17:12 audit_log.so
-rwxr-xr-x 1 root root    7392 Sep 13 17:12 auth_socket.so
-rwxr-xr-x 1 root root   40712 Sep 13 17:12 authentication_ldap_sasl_client.so
-rwxr-xr-x 1 root root   19928 Sep 13 17:12 authentication_pam.so
-rwxr-xr-x 1 root root   50216 Sep 13 17:12 connection_control.so
-rwxr-xr-x 1 root root  100064 Sep 13 17:12 firewall.so
-rwxr-xr-x 1 root root 1240104 Sep 13 17:12 group_replication.so
-rwxr-xr-x 1 root root  116624 Sep 13 17:12 innodb_engine.so
-rwxr-xr-x 1 root root   86792 Sep 13 17:12 keyring_file.so
-rwxr-xr-x 1 root root  287256 Sep 13 17:12 keyring_okv.so
-rwxr-xr-x 1 root root   19968 Sep 13 17:12 keyring_udf.so
-rwxr-xr-x 1 root root  192696 Sep 13 17:12 libmemcached.so
-rwxr-xr-x 1 root root   10920 Sep 13 17:12 locking_service.so
-rwxr-xr-x 1 root root   11928 Sep 13 17:12 mypluglib.so
-rwxr-xr-x 1 root root    7352 Sep 13 17:12 mysql_no_login.so
-rwxr-xr-x 1 root root 1714912 Sep 13 17:12 mysqlx.so
-rwxr-xr-x 1 root root   49368 Sep 13 17:12 openssl_udf.so
-rwxr-xr-x 1 root root    7480 Sep 13 17:12 rewrite_example.so
-rwxr-xr-x 1 root root   53992 Sep 13 17:12 rewriter.so
-rwxr-xr-x 1 root root   63312 Sep 13 17:12 semisync_master.so
-rwxr-xr-x 1 root root   16112 Sep 13 17:12 semisync_slave.so
-rwxr-xr-x 1 root root   61312 Sep 13 17:12 thread_pool.so
-rwxr-xr-x 1 root root   29352 Sep 13 17:12 validate_password.so
-rwxr-xr-x 1 root root   33016 Sep 13 17:12 version_token.so
root@localhost [(none)]> 

本日の説明はここまで。Docker環境でもMySQLのEnterprise Editionの機能を利用して開発や検証したい方にはお勧め。

Please Enjoy it.


MySQL8.0のヒント句が便利になっていたので基本動作確認。
バッチ処理前にSETコマンドで動的に設定していたセッション変数を実行するクエリーにヒントとして追加する事が出来るようです。

WL#681: Hint to temporarily set session variable for current statement
https://dev.mysql.com/worklog/task/?id=681

Syntax of the SET_VAR hint is:


 /*+ SET_VAR( = ) */

大量のデータをOrder by, Group by等でソート処理していて、Sort_merge_passesが多発している場合にソートバッファーの不足をヒント句で回避してディスクI/Oの発生を抑える事が出来る。
大量データのソートが多いバッチ処理などに組み込んでおくと、処理が早く終わらせる事が出来る。
(例)


mysql> SELECT /*+ SET_VAR(sort_buffer_size = 4M) */ name FROM city ORDER BY name;


実際にデータを準備してsort_buffer_sizeヒント句を検証した結果
Duration: 12.71 sec → 6.45 sec
sort_merge_passes: 216 → 0


mysql> select count(*) from ( select v.name, count(*) from t_group g join tbnode n on g.groupid = n.groupid join t_virual v on n.nodeid = v.nodeid group by v.name with rollup) t;
+----------+
| count(*) |
+----------+
|     1001 |
+----------+
1 row in set (12.71 sec)

mysql> select * from sys.statement_analysis limit 1\G
*************************** 1. row ***************************
            query: SELECT COUNT ( * ) FROM ( SELE ... v` . `name` WITH ROLLUP ) `t` 
               db: PERF
        full_scan: *
       exec_count: 1
        err_count: 0
       warn_count: 0
    total_latency: 12.71 s
      max_latency: 12.71 s
      avg_latency: 12.71 s
     lock_latency: 1.47 ms
        rows_sent: 1
    rows_sent_avg: 1
    rows_examined: 3102001
rows_examined_avg: 3102001
    rows_affected: 0
rows_affected_avg: 0
       tmp_tables: 2
  tmp_disk_tables: 0
      rows_sorted: 1000000
sort_merge_passes: 216
           digest: 1e941ce49e8f810963a8468995dc2eaf
       first_seen: 2017-09-28 20:29:46.768069
        last_seen: 2017-09-28 20:29:46.768069
1 row in set (0.01 sec)

mysql> 


mysql> CALL sys.ps_truncate_all_tables(FALSE);
+---------------------+
| summary             |
+---------------------+
| Truncated 49 tables |
+---------------------+
1 row in set (0.17 sec)

Query OK, 0 rows affected (0.18 sec)

mysql> select  /*+ SET_VAR(sort_buffer_size = 16M) */ count(*) from (select v.name, count(*) from t_group g join tbnode n on g.groupid = n.groupid join t_virual v on n.nodeid = v.nodeid  group by v.name with rollup) t;
+----------+
| count(*) |
+----------+
|     1001 |
+----------+
1 row in set (6.45 sec)

mysql> select * from sys.statement_analysis limit 1\G
*************************** 1. row ***************************
            query: SELECT /*+ SET_VAR ( `sort_buf ... v` . `name` WITH ROLLUP ) `t` 
               db: PERF
        full_scan: *
       exec_count: 1
        err_count: 0
       warn_count: 0
    total_latency: 9.94 s
      max_latency: 9.94 s
      avg_latency: 9.94 s
     lock_latency: 406.00 us
        rows_sent: 1
    rows_sent_avg: 1
    rows_examined: 3102001
rows_examined_avg: 3102001
    rows_affected: 0
rows_affected_avg: 0
       tmp_tables: 2
  tmp_disk_tables: 0
      rows_sorted: 1000000
sort_merge_passes: 0
           digest: bdf5d04f4574930fef467d6c359c49bf
       first_seen: 2017-09-28 20:37:42.923895
        last_seen: 2017-09-28 20:37:42.923895
1 row in set (0.01 sec)

使いどころが難しいが、以下のようにauto_increment_increment等の値もヒント句で変更出来るようです。


mysql> CREATE TABLE `T_SET_VAR` (
    ->   `id` int(10) NOT NULL AUTO_INCREMENT,
    ->   `memo` varchar(100) DEFAULT NULL,
    ->   PRIMARY KEY (`id`)
    -> ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected (0.18 sec)

mysql> insert into T_SET_VAR(memo) values('auto_increment_increment test');
Query OK, 1 row affected (0.08 sec)

mysql> insert into T_SET_VAR(memo) values('auto_increment_increment test2');
Query OK, 1 row affected (0.03 sec)

mysql> select * from T_SET_VAR;                                                                                                  
+----+--------------------------------+
| id | memo                           |
+----+--------------------------------+
|  1 | auto_increment_increment test  |
|  2 | auto_increment_increment test2 |
+----+--------------------------------+
2 rows in set (0.00 sec)

mysql> select * from T_SET_VAR;                                             
+----+--------------------------------+
| id | memo                           |
+----+--------------------------------+
|  1 | auto_increment_increment test  |
|  2 | auto_increment_increment test2 |
+----+--------------------------------+
2 rows in set (0.00 sec)

mysql> insert /*+ SET_VAR(auto_increment_increment = 10) */ into T_SET_VAR(memo) values('auto_increment_increment test3?');
Query OK, 1 row affected (0.03 sec)

mysql> select * from T_SET_VAR;                                                                                            
+----+---------------------------------+
| id | memo                            |
+----+---------------------------------+
|  1 | auto_increment_increment test   |
|  2 | auto_increment_increment test2  |
| 11 | auto_increment_increment test3? |
+----+---------------------------------+
3 rows in set (0.00 sec)

その他、Worklogによると以下のように、色々なセッション変数をSETコマンドを利用しないでヒント句で指定出来るようです。

List of settable variables:
———————————————————————————-
auto_increment_increment
auto_increment_offset
big_tables
bulk_insert_buffer_size
default_tmp_storage_engine
div_precision_increment
end_markers_in_json
eq_range_index_dive_limit
foreign_key_checks
group_concat_max_len
insert_id
internal_tmp_mem_storage_engine
join_buffer_size
lock_wait_timeout
max_error_count
max_execution_time
max_heap_table_size
max_join_size
max_length_for_sort_data
max_points_in_geometry
max_seeks_for_key
max_sort_length
optimizer_prune_level
optimizer_search_depth variables
optimizer_switch
range_alloc_block_size
range_optimizer_max_mem_size
read_buffer_size
read_rnd_buffer_size
sort_buffer_size
sql_auto_is_null
sql_big_selects
sql_buffer_result
sql_mode
sql_safe_updates
sql_select_limit
timestamp
tmp_table_size
updatable_views_with_limit
unique_checks
windowing_use_high_precision
———————————————————————————-

参照: The MySQL 8.0.3 Release Candidate is available


MySQL8.0 RCのDockerイメージがリリースされていたので、今後の検証やデモ用に設定しました。
手軽に検証出来るので、軽く検証するにはお勧めです。

Docker Image: https://github.com/mysql/mysql-docker


[root@DockerHost oracle]# docker pull mysql/mysql-server:8.0
8.0: Pulling from mysql/mysql-server
323fb8f65502: Pull complete 
b2a15600aac3: Pull complete 
a1116f4203e9: Pull complete 
8be6f234356c: Pull complete 
a09590e34bdc: Pull complete 
554cdb588e9e: Pull complete 
851fce189663: Pull complete 
ca60670c6cb3: Pull complete 
98a8195f4fc5: Pull complete 
ec8c0ade6c51: Pull complete 
73919c529833: Pull complete 
285b77036a3a: Pull complete 
270395aafb1e: Pull complete 
Digest: sha256:183772d6f5a1decd1eb0252e542d338a5ef8c02fe4cc2cc909b58788f8728c58
Status: Downloaded newer image for mysql/mysql-server:8.0
[root@DockerHost oracle]#

[root@DockerHost oracle]# docker run --name mysql83 -v /docker/docker83:/var/lib/mysql -v /docker/option83:/etc/mysql/conf.d -v /docker/init_script:/docker-entrypoint-initdb.d -e MYSQL_ROOT_PASSWORD=mysql -d mysql/mysql-server:8.0
ecd2156cdd36d735b5d01f6d7b89ea24cc7d499cbc59e1014bc42ba92c764365
[root@DockerHost oracle]# 

[root@DockerHost oracle]# docker exec -it mysql83 mysql --default-character-set=utf8mb4 -uroot -pmysql
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 8.0.3-rc-log MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select @@version;
+--------------+
| @@version    |
+--------------+
| 8.0.3-rc-log |
+--------------+
1 row in set (0.00 sec)

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.03 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sakila             |
| sys                |
| world              |
+--------------------+
7 rows in set (0.00 sec)


メモ:CTEの確認

mysql> WITH RECURSIVE  
    -> emp_ext (id, name, path) AS ( 
    ->    SELECT id, name, CAST(id AS CHAR(200)) 
    ->    FROM employees WHERE manager_id IS NULL 
    ->  UNION ALL 
    ->    SELECT s.id, s.name,CONCAT(m.path, ",", s.id) 
    ->    FROM emp_ext m JOIN  employees s ON m.id=s.manager_id )
    -> SELECT * FROM emp_ext ORDER BY path; 
+------+---------+-----------------+
| id   | name    | path            |
+------+---------+-----------------+
|  333 | Yasmina | 333             |
|  198 | John    | 333,198         |
|   29 | Pedro   | 333,198,29      |
| 4610 | Sarah   | 333,198,29,4610 |
|   72 | Pierre  | 333,198,29,72   |
|  692 | Tarek   | 333,692         |
|  123 | Adil    | 333,692,123     |
+------+---------+-----------------+
7 rows in set (0.00 sec)

mysql> 

メモ:Windows Functionの確認


mysql> select employee,date,sale,SUM(sale)
    -> OVER (PARTITION BY employee) AS sum FROM sales;
+----------+------------+------+------+
| employee | date       | sale | sum  |
+----------+------------+------+------+
| A        | 2017-03-01 |  200 |  900 |
| A        | 2017-04-01 |  300 |  900 |
| A        | 2017-05-01 |  400 |  900 |
| B        | 2017-03-01 |  400 | 1200 |
| B        | 2017-04-01 |  300 | 1200 |
| B        | 2017-05-01 |  500 | 1200 |
| C        | 2017-03-01 |  100 | 1000 |
| C        | 2017-04-01 |  600 | 1000 |
| C        | 2017-05-01 |  300 | 1000 |
+----------+------------+------+------+
9 rows in set (0.00 sec)

mysql> 

MySQL8.0には管理者と開発者にとって使い易い機能や関数も増えているので、
色々な場面で活用する事が出来るかと思います。

詳細情報:
http://mysqlserverteam.com/

バグ報告:
https://bugs.mysql.com/

ブログにはRC1と書いてあったけど、RC2とかもリリース予定なのかな?
Please enjoy it.


MySQL8.0がリリース候補版になりました。

Changes in MySQL 8.0.3 (2017-09-21, Release Candidate)
リリースノート:https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-3.html

【主な変更点】
Histograms, Force Index, Hints, Invisible Indexes
Common Table Expressions, Windows Functions, Character Sets,
JSON, GIS, Resource Groups, Performance Schema, Security,
Protocol, Service Infrastructure, X Protocol / X Plugin,
Performance, Tablespaces, DDL, Replication, Group Replication,
Data Dictionary, MTR Tests, Library Upgrade, Changes to Defaults

詳細:http://mysqlserverteam.com/the-mysql-8-0-3-release-candidate-is-available/

全てをカバーしてませんが、先日のセミナー資料で概要を紹介しています。


DB Tech Showcase 2017にてMySQL InnoDB Clusterの概要説明とデモをさせて頂きました。
プレゼン資料をスライドシェアにアップロードしたので、2017年4月にリリースされたMySQL標準の高可用性構成に興味あるある方、若しくは高可用性構成を検討の方はご覧ください。

余談ですが、WP Social Bookmarking Lightプラグインをアップグレードしたら古いPHPで動かなかったので、PHP5.6のバージョンにアップグレードしました。もし、WordPressのアップグレードのタイミングでwp-social-bookmarking-light.phpがエラーになったら、PHPを5.5以上にアップグレードしてみて下さい。