Posts Tagged “mysql”


レプリケーションの設定をしているDBがいつの間にかバイナリログによってディスク容量の空きが無くなっていた・・・
想像以上に早くディスク容量を消費する・・・
以下、バイナリログの削除方法と自動削除の設定方法。

http://wiki.bit-hive.com/tomizoo/pg/MySQL%20%A5%D0%A5%A4%A5%CA%A5%EA%A5%ED%A5%B0%A4%CE%BA%EF%BD%FC

Comments [mysql] MySQLのバイナリログ削除 はコメントを受け付けていません


mysqlのサブクエリに問題があることはなんとなく見聞きしていたが今日はこれについて深く追求せざるを得ない機会があったので調べてみました。
自分なりに理解したので簡単にまとめてみるが、以下のブログの記事が素晴らしいので詳しくはそちらもあわせて読むと良いでしょう。

http://nippondanji.blogspot.com/2009/03/mysql_25.html

mysqlの実行計画を知るには

mysqlで実行計画を取得するには実行したいクエリーの前に EXPLAIN をつけるだけ。
実にシンプルだが、取得できるデータもシンプル極まりない(^_^;)

mysql> EXPLAIN SELECT COUNT(customer_id) FROM dtb_customer  WHERE  del_flg = 0  
AND customer_id IN (SELECT customer_id FROM dtb_order WHERE order_id IN 
(SELECT order_id FROM dtb_order_detail WHERE product_name LIKE '%とうもろこし%' ));
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
| id | select_type        | table            | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY            | dtb_customer     | ALL  | NULL          | NULL | NULL    | NULL | 1834 | Using where |
|  2 | DEPENDENT SUBQUERY | dtb_order        | ALL  | NULL          | NULL | NULL    | NULL | 2023 | Using where |
|  3 | DEPENDENT SUBQUERY | dtb_order_detail | ALL  | NULL          | NULL | NULL    | NULL | 2163 | Using where |
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
3 rows in set (0.02 sec)

実行計画の読み取り方は こちら に詳しく載っています。

IN句はEXISTS句におきかわる

さて、上にあげたクエリーは IN句に二重にサブクエリーが入っている、ツッコミどころ満載のSQLである。(実はEC-CUBEの中でこのクエリーが使われている。)
普通は1番内側のサブクエリーから実行されていって結果が返ってくるという動きを想像してしまうしそのほうが効率がいいのは明らかだ。
ところがmysqlでは外側のクエリーから実行し、得たレコードについて内側のサブクエリーを繰り返し実行するという処理になる。
つまりIN句なしで検索した結果が3000行ある場合、その各行についてサブクエリーの走査が実行するされるのでとんでもなく時間がかかってしまう。

何故このようになるかというとmysqlのオプティマイザがIN句をEXIST句に置き換えてしまうため、サブクエリーが相関サブクエリーとなり、結果上に述べた実行計画になってしまう。

DEPENDENT SUBQUERY に注意

このように実行計画で DEPENDENT SUBQUERY となっているものについては、 nxn の走査が走ってしまう可能性があるのでできるだけ排除したほうがいいだろう。
できる限りJOINを使うように心がけたい。

Comments [tips]なぜmysqlのサブクエリは遅いのか はコメントを受け付けていません


概要

先日MySQLのMaster-Slaveレプリケーションが何かの拍子に機能しなくなっていることがわかりました。
このような状況に陥ったときの修正手順についてまとめてみます。

環境:

  • Debian lenny
  • MySQL 5.0.51
  • 1台のマスタから1台のスレーブに対してレプリケーションしている構成

修正前のSlave状態

まず、現在のSlaveの状態を確認します。

mysql> show slave status\G
*************************** 1. row ***************************
             Slave_IO_State:
                Master_Host: xxx.xxx.xxx
                Master_User: repl
                Master_Port: 3306
              Connect_Retry: 60
            Master_Log_File: mysqld-bin.000005
        Read_Master_Log_Pos: 13341150
             Relay_Log_File: mysqld-relay-bin.000232
              Relay_Log_Pos: 98
      Relay_Master_Log_File: mysqld-bin.000005
           Slave_IO_Running: No
          Slave_SQL_Running: Yes
            Replicate_Do_DB: 
        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: 13341150
            Relay_Log_Space: 98
            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: NULL
1 row in set (0.01 sec)

⇒「Slave_IO_Running: No 」になっています。
ちなみにマスタの状態は、、

mysql> show master status\G
*************************** 1. row ***************************
            File: mysqld-bin.000009
        Position: 42782848
    Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)

となっています。明らかにずれています。

復旧手順

MasterのバックアップとPositionの確認

Masterのバックアップを取ると同時にLog Positionを確認しておきます。

(Master側で)
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
※ここで表示される FileとPositionの値を記録しておく。

バックアップはmysqldumpコマンドで行ないます。

$ mysqldump -u root -p --lock-all-tables --databases db1 db2 ...  > mysql.dmp

バックアップが終わったらロックを解除します。

(Master側で)
mysql> UNLOCK TABLES;

※ここまでの間、DBへの書き込みがブロックされることになります。

Slave側にバックアップを適用

Masterで取得したバックアップファイルをSlaveに適用します。

(Slave側で)
mysql> drop database db1 db2 ....;
$ mysql -u root -p < mysql.dmp

Slave側でMasterのpositionをセットしてレプリケーション開始

Masterバックアップ時に記録したFile名とPotisionをSlaveにセットしてレプリケーションを開始します。

(Slave側で)
mysql> CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001',  MASTER_LOG_POS=4320981;
mysql> START SLAVE;

これで完了。Master側で SHOW MASTER STATUS, Slave側で SHOW SLAVE STATUSを実行してレプリケーションが機能していることを確認します。

Nagiosでのレプリケーション監視

WEB+DB PRESS vol.54に書いてあるとおりなのですがNagiosでレプリケーションの監視ができることを知りました。
標準プラグインで提供されている「check_mysql」を使用するのですがDebianの場合は
/etc/nagios-plugins/config/mysql.cfg に以下のように追記してコマンドを用意しました。

# 'check_mysql_slave' command definition
define command{
        command_name    check_mysql_slave
        command_line    /usr/lib/nagios/plugins/check_mysql -H '$HOSTADDRESS$' -u '$ARG1$' '$ARG2$'
}

そしてサーバの定義ファイルに

define service{
        use                             generic-service
        host_name                  localhost
        service_description       mysql
        check_command         check_mysql_slave!nagios!-S
}

のように設定します。

※監視用につかう nagiosユーザには REPLICATION CLIENTに加えて SUPERの権限が必要でした。

mysql> GRANT SUPER,REPLICATION CLIENT ON *.* TO nagios@localhost;

※今回は既に一度レプリケーション構成を構築していた環境で再設定することについてまとめましたが、一からレプリケーション構成を構築する場合にはこれに加えていくつかの作業が必要となります。下記のリンクなどが参考になります。

参考

Comments MySQLのレプリケーションが不整合になってしまったときの再構築手順 はコメントを受け付けていません