FANCOMI Ad-Tech Blog

株式会社ファンコミュニケーションズ nend・新規事業のエンジニア・技術ブログ

MySQL5.6.10をソースからインストールしてGTIDによるマスター切り替えを試す


はじめに

こんにちは nendのインフラ担当してますto_maruyamaです

最近JFL藤枝MYFCに注目してます 齊藤、市川、村瀬、ケルロン(敬称略)が見たい 嗚呼、試合見に行きたい

そんなわけで今回はMYFCならぬMySQL5.6.10 GAのインルトールを行います

ついでにGTIDを使ったマスター切り替えを試してみます

GTID使うとレプリケーションするのにMaster Position見なくていいそうですね ほんとなんだろうなー?

概要

今回やるのはインストールと下図のマスター切り替えです

概要

Oracle社が開催した「MySQL Tech Tour - Japan」の資料のまんまにやろうとしています

資料はここにあるのでご一読を!たとえこの記事をこれ以上読む気がなくてもご一読を!

環境はこんな感じです

【サーバ構成】
サーバ名 役割
master01 MySQLマスター
master02 MySQLサブマスター
slave01 MySQLスレーブ
【サーバ仕様】
項目 内容
OS CentOS release 6.4 (mini丸)
CPU Intel(R) Xeon(R) CPU E5640 @ 2.67GHz(仮想3コア)
メモリ 2GB
ディスク 1TB
MySQL関連】
項目 内容
MySQLインストールディレクトリ /usr/local/mysql
MySQLコンフィグ /etc/my.cnf
MySQLログディレクトリ /usr/local/mysql/var/log

ささ、それでは手順に参りましょう

まずはMySQLをサーバに入れます

MySQLインストール

その前に

  • インストール手順はtarボールの中にあるINSTALL-SOURCEに書いてあります
  • cmakeのオプションは同じくtarボールの中にあるCMakeLists.txtを参考にお好きなものをどうぞ

開発ツールをインストール

[bash gutter="false"] shell> yum groupinstall "Development Tools" shell> yum install cmake [/bash]

ソース置き場に移動

[bash gutter="false"] shell> cd /usr/local/src/ [/bash]

ソースコードを取得

MySQLのサイトからダウンロードしてください

tarボールを解凍

[bash gutter="false"] shell> tar xzvf mysql-5.6.10.tar.gz [/bash]

グループとユーザを作成

[bash gutter="false"] shell> groupadd mysql shell> useradd -g mysql -d /usr/local/mysql mysql [/bash]

権限変更

[bash gutter="false"] shell> chown -R mysql. mysql-5.6.10 [/bash]

移動

[bash gutter="false"]shell> cd mysql-5.6.10[/bash]

ビルド

ビルドにはcmake2.6以上が必要です。

[bash gutter="false"]shell> cmake -V[/bash]

で確認

[shell gutter="false"] shell> cmake . \ -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ -DDEFAULT_SYSCONFDIR=/etc \ -DDEFAULT_CHARSET=utf8 \ -DDEFAULT_COLLATION=utf8_general_ci \ -DWITH_EXTRA_CHARSETS=all \ -DWITH_INNODB_MEMCACHED=ON \ -DWITH_LIBWRAP=ON \ -DWITH_READLINE=ON \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_ARCHIVE_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \ -DWITH_PARTITION_STORAGE_ENGINE=1 [/shell]

コンパイル

[bash gutter="false"]shell> make -j 3[/bash]

※使うコア数は環境に合わせましょう

インストール

[bash gutter="false"]shell> make -j 3 install[/bash]

パスを通す

やり方は自由で

私は/etc/profileにこんな感じで追記しました

[bash gutter="false"]

Path manipulation

if [ "$EUID" = "0" ]; then pathmunge /sbin pathmunge /usr/sbin pathmunge /usr/local/sbin pathmunge /usr/local/mysql/bin else pathmunge /usr/local/sbin after pathmunge /usr/sbin after pathmunge /sbin after pathmunge /usr/local/mysql/bin after fi [/bash]

MySQLのインストールシェルを実行

[bash gutter="false"]shell> scripts/mysql_install_db --user=mysql[/bash]

起動スクリプトを設置

[bash gutter="false"]shell> cp support-files/mysql.server /etc/init.d/mysql[/bash]

MySQLベースディレクトリの権限を設定

[bash gutter="false"]shell> chown -R mysql. /usr/local/mysql[/bash]

