dshimizu/blog

アルファ版

MySQL InnoDB Cluster初期作成時に Dba.createCluster: ERROR: 1 table(s) do not have a Primary Key or Primary Key Equivalent (non-null unique key) となった場合の対処

MySQL ShellからMySQL InnoDB Clusterを作ろうとした時に以下のようなエラーが出ましたので、その原因の調査と対応手順をまとめます。 icrootと言うのは InnoDB Cluster 管理用のユーザとします。

mysql-js> cluster = dba.createCluster('ClusterDev');
A new InnoDB cluster will be created on instance 'icroot@192.168.10.65:3306'.

Warning: The instance configuration needs to be changed in order to
create an InnoDB cluster. To see which changes will be made, please
use the dba.checkInstanceConfiguration() function before confirming
to change the configuration.

Should the configuration be changed accordingly? [y|N]: y

Creating InnoDB cluster 'ClusterDev' on 'icroot@192.168.10.65:3306'...
Dba.createCluster: ERROR: 1 table(s) do not have a Primary Key or Primary Key Equivalent (non-null unique key).
ERROR: Error starting cluster: The operation could not continue due to the following requirements not being met:
Non-compatible tables found in database. (RuntimeError)

環境

調査と解決策

どうもPKのないテーブルを扱おうとしているためにエラーとなっているようです。InnoDB ClusterはPKのないテーブルをサポートしていないので、PKのないテーブルがある場合にこのエラーが出るのは正常な動作と思います。 しかし、今回はデフォルトで存在する以下のデータベースしかありません。sysデータベースの中のテーブルにはPKのないテーブルがありますが、あらかじめ存在するシステムテーブルが原因なのか…

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

とりあえずエラーメッセージでググると以下がヒットしました。

どうもsys.sys_configに対する権限が足りないのでInnoDB Clusterを扱うユーザの権限を見直せとか言われていているような感じがします。

InnoDB Clusterでのユーザ権限に関するドキュメントを見てみます。

InnoDBクラスタメタデータテーブルに完全な読み書き権限を割り当てる必要がある」とのことで、以下が必要なようです。

GRANT ALL PRIVILEGES ON mysql_innodb_cluster_metadata.* TO your_user@'%' WITH GRANT OPTION;
GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO your_user@'%' WITH GRANT OPTION;
GRANT SELECT ON performance_schema.* TO your_user@'%' WITH GRANT OPTION;
GRANT SELECT ON *.* TO your_user@'%' WITH GRANT OPTION;
GRANT SELECT, INSERT, UPDATE, DELETE ON mysql.* TO your_user@'%' WITH GRANT OPTION;

実際に存在するユーザ権限をみてみます。

root@mysql1 > show grants for icroot@`%`;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for icroot@%                                                                                                                       |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'icroot'@'%' WITH GRANT OPTION |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO 'icroot'@'%' WITH GRANT OPTION                                                       |
| GRANT SELECT ON `performance_schema`.* TO 'icroot'@'%' WITH GRANT OPTION                                                                  |
| GRANT ALL PRIVILEGES ON `mysql_innodb_cluster_metadata`.* TO 'icroot'@'%' WITH GRANT OPTION                                               |
+-------------------------------------------------------------------------------------------------------------------------------------------+
4 rows in set (0.00 sec)

各DB/テーブルへの参照権限(GRANT SELECT ON . TO your_user@'%' WITH GRANT OPTION;)にあたる部分がないようです。

該当のユーザはmysqlshからdba.configureLocalInstance()を使って作成したのですが、作成されたユーザには sys.sys_config への参照権限がついていないみたいです。

とりあえず全てのMySQLノードで . への参照権限を付与します。

root@mysql1 > grant select on *.* TO icroot@'%' WITH GRANT OPTION;

root@mysql1 > show grants for icroot@'%';
+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for icroot@%                                                                                                                               |
+---------------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'icroot'@'%' WITH GRANT OPTION |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO 'icroot'@'%' WITH GRANT OPTION                                                               |
| GRANT SELECT ON `sys`.* TO 'icroot'@'%' WITH GRANT OPTION                                                                                         |
| GRANT SELECT ON `performance_schema`.* TO 'icroot'@'%' WITH GRANT OPTION                                                                          |
| GRANT ALL PRIVILEGES ON `mysql_innodb_cluster_metadata`.* TO 'icroot'@'%' WITH GRANT OPTION                                                       |
+---------------------------------------------------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

root@mysql2 > grant select on *.* TO icroot@'%' WITH GRANT OPTION;

root@mysql2 > show grants for icroot@'%';
+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for icroot@%                                                                                                                               |
+---------------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'icroot'@'%' WITH GRANT OPTION |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO 'icroot'@'%' WITH GRANT OPTION                                                               |
| GRANT SELECT ON `sys`.* TO 'icroot'@'%' WITH GRANT OPTION                                                                                         |
| GRANT SELECT ON `performance_schema`.* TO 'icroot'@'%' WITH GRANT OPTION                                                                          |
| GRANT ALL PRIVILEGES ON `mysql_innodb_cluster_metadata`.* TO 'icroot'@'%' WITH GRANT OPTION                                                       |
+---------------------------------------------------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

root@mysql3 > grant select on *.* TO icroot@'%' WITH GRANT OPTION;

root@mysql3 > show grants for icroot@'%';
+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for icroot@%                                                                                                                               |
+---------------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'icroot'@'%' WITH GRANT OPTION |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO 'icroot'@'%' WITH GRANT OPTION                                                               |
| GRANT SELECT ON `sys`.* TO 'icroot'@'%' WITH GRANT OPTION                                                                                         |
| GRANT SELECT ON `performance_schema`.* TO 'icroot'@'%' WITH GRANT OPTION                                                                          |
| GRANT ALL PRIVILEGES ON `mysql_innodb_cluster_metadata`.* TO 'icroot'@'%' WITH GRANT OPTION                                                       |
+---------------------------------------------------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

クラスタ作成を試してみると成功しました。

mysql-js> var cluster = dba.createCluster('devCluster');
A new InnoDB cluster will be created on instance 'icroot@192.168.10.65:3306'.

Creating InnoDB cluster 'devCluster' on 'icroot@192.168.10.65:3306'...
Adding Seed Instance...

Cluster successfully created. Use Cluster.addInstance() to add MySQL instances.
At least 3 instances are needed for the cluster to be able to withstand up to
one server failure.

まとめ

MySQL ShellからMySQL InnoDB Clusterを作ろうとした時に Dba.createCluster: ERROR: 1 table(s) do not have a Primary Key or Primary Key Equivalent (non-null unique key) というエラーが出た事象に関しての調査と対応手順を書きました。 MySQL Shell のエラーメッセージはちょっとわかりづらいです。

参考