1. 程式人生 > 其它 >MySQL主從模式及配置

MySQL主從模式及配置

主伺服器:192.168.20.239

從伺服器:192.168.20.176

主從原理

主節點

1、當主節點上進行 insert、update、delete 操作時,會按照時間先後順序寫入到 binlog 中;
2、當從節點連線到主節點時,主節點會建立一個叫做 binlog dump 的執行緒;

3、一個主節點有多少個從節點,就會建立多少個 binlog dump 執行緒;

4、當主節點的 binlog 發生變化的時候,也就是進行了更改操作,binlog dump 執行緒就會通知從節點 (Push模式),並將相應的 binlog 內容傳送給從節點;

從節點

當開啟主從同步的時候,從節點會建立兩個執行緒用來完成資料同步的工作。

I/O執行緒: 此執行緒連線到主節點,主節點上的 binlog dump 執行緒會將 binlog 的內容傳送給此執行緒。此執行緒接收到 binlog 內容後,再將內容寫入到本地的 relay log。

SQL執行緒: 該執行緒讀取 I/O 執行緒寫入的 relay log,並且根據 relay log 的內容對從資料庫做對應的操作。

主從配置一般都是和讀寫分離相結合,主伺服器負責寫資料,從伺服器負責讀資料,並保證主伺服器的資料及時同步到從伺服器。

一、配置主伺服器:

1:在mysql下找到my.ini檔案,一般在 C:\ProgramData\MySQL\MySQL Server 5.7

在其[mysqld] 下新增主伺服器端配置:

#伺服器 id
server-id=1
#二進位制檔案存放路徑
log-bin=C:\ProgramData\MySQL\MySQL Server 5.7\Data\mysql-bin
#待同步的資料庫  (如果這一行沒有,那麼就是針對所有的不用忽略的資料庫進行同步)
#binlog-do-db=test_db
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=information_schema
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=mysql

注意,上面的mysql-bin 並不是指一個資料夾,而是指 存放為二進位制資料

2:儲存my.ini檔案,重啟資料庫,然後會在C:\ProgramData\MySQL\MySQL Server 5.7\Data 下看到 mysql-bin.index 檔案和 mysql-bin.000001 檔案;

3:連線主資料庫

mysql -u root -p123456

4:給要連線的從伺服器設定許可權:(注意下面的 單引號  分號 )

grant replication slave,reload,super on *.* to 'backup'@'192.168.20.%' identified by '123456';

註釋:  給主機192.168.20.%新增許可權,使用者名稱:backup,密碼:123456;(只需輸入一次就可以了)

    *.* 表示任意資料庫中的任意表,'192.168.20.%' 表示只允許192.168.20.··網段的“從”訪問“主” 的資料庫

    如果你把字元,單引號或者是分號漏掉了,那麼執行會沒有反應的,如果執行成功,會顯示 query ok

mysql> use mysql;
mysql> select user from user;
+---------------+
| user          |
+---------------+
| test          |
| backup        |
| mysql.session |
| mysql.sys     |
| root          |
+---------------+
#檢視使用者發現多了backup

實際就是在mysql中新增一個backup的 slave 賬號,並授權給從伺服器。建立backup使用者,並授權給192.168.20.··使用。

 5:輸入命令 show master status;       # 找到File 和 Position 的值記錄下來; (如果你不小心把主伺服器上的資料庫刪除了,然後重新添加了一個同名的,但是這裡的position 是會改變的,一定要注意

 6: 匯出主資料庫的資料 

mysqldump -u root -p123456 --databases test_db > test_db.mysql

7:把匯出的sql語句,匯入從資料庫

方法一:
mysql>source F:\dir\test_db.mysql
方法二:
先建立DB,然後:mysql -uroot -p123456 test_db < test_db.mysql

這樣從伺服器上也有了 test_db 這個資料庫了 

二、配置從伺服器:

1:在mysql下找到my.ini檔案,在其[mysqld] 下新增從伺服器端配置:

#伺服器 id ,不能和主伺服器一致
server-id=2
#同步的資料庫(需要備份的資料庫名),不寫本行 表示 同步所有資料庫
#replicate-do-db=test_db
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=information_schema
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=mysql
#忽略不同步的資料庫,這個可以不用寫
#binlog-ignore-db=test

2:儲存my.ini檔案,重啟從資料庫,在mysql5.1以上版本中是不支援1中master設定的,如果添加了master設定,資料庫就無法重啟了(這個可能是針對以前的低於5.1的資料庫的,反正我們沒有用到那麼低的,所以不用管什麼 master設定);

3:用上面分配的賬號backup,嘗試連線主資料庫,成功

mysql -ubackup -p123456 -h192.168.20.239

4:重新開啟一個dos介面,用管理員賬號連線從資料庫

mysql –uroot –p123456

修改對主資料庫的連線的引數:

mysql> change master to master_host='192.168.20.239',master_user='backup',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=154;

ps:可能會報一個錯誤,大概的意思是說slave執行緒正在執行,不能設定,這樣的話,執行mysql> stop slave; 停止slave執行緒,然後再設定連線的引數;

設定後,可以執行命令檢視狀態,Master_User: backup 就是剛剛的賬號

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 192.168.20.239
                  Master_User: backup
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: DESKTOP-P02RV6K-relay-bin.000019
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000006
             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: 1258
              Relay_Log_Space: 308
              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: 1236
                Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: a2085118-c063-11ec-a4a8-00090faa0001
             Master_Info_File: C:\ProgramData\MySQL\MySQL Server 5.7\Data\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: 220508 16:56:41
     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:
