:>/dev/null

ラガードエンジニアの不撓不屈の精神/unlearning/go beyond

MySQL+groonga+mroonga移行手順(バージョンアップ)

前回の記事( MySQL+groonga+mroonga構築手順 - :>/dev/null )でレガシーシステムを検証したが、その環境を現時点(2019/07/18)の最新Versionにアップデートする必要があり作業記録メモを残す。
レガシーシステムではMySQLからgroongaをストレージエンジンとして利用する場合、mroonga plugin(MySQL組込)を使用せず直接利用する構成だが、
groongaがv3.04からmysql経由で直接使用するのを停止しmroonga経由で使用する方式に統一された為、バージョンアップ環境ではmroonga経由の構成で調査。

  • 以下構築要件
    • OS:CentOS7.6 x86_84
    • MySQL:5.7.26
    • groonga:9.0.4
    • mroonga:9.0.4

◎ 環境構築

■ インストール&設定

関連パッケージインストール

# yum install wget tar gcc-c++ make mecab-devel mysql-community-devel

mysqlインストール

# yum remove mariadb-libs ← 標準インストールされてるライブラリとの依存関係でエラーが発生する為、先行して既存ライブラリ削除
# rpm -Uvh http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
# yum info mysql-community-server ← レポジトリの対象Version確認
# yum install mysql-community-server

初期設定

# systemctl start mysqld

初期パスワード確認

# cat /var/log/mysqld.log | grep password

初期化

# mysql_secure_installation


Securing the MySQL server deployment.

Enter password for user root: [初期パスワード]

The existing password for the user account root has expired. Please set a new password.

New password: [新しいパスワード]

Re-enter new password: [もう一度新しいパスワード]
The 'validate_password' component is installed on the server.
The subsequent steps will run with the existing configuration
of the component.
Using existing password for root.

Estimated strength of the password: 100 
Change the password for root ? ((Press y|Y for Yes, any other key for No) : y

New password: [新しいパスワード]

Re-enter new password: [もう一度新しいパスワード]

Estimated strength of the password: 100 
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!

/etc/my.cnf作成

# vi /etc/my.cnf

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

# defaultではポリシーが厳しい基準の為、テスト用にパスワードポリシー変更
validate_password_length=4
validate_password_policy=LOW

## Replication 用設定
# 各MySQLサーバを識別するためのIDの設定
server-id=101

# バイナリログの有効化
log_bin=mysql-bin

# バイナリログをコミットと同時にディスクに書込む
sync_binlog=1

mysql再起動

# systemctl restart mysqld

自動起動設定

# systemctl enable mysqld
◆ パッケージインストールの場合

groonga

# yum install https://packages.groonga.org/centos/groonga-release-latest.noarch.rpm
# yum install --enablerepo=epel groonga

mroonga

# wget https://packages.groonga.org/centos/groonga-release-1.4.0-1.noarch.rpm
# rpm -ivh groonga-release-1.4.0-1.noarch.rpm
# yum install --enablerepo=epel mysql57-community-mroonga
◆ ソースインストールの場合

groonga

# wget https://packages.groonga.org/source/groonga/groonga-9.0.4.tar.gz
# tar zxvf groonga-9.0.4.tar.gz
# cd groonga-9.0.4/
# ./configure
# make -j$(grep '^processor' /proc/cpuinfo | wc -l)
# make install

mysql

# wget https://fossies.org/linux/misc/mysql-5.7.26.tar.gz
# tar zxvf mysql-5.7.26.tar.gz
# cmake . \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DMYSQL_TCP_PORT=3306 \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DDEFAULT_CHARSET=utf8 \
-DWITH_EXTRA_CHARSETS=all \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
-DDOWNLOAD_BOOST=1 \
-DWITH_BOOST=/tmp

・ソースコンパイルに必要なパッケージ/ライブラリをインストール

# yum install wget gcc-c++ cmake ncurses-devel zlib-devel readline-devel bison
# wget  http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz

※頻繁に下記エラーが発生する為、事前にライブラリをダウンロード

-- LOCAL_BOOST_DIR -- LOCAL_BOOST_ZIP -- Could not find (the correct version of) boost. -- MySQL currently requires boost_1_59_0 CMake Error at cmake/boost.cmake:81 (MESSAGE): You can download it with -DDOWNLOAD_BOOST=1 -DWITH_BOOST= This CMake script will look for boost in . If it is not there, it will download and unpack it (in that directory) for you. If you are inside a firewall, you may need to use an http proxy: export http_proxy=http://example.com:80 Call Stack (most recent call first): cmake/boost.cmake:238 (COULD_NOT_FIND_BOOST) CMakeLists.txt:508 (INCLUDE) -- Configuring incomplete, errors occurred! See also "/tmp/mysql-5.7.26/CMakeFiles/CMakeOutput.log". See also "/tmp/mysql-5.7.26/CMakeFiles/CMakeError.log".

ref)
https://www.eastforest.jp/mysql/3521

