天天看點

Debug mysql master slave issue

雙庫複制

檢查主庫,備庫的狀态

#show master status     --- 主庫

#show slave status \G;  --- 備庫

檢查是哪個庫到哪個庫不通的

insert into test value('test25',25);

排查出複制通道,重設主庫和備庫,

#slave stop

#reset master

#reset slave

#slave start

如果還是不可以的話,重新開機DB在做以上操作。

有三個位址必須調試成功,

1  從庫連接配接主庫進行測試: mysql -h192.168.200.80 -urepluser -ptestpassword     此處必須連接配接成功

2  show master status;必須有相關顯示

3 show slave status;

 必須為

sudo vim /etc/mysql/my.cnf   mysql 配置檔案

sudo /etc/init.d/mysql restart  重新開機 mysql

資料庫伺服器 Master, 主機名 :DB01, IP: 192.168.1.80

資料庫伺服器 Slave, 主機名 :DB02, IP: 192.168.1.103

先配置 Master 的 mysql 環境 .

修改 mysql 的配置檔案 my.cnf 確定有下面的資訊 , 沒有加上 . 有的話修改成下面這樣 . 其他的可以保持預設配置 .

    [mysqld]

    log-bin = mysql-bin

    server-id = 1

       binlog-do-db = test // 要同步的表

GRANT REPLICATION SLAVE ON *.* TO [email protected] IDENTIFIED BY 'testpassword';

從庫連接配接主庫進行測試: mysql -h192.168.200.80 -urepluser -ptestpassword

此處測試應該是通過的,否則 mysql 配置有問題

------- 比如 當在另一台機器上登入 mysql 時出現如下錯誤:

ERROR 2003 (HY000): Can't connect to MySQL server on 'x.x.x.x' (111)

打開 /etc/mysql/my.cnf 檔案,找到 bind-address = 127.0.0.1 修改為 bind-address = 0.0.0.0

-----

OK, 簡單的 MySQL master 伺服器配置到這裡 .

重新開機 mysql 服務 , 登入 , 檢視 master[show master status;] 狀态 . 如下圖 :

可通過 show master status 來監控主伺服器的狀态,内容如下:

+------------------+----------+--------------+------------------+

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |

| mysql-bin.000003 |     1164 |              |                  |

##### 其中 File 表示日志檔案記錄, Position 表示日志檔案的位置,這個也是資料庫執行複制操作的必須辨別,後面兩字段表示複制的資料庫和不複制的資料庫名,也可以在配置檔案中你進行配置。

此處若不顯示,說明配置也有問題。

再配置 Slave 的 mysql 環境 .

同樣修改 my.cnf 配置檔案 . 確定下面有如下資訊 .

     [mysqld]   -- 最好是放在 [mysqld] 下面

    server-id=2

    master-host = 192.168.200.80

    master-user = repluser

    master-password = testpassword

    master-port = 3306

    master-connect-retry = 120

    replicate-do-db = test

儲存修改 , 重新開機 mysql 服務 . 登入資料庫 , 可以看到 slave [show slave status;] 狀态資訊 . 如下圖 :

mysql> show slave status\G;

*************************** 1. row ***************************

             Slave_IO_State: Waiting for master to send event

                Master_Host: 192.168.200.80

                Master_User: repluser

                Master_Port: 3306

              Connect_Retry: 120

            Master_Log_File: mysql-bin.000007

        Read_Master_Log_Pos: 1627

             Relay_Log_File: mysqld-relay-bin.000009

              Relay_Log_Pos: 1764

      Relay_Master_Log_File: mysql-bin.000007

            Slave_IO_Running: Yes

          Slave_SQL_Running: Yes

            Replicate_Do_DB: test

        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: 1627

            Relay_Log_Space: 1764

            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

show slave status\G  如果發現有:

  Slave_IO_Running: Yes

Slave_SQL_Running: Yes

  就說明已經成功了,如果這兩個選項不全是 Yes ,那就說明你錢面的某個配置錯了,

  我做的時候沒有把主伺服器重新開機,就出現   Slave_IO_Running: NO 。重新開機後好了

配置正常 .

簡單的 MySQL 主從配置就 OK 了 . 當然這個是測試環境使用 . 生成環境還需要很多地方的優化配置 .

  ========================Slave_SQL_Running: No

解決辦法一、

Slave_SQL_Running: No

1.程式可能在slave上進行了寫操作

2.也可能是slave機器重起後,事務復原造成的.

一般是事務復原造成的:

解決辦法:

mysql> slave stop;

mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;

mysql> slave start;

解決辦法二、

首先停掉Slave服務:slave stop

到主伺服器上檢視主機狀态:

記錄File和Position對應的值

進入master

mysql> show master status;

+----------------------+----------+--------------+------------------+

| File                 | Position | Binlog_Do_DB | Binlog_Ignore_DB |

| localhost-bin.000094 | 33622483 |              |                  |

1 row in set (0.00 sec)

然後到slave伺服器上執行手動同步:

mysql> change master to > master_host='master_ip', > master_user='user', > master_password='pwd', > master_port=3306, > master_log_file=localhost-bin.000094', > master_log_pos=33622483 ; 1 row in set (0.00 sec) mysql> slave start; 1 row in set (0.00 sec)