1 row in set (0.00 sec)

注意:上面的IO執行緒啟動失敗

Slave_IO_Running: No
錯誤資訊 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'

 原因:一方面是因為網路通訊的問題,也有可能是日誌讀取錯誤的問題。因為我是重新設定的,所以可能是讀取順序的錯誤。

解決辦法:

在 slave 執行 mysql> stop slave

在 master 執行 mysql> show master status;
重新整理日誌:mysql> flush logs;
因為重新整理日誌file的位置會+1,即File變成為:mysqld-bin.000002

馬上到 slave 執行
mysql> CHANGE MASTER TO MASTER_LOG_FILE='mysqld-bin.000002',MASTER_LOG_POS=154;
mysql> slave start;
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.20.239
                  Master_User: backup
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 154
               Relay_Log_File: DESKTOP-P02RV6K-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
******************************************************

Slave_IO_Running: Yes               這個表示:連線到主庫,並讀取主庫的日誌到本地,生成本地日誌檔案. yes表示  網路正常

Slave_SQL_Running: Yes             這個表示:讀取本地日誌檔案,並執行日誌裡的SQL命令。  yes表示  表結構正常

5:在 master 中新增一行資料,發現 slave 中也自動增加了,並且Position保持一致。

6:使用 show processlist 語句可檢視執行緒狀態

主資料庫上:可以看到第一個執行緒的 State 是 「Master has sent all binlog to slave; waiting for more updates」,說明同步執行緒一直在執行中。

mysql> show processlist;
+----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User   | Host                  | db      | Command     | Time | State                                                         | Info             |
+----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+
|  2 | root   | localhost:11714       | test_db | Query       |    0 | starting                                                      | show processlist |
|  5 | backup | DESKTOP-P02RV6K:50511 | NULL    | Binlog Dump | 2315 | Master has sent all binlog to slave; waiting for more updates | NULL             |
+----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+

從資料庫上:

mysql> show processlist;
+----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+
| Id | User        | Host            | db      | Command | Time | State                                                  | Info             |
+----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+
|  6 | root        | localhost:58744 | test_db | Query   |    0 | starting                                               | show processlist |
|  9 | system user |                 | NULL    | Connect | 2230 | Waiting for master to send event                       | NULL             |
| 10 | system user |                 | NULL    | Connect |  858 | Slave has read all relay log; waiting for more updates | NULL             |
+----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+

三、可能出問題的地方

1:開始一定要把資料庫資料同步,保證資料一致性。

2:如果Slave_IO_Running: NO 那麼要看看是不是  (1) A有賬戶在用dos介面在登陸資料庫而沒有退出 (2) A資料庫的postion和file有改變,而B裡面change的時候,還是用的以前的資料?

3:主庫不小心宕機,重啟之後發現主庫資料更新,但是從庫不執行,造成了主從的資料不同步。但是在從上面檢視 Slave_IO_Running 和  從庫的狀態,都是正常的。這個時候要注意在主庫看看 show master status  看看postion和file是不是和從庫一致的,我就發現我的主庫宕機之後再次開機就不一樣了。這個時候在從庫執行  

CHANGE MASTER TO MASTER_HOST='192.168.20.239',MASTER_USER='backup',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=154

但是這裡還是有個問題,雖然這個時候,主從可以開始同步了,但是由於這中間,如果不是及時發現,那麼主從的資料還是會有差異的,那這個怎麼解決呢?  答案是,只能重新設定主從。

4:如果我在主裡面  delete  from  xx表  那麼在從裡面,到底是讀出主裡面刪除了哪些行,進而對從進行刪除?還是直接也是和主一樣,運行了 delete from xx呢?答案是後者,從會像主一樣,直接執行 delete from  xx 。所以如果你是有上面3這個問題發生(主從資料不同步了),後面再進行了其他操作的話,會越來越不同步的,所以趕緊重新做主從

5:從庫掛了怎麼辦

在主服務的 binlog dump 執行緒將指定的 binlog 資訊發給從服務時,除了日誌內容,還包括本次傳送內容在主服務端的 bin-log 日誌檔名稱以及位置資訊。

從服務的 I/O 執行緒接收到資訊後將日誌內容寫入realy-log 檔案(mysql-relay-bin.xxxxxx)的末端,並將讀取到的主服務端的 bin-log 的檔名和位置記錄到 master-info 中(通過 show slave status 中的 Master_Info_File 欄位可以看到 master.info 儲存的位置),以便下一次讀取時能告訴主服務從哪裡開始同步。

從服務的 SQL 執行緒檢測到 realy-log 新增了內容後,解析日誌檔案生成對應的 sql 語句,並應用這些 sql 到資料庫,保證主從資料一致性。

所以,即使從庫掛掉了,因為有 master.info 記錄了上一次同步的位置,只要同步服務再次啟動,那就可以從上次同步的位置繼續增量同步了。

參考資料

1:公眾號[古時的風箏]MySQL主從配置和讀寫分離 https://www.cnblogs.com/fengzheng/p/13401783.html

2:windows 下mysql 主從庫的配置 https://www.cnblogs.com/joeylee/archive/2013/01/24/2875515.html