mroonga

# wget https://packages.groonga.org/source/mroonga/mroonga-9.04.tar.gz
# tar zxvf mroonga-9.04.tar.gz
# cd mroonga-9.04/
# ./configure PKG_CONFIG_PATH=/tmp/groonga-9.0.4/ --with-mysql-source=/tmp/mysql-5.7.26-el7-x86_64 --with-mysql-build=/tmp/mysql-5.7.26-el7-x86_64 --with-mysql-config=/usr/bin/mysql_config
# make
# make install
# mysql -uroot -p < /usr/local/share/mroonga/install.sql

※configureオプション
--with-mysql-source:MySQLソースコードディレクトリーを指定
--with-mysql-build:MySQLのビルドディレクトリーを指定
--with-mysql-config:mysql_configコマンドのパスを指定

SHOW ENGINES SQLを実行することでMroongaが正常にインストールされているかを確認。Mroongaという行があれば正常にインストール済み。

mysql> SHOW ENGINES;  
+------------+---------+-----------------------------------------+--------------+------+------------+
| Engine     | Support | Comment                                 | Transactions | XA   | Savepoints |
+------------+---------+-----------------------------------------+--------------+------+------------+
...snip...
| Mroonga    | YES     | Fulltext search, column base            | NO           | NO   | NO         |
...snip...
+------------+---------+-----------------------------------------+--------------+------+------------+

ref)
https://gitter.im/groonga/ja
https://yoku0825.blogspot.com/2015/12/mysql-55mysql-57.html

◆ 動作確認

database作成

mysql> CREATE DATABASE db1 DEFAULT CHARACTER SET ujis COLLATE ujis_japanese_ci;

table作成

mysql> create table t1 (c1 int primary key, c2 varchar(255), c3 text, fulltext index(c2), fulltext index(c3)) ENGINE = mroonga DEFAULT CHARSET ujis;

サンプルデータ作成&確認

mysql> insert into t1 values(1, "明日の富士山の天気について","東京");
mysql> insert into t1 values(2, "天気予報","明日の富士山の天気は分かりません");
mysql> insert into t1 values(3, "dummy", "dummy");

mysql> select * from t1 where match(c2) against("富士山");
+-----+-----------------------------------------+-----------------------+
| c1    | c2                                                    | c3                            |
+-----+-----------------------------------------+-----------------------+
|  1     |  明日の富士山の天気について          | 東京                         |
+-----+-----------------------------------------+-----------------------+

■ Replication

Masterノード作業

Replicationユーザー作成&確認

mysql> GRANT REPLICATION SLAVE ON *.* TO repl@xxx.xxx.xxx.xxx IDENTIFIED BY '******';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> SELECT user,host FROM mysql.user;
+---------------+---------------+
| user          | host          |
+---------------+---------------+
| repl          | xxx.xxx.xxx.xxx |
+---------------+---------------+

dump中にDBが更新されないようにテーブルの書き込みロック

mysql> flush tables with read lock;

現在のバイナリログの状態を確認する

mysql> show master status;
+------------------+----------+--------------+------------------+----------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                      |
+------------------+----------+--------------+------------------+----------------------------------------+
| mysql-bin.000002 |      194 |              |                  |       |
+------------------+----------+--------------+------------------+----------------------------------------+

データタンプ

# mysqldump -u root -p \
--single-transaction \
--flush-logs \
--master-data=2 \
--all-databases \
--hex-blob \
--triggers \
--routines \
--events > /tmp/master_db.sql

テーブルロックを解除

mysql> unlock tables;

Masterノード → Slaveノードへデータ転送

# scp -i ~/.ssh/private.pem /tmp/master_db.sql xxx.xxx.xxx.xxx:/tmp/
Slaveノード作業

/etc/my.cnf作成

## Replication 用設定
# 各MySQLサーバを識別するためのIDの設定
server-id=102

# 更新を禁止する
read_only

# スレーブSQLスレッドによって実行される更新をバイナリログに書き込む
log_slave_updates

# リレーログファイルの名前
relay_log=mysql-relay-bin