mysql> show slave status\G

*************************** 1. row ***************************

........

            Master_Log_File: localhost-bin.000094

        Read_Master_Log_Pos: 33768775

             Relay_Log_File: localhost-relay-bin.000537

              Relay_Log_Pos: 1094034

      Relay_Master_Log_File: localhost-bin.000094

           Slave_IO_Running: Yes

          Slave_SQL_Running: Yes

            Replicate_Do_DB:

手動同步需要停止master的寫操作!

======================================== 

以下是一些備注,可看可不看。

stop slave    reset slave     start slave

----------- 今天發現 Mysql 不同步, show slave status 檢視同步狀态如下:

Slave_IO_Running: No

使用 start slave 也不能同步。後來,先  slave stop 再  slave reset 再  slave start 就正常了。

====================== 手動同步

解決辦法 I :

1. 首先停掉 Slave 服務: slave stop

到主伺服器上檢視主機狀态:

記錄 File 和 Position 對應的值。

mysql> show master status;

+------------------+-----------+--------------+------------------+

| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |

| mysql-bin.000020 | 135617781 | | |

1 row in set (0.00 sec)

3. 到 slave 伺服器上執行手動同步:

mysql> change master to

> master_host='192.168.200.80',

> master_user='repluser',

> master_password='testpassword',

> master_port=3306,

> master_log_file='mysql-bin.000007',

> master_log_pos=98;

 change master to master_host='192.168.12.203', master_user='repluser', master_password='admin@asdf', master_port=3306, master_log_file='binlog.000009', master_log_pos=1253;

4  slave start

 ===================== end  手動同步

1. 問題:主從伺服器表類型的選擇

一般的共識是主伺服器使用innodb,事務,行鎖等功能是myisam所沒有的,對修改操作而言,它更高效;從伺服器使用myisam,全文檢索功能是innodb所沒有的,對查詢操作而言,它更高效。這樣就可以各盡其能。

2. 問題:主從伺服器字段類型的選擇

字 段類型對于分頁等操作有很大影響。主伺服器一般是innodb,因為不涉及查詢,是以可以使用varchar等來存儲字元串來節省空間,從伺服器一般是 myisam,因為涉及查詢,是以必須在char和varchar之間仔細權衡,沒有varchar, text, blob字段的表是靜态表,反之是動态表,靜态表的檢索效率要比動态表好若幹倍,一般來說,所有涉及大結果集的查詢都應該盡可能保證在靜态表上完成,這裡 說一個例子:比如說常見的articles表有title(varchar), body(text)等字段,在做文章清單的時候,因為不是靜态表,是以查詢不會很快,下面開始重構解決方案:把原來的articles表拆分成 subjects表和contents表,title字段設定為一個足夠的char類型放在subjects表裡,body字段還保持是text類型放到 contents表裡,subjects和contents表之間的關系是一對多,這樣,順帶着也友善的實作了多頁文章的功能,而且更重要的是在查詢文章 清單的時候,操作都是在subjects靜态表裡完成,效率肯定會比前一種方案提升很多。

強調:MyISAM裡靜态表和動态表的差別對 性能影響極大,但我敢說很大一部分使用者并沒有注意過這一點!如果你就是其中之一,那麼我強烈建議你再次體會一下前面說的articles分解為 subjects/contents的過程,相信你熟悉了以後,下一個應用的速度會有質的提升。

3. 問題:主從伺服器讀寫分離時讀操作失敗

先 重制一下問題:比如說添加一條新資料,添加成功後根據last_insert_id跳轉到新添加資料的浏覽頁面。在此過程中添加新資料的操作是在主伺服器 上完成的,浏覽新資料的操作實在從伺服器上完成的,不過由于主從伺服器間SQL同步存在延遲,是以當使用last_insert_id在從伺服器上查詢的 時候,從伺服器很可能還沒有還沒來得及同步到此記錄,是以讀操作失敗。解決思路也不複雜,在代碼裡加入一個緩存層(可以使用 memcached),新添加的資料都順手放到緩存層裡一份,新資料的讀操作也先查詢緩存層,這樣就不會再有讀操作失敗的問題了,當然删除或者更新資料的 時候也要順帶着處理好緩存資料,可以使用觀察者模式來搞定。不過這樣緩存方案隻限于讀取單一的記錄,對于讀取清單的記錄的情況,則是無效的。

4. 問題:主從伺服器索引是否有必要保持一緻

一 般都是利用主從伺服器完成讀寫分離,從伺服器上進行讀操作,主伺服器進行寫操作,這樣的話,主伺服器上僅保留主鍵,外鍵,唯一索引等必要的索引即可,以便 保持資料合法性,而對于那些原本用于優化SELECT操作的索引,可以全部删除,如此的話主伺服器的寫操作效率會提升很多。把索引保持在從伺服器上還有一 個好處就是實際應用裡,我們可能時常要通過ALTER TABLE去調整索引,而ALTER TABLE本身資料劇烈運動,會影響線上業務,為了規避影響,我們可以先停止一台從伺服器,然後ALTER TABLE建好索引,然後再把從伺服器啟動,用這樣的方法把所有的從伺服器都建好索引,進而平滑的完成了ALTER TABLE操作。

  Slave_IO_Running: Yes

繼續閱讀