/etc/my.cnf(もちろん参考で)

[bash] [client] port = 3306 socket=/var/lib/mysql/mysql.sock default-character-set=utf8

[mysqld] slave_parallel_workers = 3 port = 3306 socket=/var/lib/mysql/mysql.sock skip-external-locking key_buffer = 32M max_allowed_packet = 16M sort_buffer_size = 4M read_buffer_size = 4M read_rnd_buffer_size = 4M join_buffer_size = 8M myisam_sort_buffer_size = 1M max_connections = 200 thread_cache_size = 200 table_open_cache = 1024 table_definition_cache=600 query_cache_type = 1 query_cache_size = 128M query_cache_limit = 4M tmp_table_size = 32M max_heap_table_size = 32M

sync_binlog=1 relay-log=relay-bin relay-log-index=relay-bin binlog-row-image=minimal

server-id = 1

skip_slave_start=1 expire_logs_days=2

gtid-mode=on enforce-gtid-consistency=on log-bin log-bin-index=mysql-bin-index log-slave-updates

innodb_thread_concurrency = 0 innodb_data_home_dir = /usr/local/mysql/data/ innodb_data_file_path = ibdata1:2G innodb_file_per_table innodb_autoextend_increment=100 innodb_log_group_home_dir = /usr/local/mysql/data/ innodb_buffer_pool_size = 1000M innodb_additional_mem_pool_size = 20M innodb_log_file_size = 1G innodb_log_files_in_group=2 innodb_log_buffer_size = 8M innodb_flush_log_at_trx_commit = 2 innodb_support_xa=1 innodb_lock_wait_timeout = 50 innodb_flush_method=O_DIRECT innodb_io_capacity=40000 innodb_read_io_threads=8 innodb_write_io_threads=16 innodb_adaptive_flushing=1

datadir=/usr/local/mysql/data user=mysql skip-character-set-client-handshake character-set-server=utf8 default-storage-engine=InnoDB collation-server = utf8_bin init-connect = SET NAMES utf8

long_query_time=5 log-slow-admin-statements

slow_query_log=ON slow_query_log_file=/usr/local/mysql/var/log/mysql-slow.log

skip-name-resolve

[mysqldump] quick max_allowed_packet = 16M default-character-set=utf8

[mysql] no-auto-rehash default-character-set=utf8

[isamchk] key_buffer = 256M sort_buffer_size = 256M read_buffer = 2M write_buffer = 2M

[myisamchk] key_buffer = 256M sort_buffer_size = 256M read_buffer = 2M write_buffer = 2M

[mysqlhotcopy] interactive-timeout

[mysqld_safe] log-error=/usr/local/mysql/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid

[mysql.server] basedir=/usr/local/mysql [/bash]