# クラッシュセーフなレプリケーション設定
relay_log_info_repository=TABLE
relay_log_recovery=ON
relay_log_purge=ON

mysql再起動

# systemctl restart mysqld

Masterノードのデータリストア

# mysql -uroot -p
 
mysql> CREATE DATABASE db1 DEFAULT CHARACTER SET ujis COLLATE ujis_japanese_ci;
mysql> use db1;
mysql> source /tmp/master_db.sql;

SlaveノードのReplication設定
(Slaveノード → Masterノードへ接続するためのパラメータ設定)

# mysql -uroot -p
 
mysql> change master to
    -> master_host='xxx.xxx.xxx.xxx',
    -> master_user='repl',
    -> master_password='******',
    -> master_log_file='mysql-bin.000002',
    -> master_log_pos=194;

Replication対象DBとして設定

mysql> change replication filter replicate_do_db = (db1);

※Replication対象DBから 削除する場合
(フィルターを消すには、フィルター名をreplicate-do-db構文から削除する必要があり)

mysql> show slave status\G
...snip...
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: db1
          Replicate_Ignore_DB:
...snip...

mysql> change replication filter replicate_do_db = (); ← slave未停止の場合、エラーで弾かれる
ERROR 3017 (HY000): This operation cannot be performed with a running slave sql thread; run STOP SLAVE SQL_THREAD first

mysql> stop slave;
mysql> change replication filter replicate_do_db = ();
mysql> start slave;

mysql> show slave status \G;
...snip...
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
...snip...

Replication開始

mysql> start slave;

Replicationステータス確認

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: xxx.xxx.xxx.xxx
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 194
               Relay_Log_File: 157x112x83x169-relay-bin.000005
                Relay_Log_Pos: 367
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: db1
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 194
              Relay_Log_Space: 796
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 101
                  Master_UUID: 361e5307-a2e4-11e9-8318-0050568ca249
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:

ステータス結果
「Slave_IO_Running」と「Slave_SQL_Running」がともに「Yes」となっていれば、レプリケーション設定完了。
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
上記正常稼働後、更新系のSQLをMasterノードで実行し変更内容がSlaveに伝播する事を確認。

◎ バージョンアップ環境設定

■ バージョンアップ(データ移行)手順

バージョンアップ環境のmy.cnfファイル生成

現構成のコピーベースですがmysql5.7へアップデートした為、一部パラメータ名変更の発生に伴い設定調整。

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
 
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
 
server-id=101
log_bin=mysql-bin
 
port = 3306
#skip-locking  ← 旧パラメータ(廃止)
skip-external-locking
skip-character-set-client-handshake
skip-name-resolve
back_log = 100
#old_passwords  ← 旧パラメータ(廃止)
key_buffer_size=64M
max_allowed_packet = 16M
max_connect_errors = 100000
max_connections = 8192
#table_cache = 2048  ← 旧パラメータ(廃止)
table_open_cache = 2048
sort_buffer_size = 64M
join_buffer_size = 2M
net_buffer_length = 1M
read_buffer_size = 2M
read_rnd_buffer_size = 2M
query_cache_limit=16M
query_cache_size=1024M
query_cache_type=2
#thread_cache=512  ← 旧パラメータ(廃止)
thread_cache_size=512
net_read_timeout=3600
connect_timeout=60
wait_timeout=300
open-files-limit=1000
character-set-server=ujis
tmpdir = /tmp/
 #default-storage-engine = groonga  ← 旧パラメータ(廃止)
default-storage-engine = mroonga

[client]
port = 3306
socket=/var/lib/mysql/mysql.sock
default-character-set=ujis
 
[mysqldump]
quick
max_allowed_packet = 16M
 
[mysql]
no-auto-rehash
default-character-set=ujis
 
[mysqlhotcopy]
interactive-timeout

現構成からダンプ(現環境(mysql5.1.60)の作業)

mysqlの登録済みユーザー移行準備

登録済みユーザー確認

# mysql -uroot -p
mysql> use mysql;
mysql> select user, host from user\g;
+---------------+---------------+
| user          | host          |
+---------------+---------------+
| admin         | localhost     |
| mysql.session | localhost     |
| mysql.sys     | localhost     |
| root          | localhost     |
+---------------+---------------+

登録済みユーザー権限確認 移行対象ユーザーの現構成を確認。下記adminユーザーの例。

mysql> show grants for admin@localhost;
+-------------------------------------------------------------------------------------+
| Grants for admin@localhost                                                          |
+-------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'admin'@'localhost' IDENTIFIED BY PASSWORD '****************' |
| GRANT ALL PRIVILEGES ON `db1`.* TO 'admin'@'localhost'                              |
+-------------------------------------------------------------------------------------+

