Masterがこけると、当然Slaveのデータも更新されない。
- Slaveにログインして
stop slave;
で、SLAVE状態を止める。
- IPアドレスをMasterのものに付け替える。
vi /etc/sysconfig/network-scripts/ifcfg-eth0 IPADDR=***.***.***.***
を書き換え。
/etc/init.d/network restart
で、ネットワークの再起動。
たぶんこれだけ。
Masterがこけると、当然Slaveのデータも更新されない。
stop slave;
で、SLAVE状態を止める。
vi /etc/sysconfig/network-scripts/ifcfg-eth0 IPADDR=***.***.***.***
を書き換え。
/etc/init.d/network restart
で、ネットワークの再起動。
たぶんこれだけ。
クエリが帰って来ないなーという時は、今何やってるのか見てみる。
mysql -u **** -p
Enter password:
でログインして
show processlist;
すると今現在稼働しているプロセスリストを表示してくれる。
+----------+------+-------------------+------+-------------+-------+----------------------------------------------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----------+------+-------------------+------+-------------+-------+----------------------------------------------------------------+------------------+ | 37853901 | repl | 10.10.10.10:56317 | NULL | Binlog Dump | 23241 | Has sent all binlog to slave; waiting for binlog to be updated | NULL | | 37853903 | repl | 10.10.10.11:44864 | NULL | Binlog Dump | 23238 | Has sent all binlog to slave; waiting for binlog to be updated | NULL | | 38092482 | root | localhost | NULL | Query | 0 | NULL | show processlist | +----------+------+-------------------+------+-------------+-------+----------------------------------------------------------------+------------------+
こんななら問題なし?
ココに
+----------+------+-------------------+----------+---------+-------+----------------------+-----------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----------+------+-------------------+----------+---------+-------+----------------------+-----------------------------------------------+ | 38081655 | root | 10.10.10.12:34775 | hogehoge | Query | 728 | Copying to tmp table | SELECT `hoge` FROM table WHERE `hoge` = null | | 38081656 | root | 10.10.10.12:34776 | hogehoge | Sleep | 728 | | NULL | +----------+------+-------------------+----------+---------+-------+----------------------+-----------------------------------------------+
って「Copying to tmp table」があったら、そりゃ遅い。メモリ上で処理できなくてディスクに書き出してるってことなので。
ちなみにTimeに728って書いてあるってことは既に12分08秒経過してる。
どうしようもないのでこのプロセスにはいなくなってもらうことにする。
kill 38081655
でいなくなってもらう。
テーブルの構造変更やデータ変更する前にバックアップしておかないと、壊しちゃったとき大変。
なのでテーブルを複製しておく。
同じ構造のテーブルを作成する。
create table data_backup like data_original;
で、このテーブルに現在あるデータを全部流し込む。
insert into data_backup select * from data_original;
これでテーブル単位でのバックアップ完了。
作ったらバックアップで作業したり更新したりテストしたり出来る。
mysql> show variables like 'char%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 8 rows in set (0.00 sec)
このようになっていたりして予期しないところで化けちゃったりなんだったり。
vi /etc/my.cnf
に以下のものを追加します。
[mysqld] character-set-server = utf8 default-character-set = utf8 init_connect='SET NAMES utf8' [client] default-character-set = utf8
変更したらMySQLを再起動。
mysql> show variables like 'char%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 8 rows in set (0.00 sec) mysql> show variables like 'collation_%'; +----------------------+-----------------+ | Variable_name | Value | +----------------------+-----------------+ | collation_connection | utf8_general_ci | | collation_database | utf8_general_ci | | collation_server | utf8_general_ci | +----------------------+-----------------+ 3 rows in set (0.00 sec)
この形でOK。
みんなが書いていることだけどgrantを思い出せなかったので、自分でも書いておく。
はじめに書く呪文は
grant all privileges on *.* to username identified by 'password' with grant option;
です。
usernameはroot@localhostでもroot@111.222.333.444でも。
これで入れなかったらまず、
flush privileges;
でユーザテーブルをリフレッシュしてみること。
それでも入れなかったら原因を考えてみる。
MySQLの落とすときに
120210 20:36:36 [Note] /usr/libexec/mysqld: Normal shutdown 120210 20:36:38 [Warning] /usr/libexec/mysqld: Forcing close of thread 554 user:'' ・・・・・・スレッドの数が1ずつ減っていく 120210 20:36:38 [Warning] /usr/libexec/mysqld: Forcing close of thread 54 user: '' 120210 20:39:51 InnoDB: Starting shutdown... 120210 20:39:52 InnoDB: Shutdown completed; log sequence number 0 1206809921 120210 20:39:52 [Note] /usr/libexec/mysqld: Shutdown complete
ってカンジで
[Warning] /usr/libexec/mysqld: Forcing close of thread *** user:''
がたくさんある。
なんじゃらほい?
show processlist
で確認すると
unauthenticated user
がいっぱい溜まってToo Many Connectionsになっちゃってる場合。
skip-name-resolve
を my.cnf の[mysqld]の中に書いてあげるといいらしい。
いざって時にはすでに mysql 自体がハングっちゃって「show processlist」すら出来ない場合もあるだろうから、
名前解決する必要がないってわかっている場合は事前に書いておいても問題ないかと思う。
その前に
max_connections thread_cache wait_time
辺りを見直すのも吉。
レプリケーションの作り方について。
MySQL レプリケーションの設定 – とみぞーノートさま
現場指向のレプリケーション詳説 – IRORI.ORGさま
と、参考になるところはいっぱいあるのだが、自分で書かないと覚えられないたちなので仕方がない。
MySQLのドキュメントだと5.1.1. レプリケーションのセットアップ方法とか12.6. 複製ステートメントとかの辺り。
要はMasterで発行されたSQLをSlaveでもそのまま実行するということ。
とりあえず作り方。
[mysqld] log-bin=mysql-bin server-id=168001012
「log-bin」はバイナリログを取っておく、という指定。
「server-id」は適当にSlaveとかぶらないものを指定する。
required unique id between 1 and 2^32 – 1
ということなので、1 から 4,294,967,295 の範囲内で。
今回はサーバのIPアドレス、下3つを採用。
mysql -u root -p
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.13' IDENTIFIED BY 'slave_password';
「repl」はユーザー名。ほかの用途に使わないようなものを指定する。
「192.168.1.13」はSlave側のアドレス。
Slaveが複数ある場合には「192.168.1.0/255.255.255.0」とかのほうがいいかも。
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.0/255.255.255.0' IDENTIFIED BY 'slave_password';
こんなカンジで。
mysql> FLUSH TABLES WITH READ LOCK;
この状態だと読み込みはOKということになる。
mysqldump -u root -p --all-databases --add-drop-database --add-drop-table -x >> /tmp/sqldump_20120807.sql
個別のデータベースのDUMPを出力する場合は以下のようにする
–databases [db_name] → [db_name] で指定したデータベースのみDumpする。
mysqldump -u root -p --databases db_name --add-drop-database --add-drop-table -x >> /tmp/sqldump_20120807_db_name_only.sql
mysqldumpが使えない時は「/var/lib/mysql」配下をすべてtarで固める。
tar -cpf /var/tmp/mysql.tar /var/lib/mysql
mysql > SHOW MASTER STATUS; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000024 | 49005253 | test | manual,mysql | +------------------+----------+--------------+------------------+
scp -Cqp /tmp/mysqldump_20120807.sql root@192.168.1.13:/tmp/mysqldump_20120807.sql
scp -Cqp /var/tmp/mysql.tar root@192.168.1.13:/var/tmp/mysql.tar
mysql> UNLOCK TABLES;
[mysqld] log-bin=mysql-bin server-id=168001013
「log-bin」はSlaveのみであれば特に必要ないが、
binary logging – not required for slaves, but recommended
という記述があるので、一応つけておく。
Masterがコケた時、このSlaveがMasterになる可能性があるなら付けておく。
「server-id」はMasterとかぶらないものを指定する。
mysql -u root -p < /tmp/sqldump_20120807.sql
cd /var/lib/mysql rm -fr * tar xpf /var/tmp/mysql.tar
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.12', MASTER_USER='repl', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000024', MASTER_LOG_POS=49005253;
いきおい余って MASTER_LOG_POS の数値を「’」で囲まないように。
文字列として認識されてハマります。
実際に小1時間ハマりました。。。
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS;
Slave_IO_Running と、 Slave_SQL_Running が両方ともYesになっていることを確認。
Seconds_Behind_Master が0であれば、マスターに対する遅延も発生していない、ということになる、はず。
ここまでで Master <-> Slave の構築はできたかな?と。
まず、ログファイル作成。
touch /var/log/mysql/query.log chmod 660 /var/log/mysql/query.log chown mysql:mysql /var/log/mysql/query.log
次にmy.cnfの修正。
[mysqld] log = /var/log/mysql/query.log
ここまでできたらMySQLの再起動。
service mysql restart
以上です。
元ネタはココ。
CREATE FUNCTION levenshtein( s1 VARCHAR(255), s2 VARCHAR(255) ) RETURNS INT DETERMINISTIC BEGIN DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT; DECLARE s1_char CHAR; -- max strlen=255 DECLARE cv0, cv1 VARBINARY(256); SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0; IF s1 = s2 THEN RETURN 0; ELSEIF s1_len = 0 THEN RETURN s2_len; ELSEIF s2_len = 0 THEN RETURN s1_len; ELSE WHILE j c_temp THEN SET c = c_temp; END IF; SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1; IF c > c_temp THEN SET c = c_temp; END IF; SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1; END WHILE; SET cv1 = cv0, i = i + 1; END WHILE; END IF; RETURN c; END;
この関数を該当DB上に作成して、
SELECT place, levenshtein(place, 'スターバックス') AS distance FROM main_data ORDER BY distance ASC LIMIT 10;
みたいなクエリでアクセスするとレーベンシュタイン距離が返ってくる。
DBにはMySQLが使われているわけですが、
WP-DBManagerはそのDBのdumpを定期的に書き出してくれる。
「Terminalが使えないならphpMyAdminかAdminerを使えばいいじゃない」と普通は思うんだけど、それすらもままならないクライアントに運用してもらう場合とか入用になるかも。
ただし、上に「DBのdumpを定期的に書き出してくれる」と書いたように、wordpressのテーブルを判別して書き出しているわけではない。
レンタルサーバなどでwordpress用のテーブルには接頭辞つけて…とか関係なしに全テーブルのdumpを吐きだすっぽい。
初心者でもバックアップからの復元ぐらいやってほしいと思って入れてみたのだけど、テーブル名が全部羅列されている画面だったり、普通にクエリ発行できたりと、じつは初心者向けではないような。
「Terminal開くのめんどくせ」っていう人向けのツールだった。
MySQL、SQLite3、groonga系のサーバの人についてはまとめようと思ったら、groonga系のコンテンツがなかったw
SQLiteのコンテンツもなかったw