【5.6で追加されたパラメタ】
パラメタ名 役割
slave_parallel_workers スレーブで起動するSQLスレッド数を指定
binlog-row-image=minimal 変更された行イメージだけを保持
gtid-mode=on GTIDモードを有効にする
enforce-gtid-consistency=on 非トランザクションテーブルを更新し、単一のステートメントを許可する(って書いてあった

下2つがGTID使う場合必須です

MySQL起動

[bash gutter="false"]shell> /etc/init.d/mysql start[/bash]

rootユーザのパスなどを設定するスクリプトを実行

[bash gutter="false"]shell> mysql_secure_installation[/bash]

[bash gutter="false"] 「ERROR 1372 (HY000) at line 1: Password hash should be a 41-digit hexadecimal number」 [/bash]

な人はmy.cnfにold_passwords=1が入っているかもしれないのでコメントアウトしてmysqlを再起動してください 旧バージョンからアップグレードの人はmysql_upgrade必要かも

自動起動の設定

[bash gutter="false"] shell> chkconfig --add mysql shell> chkconfig mysql on [/bash]

レプリケーション用のユーザを作成

面倒なので3つのサーバ間なら誰がどこからでもレプリケーションできるようにします

[bash gutter="false"] mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO <USER>@'master01' IDENTIFIED BY '<PASSWORD>'; mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO <USER>@'master02' IDENTIFIED BY '<PASSWORD>'; mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO <USER>@'slave01' IDENTIFIED BY '<PASSWORD>'; mysql> FLUSH PRIVILEGES; [/bash]

レプリケーション環境の構築

ここまでやったらmaster01のスナップショットからmaster02とslave01を複製しました

コピーしたらこれはやっといてね

  • /etc/my.cnfのserver-idを変更
  • /usr/local/mysql/data/auto.cnfのserver-uuid行を削除
  • mysql再起動

でないとサーバがユニークにならんのさ

さて、それではレプリケーションをはじめましょう

[bash gutter="false"] mysql> CHANGE MASTER TO MASTER_HOST = 'master01', MASTER_PORT = 3306, MASTER_USER = '<USER>', MASTER_PASSWORD ='<PASSWORD>', MASTER_AUTO_POSITION = 1; mysql> START SLAVE; [/bash]

状態を確認 うまくいったかなー

[bash gutter="false"] mysql> SHOW SLAVE STATUS\G

Slave_IO_Running: Yes Slave_SQL_Running: Yes [/bash]

うん、いい感じ

SHOW SLAVE STATUSのパラメタ的にはこのあたりが5.6から追加になっている部分ですね

[bash gutter="false"] Master_UUID: e1eedd5d-9182-11e2-b260-36d7966a4f4e Retrieved_Gtid_Set: e1eedd5d-9182-11e2-b260-36d7966a4f4e:299-313 Executed_Gtid_Set: 2c92dbad-920f-11e2-b5f4-32cc6aab1d8f:1-2, e1eedd5d-9182-11e2-b260-36d7966a4f4e:1-313 [/bash]

Oracle様の資料を読んでいない悪い子のためにGTID補足

[bash gutter="false"]e1eedd5d-9182-11e2-b260-36d7966a4f4e:1-313

「:」をデリミタにして e1eedd5d-9182-11e2-b260-36d7966a4f4e = master01のUUID 1-313 = 実行したトランザクションのID [/bash]

さて、ではmaster01でSQLを一発

[bash gutter="false"]mysql> CREATE DATABASE repl_test;[/bash]

GTIDはどうなったかな

[bash gutter="false"] mysql> SELECT @@global.gtid_executed; +--------------------------------------------+ | @@global.gtid_executed | +--------------------------------------------+ | e1eedd5d-9182-11e2-b260-36d7966a4f4e:1-314 | +--------------------------------------------+ [/bash]

インクリメントしてますね

そんじゃmaster02でも確認しましょう まずはGTIDから

[bash gutter="false"] mysql> SELECT @@global.gtid_executed; +--------------------------------------------------------------------------------------+ | @@global.gtid_executed | +--------------------------------------------------------------------------------------+ | 2c92dbad-920f-11e2-b5f4-32cc6aab1d8f:1-2, | | e1eedd5d-9182-11e2-b260-36d7966a4f4e:1-314 | +--------------------------------------------------------------------------------------+ [/bash]

うむうむ、master01のID314のトランザクションが流れてきてますね さて、DBはできてるかな

[bash gutter="false"] mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | repl_test | +--------------------+ [/bash]

苦しゅうない

ここまで確認できたらslave01もmaster01からレプリケーションするようにしてあげましょう

できたかな

ここまででこんな構成になってるはず

現在の構成

さぁ次はmaster01に障害があった体でslave01のマスターをmaster01からmaster02にスイッチします

シナリオはこんな感じ

  1. master01がダウン
  2. master02へ更新が向く
  3. masterを失ったslave01は更新データがもらえず途方にくれる
  4. そこに通りすがりのエンジニアが手動でCHANGE MASTERしてくれる
  5. slave01はmaster02から更新データを取得し最新に保たれる

ではやってみます

1.master01を停止する

IOスレッドが切れたことを確認

● master02

[bash gutter="false"] mysql> show slave status\G Slave_IO_State: Reconnecting after a failed master event read Slave_IO_Running: Connecting Slave_SQL_Running: Yes [/bash]

● slave01

[bash gutter="false"] mysql> show slave status\G Slave_IO_State: Reconnecting after a failed master event read Slave_IO_Running: Connecting Slave_SQL_Running: Yes [/bash]

マスターへ接続ができなくなったのでmaster02とslave01のスレッドを止めます

[bash gutter="false"]mysql> STOP SLAVE;[/bash]

2.master02のデータを更新します

テーブル作成

[bash gutter="false"]mysql> USE repl_test; mysql> CREATE TABLE switch ( -> id integer PRIMARY KEY AUTO_INCREMENT, -> value integer NOT NULL); [/bash]

DB削除

[bash gutter="false"]mysql> DROP DATABASE repl_test;[/bash]

別のDBとテーブルを作成

[bash gutter="false"]mysql> CREATE DATABASE repl_test2;[/bash] [bash gutter="false"]mysql> USE repl_test2;[/bash] [bash gutter="false"] mysql> CREATE TABLE switch2 ( -> id integer PRIMARY KEY AUTO_INCREMENT, -> value integer NOT NULL); [/bash]

レコード追加

[bash gutter="false"]mysql> INSERT INTO switch2(value) VALUES(777);[/bash] [bash gutter="false"] mysql> SHOW MASTER STATUS\G File: master02-bin.000008 Position: 1466 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: 2c92dbad-920f-11e2-b5f4-32cc6aab1d8f:1-7, e1eedd5d-9182-11e2-b260-36d7966a4f4e:1-314 [/bash]

3.slave01のマスターをmaster01からmaster02へスイッチ

[bash gutter="false"] mysql> CHANGE MASTER TO MASTER_HOST = 'master02', -> MASTER_PORT = 3306, -> MASTER_USER = '<USER>', -> MASTER_PASSWORD ='<PASSWORD>', -> MASTER_AUTO_POSITION = 1; mysql> START SLAVE; [/bash]

レプリケーションの状態を確認

[bash gutter="false"] mysql> SHOW SLAVE STATUS\G Slave_IO_Running: Yes Slave_SQL_Running: Yes Master_UUID: 2c92dbad-920f-11e2-b5f4-32cc6aab1d8f Retrieved_Gtid_Set: 2c92dbad-920f-11e2-b5f4-32cc6aab1d8f:3-7 Executed_Gtid_Set: 2c92dbad-920f-11e2-b5f4-32cc6aab1d8f:1-7, e1eedd5d-9182-11e2-b260-36d7966a4f4e:1-314 [/bash]

復習

[bash gutter="false"] 2c92dbad-920f-11e2-b5f4-32cc6aab1d8f:1-7

「:」をデリミタにして 2c92dbad-920f-11e2-b5f4-32cc6aab1d8f = master02のUUID 1-7 = さっき実行したトランザクション [/bash]

ちゃんとレプリケートされたようですね

ではデータも確認しましょう

[bash gutter="false"] mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | repl_test2 | +--------------------+ [/bash] [bash gutter="false"] mysql> USE repl_test2; mysql> SELECT * FROM switch2; +----+-------+ | id | value | +----+-------+ | 1 | 777 | +----+-------+ [/bash]

以上!

まとめ

● インストール

・基本的には5.5と変わらず ・my.cnfの新しいパラメタ

● GTIDによるマスター切り替え

slave01のマスターをmaster01からmaster02にスイッチする場合 従来のPositionを利用したレプリケーションだと slave01がmaster01のどのPositionまでトランザクションを実行していて そのPositionがmaster02のどのPositionにあたるのかを調べたうえで Positionを指定してCHANGE MASTERをする必要がありました(ああ、ややこしい)

GTIDの場合、「MASTER_AUTO_POSITION = 1」を設定するだけで 簡単にマスターのスイッチができるんですね

これはスレーブがmaster:rangeを表すIDを持っている つまり、どのマスターのどのトランザクションまで実行したかを知っているから のようですが、詳細は次回以降で調査していこうと思います

次回

次回はGTIDの突っ込んだ話と、MySQL WorkbenchのMySQL Utilitiesを使って遊んでみます

今回はあえてMySQL Workbenchが間に合わなくて手動で行った作業がたくさんあります MySQL Workbenchには自動化ツールがごっさ入っているので 次回以降はそれを使って処理を華麗に自動化していきます

それではまた次回!

編集後記

5.6のパスワード桁数制限にハマってぐぐってたら下の記事を読むことになった

http://dev.mysql.com/doc/refman/5.1/ja/password-hashing.html

MySQL 4.1 (4.1.1 を含む 4.1 シリーズ) から MySQL 5.1 へのアップグレードでは、パスワード ハッシュ メカニズムが同一であるため、このアップグレードでは、ここに挙げるパスワード ハッシュに関する問題は発生しません。これ以外のアップグレード、たとえば、MySQL 4.1 よりも古いバージョンから 5.1 にする場合は、まず、MySQL 4.1 へアップグレードしてから、 5.1 へのアップグレード (インルトール) を行ないます。

インルトール≒インストールw