ユーザー登録に関して
バージョンアップ環境でユーザー登録が必要な為、現環境のユーザー名/権限を確認し、バージョンアップ環境で手動登録する必要がある。

old_passwordsに関して
MySQL 5.7.5移行からold_passwordsが利用できなくなり、完全に古いパスワードでログイン不可。
アップグレード前に予めold_passwordsを解除した上で、ハッシュが短いユーザーのパスワードを再設定する事で解決する必要がある。

アプリケーションデータ

dump中にDBが更新されないようにテーブルの書き込みロック

mysql> flush tables with read lock;

テーブルスキーマ

$ mysqldump -uroot -p -c --add-drop-table=0 --skip-comments --default-character-set=ujis --order-by-primary --skip-extended-insert -d -B db1 > mysql51-s.sql

テーブルデー

$ mysqldump -uroot -p -c --add-drop-table=0 --skip-comments --default-character-set=ujis --order-by-primary --skip-extended-insert -t -B db1 > mysql51-d.sql

テーブルロックを解除

mysql> unlock tables;
デフォルトストレージエンジンをgroonga → mroongaへ変換
$ sed -e 's/ENGINE=groong/ENGINE=mroong/g' mysql51-s.sql
バージョンアップ環境へファイル転送
$ scp -i ~/.ssh/private.pem /tmp/mysql51-* xxx.xxx.xxx.xxx:/tmp/

バージョンアップ環境へリストア(バージョンアップ環境(mysql5.7.26)の作業)

mysqlのユーザー移行

登録済みユーザー確認

mysql> use mysql;
mysql> select user, host from user\g;
+---------------+---------------+
| user          | host          |
+---------------+---------------+
| admin         | localhost     |
| mysql.session | localhost     |
| mysql.sys     | localhost     |
| root          | localhost     |
+---------------+---------------+
現環境(移行)ユーザー登録

移行対象ユーザーの登録。下記adminユーザーの例。

mysql> grant ALL PRIVILEGES ON db1.* TO 'admin'@'localhost' IDENTIFIED BY '*******';
登録済みユーザー権限確認
mysql> show grants for admin@localhost;
+--------------------------------------------------------+
| Grants for admin@localhost                             |
+--------------------------------------------------------+
| GRANT USAGE ON *.* TO 'admin'@'localhost'              |
| GRANT ALL PRIVILEGES ON `db1`.* TO 'admin'@'localhost' |
+--------------------------------------------------------+

ユーザー権限に関して
現環境とバージョンアップ環境でユーザー登録/権限が同様に設定されている事を確認する必要がある。

アプリケーションデータ移行

テーブルスキーマ

# mysql -u root -p --default-character-set=ujis db1 < /tmp/mysql51-s.sql

テーブルデー

# mysql -u root -p --default-character-set=ujis db1 < /tmp/mysql51-d.sql

動作確認

・テーブルスキーマ

リストア後のテーブルスキーマ定義を確認。

mysql> use db1;
mysql> show create table t1 \G;
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `c1` int(11) NOT NULL,
  `c2` varchar(255) DEFAULT NULL,
  `c3` text,
  PRIMARY KEY (`c1`),
  FULLTEXT KEY `c2` (`c2`),
  FULLTEXT KEY `c3` (`c3`)
) ENGINE=Mroonga DEFAULT CHARSET=ujis

ステータス結果
対象テーブルのスキーマ定義に下記が設定されてる事を確認。
ENGINE=Mroonga
DEFAULT CHARSET=ujis

テーブルデー

現環境とバージョンアップ環境で全文検索SQLを発行した場合、同じ結果が表示される事を確認。

# 現環境
mysql> select * from t1 where match(c2) against("富士山");
+-----+-----------------------------------------+-----------------------+
| c1    | c2                                                    | c3                            |
+-----+-----------------------------------------+-----------------------+
|  1     |  明日の富士山の天気について          | 東京                         |
+-----+-----------------------------------------+-----------------------+
 
 
# バージョンアップ環境
mysql> select * from t1 where match(c2) against("富士山");
+-----+-----------------------------------------+-----------------------+
| c1    | c2                                                    | c3                            |
+-----+-----------------------------------------+-----------------------+
|  1     |  明日の富士山の天気について          | 東京                         |
+-----+-----------------------------------------+-----------------------+

ステータス結果
現環境とバージョンアップ環境で同様の結果が表示される事が出来れば、バージョンアップ(データ移行)完了。