MariaDB/Mysql之主從架構的複製原理及主從/雙主配置詳解(一)

1. 複製概述
Mysql內建的複製功能是構建大型,高性能應用程序的基礎。將Mysql的數據分佈到多個系統上去,這種分佈的機制,是通過將Mysql的某一臺主機的數據複製到其它主機(slaves)上,並重新執行一遍來實現的。複製過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日誌文件,並維護文件的一個索引以跟蹤日誌循環。這些日誌可以記錄發送到從服務器的更新。當一個從服務器連接主服務器時,它通知主服務器從服務器在日誌中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,然後封鎖並等待主服務器通知新的更新。
    請注意當你進行復制時,所有對複製中的表的更新必須在主服務器上進行。否則,你必須要小心,以避免用戶對主服務器上的表進行的更新與對從服務器上的表所進行的更新之間的衝突。

1.1 mysql支持的複製類型:
(1) 基於語句的複製: 在主服務器上執行的SQL語句,在從服務器上執行同樣的語句。MySQL默認採用基於語句的複製,效率比較高.一旦發現沒法精確複製時,會自動選着基於行的複製。  
(2) 基於行的複製:把改變的內容複製過去,而不是把命令在從服務器上執行一遍. 從mysql5.0開始支持
(3) 混合類型的複製: 默認採用基於語句的複製,一旦發現基於語句的無法精確的複製時,就會採用基於行的複製。


1.2 複製解決的問題
MySQL複製技術有以下一些特點:
(1) 數據分佈 (Data distribution )
(2) 負載平衡(load balancing)
(3) 備份(Backups)
(4) 高可用性和容錯行 High availability and failover


1.3 複製如何工作

整體上來說,複製有3個步驟:  
(1)master將改變記錄到二進制日誌(binary log)中(這些記錄叫做二進制日誌事件,binary log events);
(2)slave將master的binary log events拷貝到它的中繼日誌(relay log);
(3)slave重做中繼日誌中的事件,將改變反映它自己的數據。

下圖描述了複製的過程:


wKioL1NOK7SQhI9oAAELs3vtpuI124.jpg

該過程的第一部分就是master記錄二進制日誌。在每個事務更新數據完成之前,master在二日誌記錄這些改變。MySQL將事務串行的寫入二進制日誌,即使事務中的語句都是交叉執行的。在事件寫入二進制日誌完成後,master通知存儲引擎提交事務。
   下一步就是slave將master的binary log拷貝到它自己的中繼日誌。首先,slave開始一個工作線程——I/O線程。I/O線程在master上打開一個普通的連接,然後開始binlog dump process。Binlog dump process從master的二進制日誌中讀取事件,如果已經跟上master,它會睡眠並等待master產生新的事件。I/O線程將這些事件寫入中繼日誌。
   SQL slave thread(SQL從線程)處理該過程的最後一步。SQL線程從中繼日誌讀取事件,並重放其中的事件而更新slave的數據,使其與master中的數據一致。只要該線程與I/O線程保持一致,中繼日誌通常會位於OS的緩存中,所以中繼日誌的開銷很小。
   此外,在master中也有一個工作線程:和其它MySQL的連接一樣,slave在master中打開一個連接也會使得master開始一個線程。複製過程有一個很重要的限制-->複製在slave上是串行化的,也就是說master上的並行更新操作不能在slave上並行操作。


2.複製配置
有兩臺MySQL數據庫服務器Master和slave,Master爲主服務器,slave爲從服務器,初始狀態時,Master和slave中的數據信息相同,當Master中的數據發生變化時,slave也跟着發生相應的變化,使得master和slave的數據信息同步,達到備份的目的。

要點:

負責在主、從服務器傳輸各種修改動作的媒介是主服務器的二進制變更日誌,這個日誌記載着需要傳輸給從服務器的各種修改動作。因此,主服務器必須激活二進制日誌功能。從服務器必須具備足以讓它連接主服務器並請求主服務器把二進制變更日誌傳輸給它的權限。

示例:主從同步配置:
注意問題:
   1.版本    
        (1)雙方的MySQL版本要一致;
        (2)如果不一致:主的要低於從的;  
   2.從什麼位置開始複製:
        (1)都從0開始:兩臺新服務器,沒有任何數據;
        (2)主服務器已經運行一段時間,並且存在不小的數據集:把主服務器備份,然後在從服務恢復,從主服務器上備份時所處的位置開始複製;

環境:

Master/SlavePlatfromIPAPP Version
MaterCentOS6.5_X86-64    172.16.41.1   mariadb-10.0.10
SlaveCentOS6.5_X86-64  172.16.41.2 mariadb-10.0.10
1.配置主從服務器:

#Master的配置:

(1)創建有複製權限的用戶,命令如下:

MariaDB [(none)]> CREATE USER 'tom'@'172.16.41.2' IDENTIFIED BY 'qazwsx123';
MariaDB [(none)]> REVOKE ALL PRIVILEGES ,GRANT OPTION FROM 'tom'@'172.16.41.2';
MariaDB [(none)]> GRANT RELOAD,LOCK TABLES, REPLICATION CLIENT ,REPLICATION SLAVE ON *.* TO 'tom'@'172.16.41.2';

MariaDB [(none)]> FLUSH PRIVILEGES

(2)啓用二進制日誌
主配置文件/etc/my.cnf [mysqld]段中,修改如下行:

log-bin = /mydata/binlogs/master-bin

(3)修改server-id
主配:置文件/etc/my.cnf [mysqld]段中,修改如下行
server-id  =  1

#Slave的配置:

(1)修改server-id
主配置文件/etc/my.cnf [mysqld]段中,修改如下行:

server-id  =  2
(2)啓用中繼日誌,關閉二進制日誌

#log-bin = /mydata/mysql-bin   //加上註釋

relay-log = /mydata/relaylogs/relay-bin

確保中繼日誌已開啓
MariaDB [(none)]> SHOW GLOBAL  VARIABLES LIKE 'relay_log';
+---------------+-----------------------------+
| Variable_name | Value                       |
+---------------+-----------------------------+
| relay_log     | /mydata/relaylogs/relay-bin |
+---------------+-----------------------------+
1 row in set (0.00 sec)

(3)連接Master服務器

MariaDB [(none)]> CHANGE MASTER TO MASTER_USER='tom', MASTER_HOST='172.16.41.1', MASTER_PASSWORD='qazwsx123' ;

MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
              Slave_IO_State:
                 Master_Host: 172.16.41.1
                 Master_User: tom
                 Master_Port: 3306
               Connect_Retry: 60
             Master_Log_File:
         Read_Master_Log_Pos: 4
              Relay_Log_File: relay-bin.000001
               Relay_Log_Pos:
4
       Relay_Master_Log_File:
            Slave_IO_Running: No
           Slave_SQL_Running: No
             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: 0
             Relay_Log_Space: 248
             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
Master_SSL_Verify_Server_Cert: No
               Last_IO_Errno: 0
               Last_IO_Error:
              Last_SQL_Errno: 0
              Last_SQL_Error:
 Replicate_Ignore_Server_Ids:
            Master_Server_Id: 0
              Master_SSL_Crl:
          Master_SSL_Crlpath:
                  Using_Gtid: No
                 Gtid_IO_Pos:
1 row in set (0.00 sec)


在輸出的結果當中:

Slave_IO_Running: No

Slave_SQL_Running: No

表明slave還沒有開始複製過程。日誌的位置爲4而不是0,這是因爲0只是日誌文件的開始位置,並不是日誌位置。實際上,MySQL知道的第一個事件的位置是4。



(4)在Slave上面啓動複製線程:

MariaDB [(none)]> START SLAVE;

MariaDB [(none)]> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
              Slave_IO_State: Waiting for master to send event
                 Master_Host: 172.16.41.1
                 Master_User: tom
                 Master_Port: 3306
               Connect_Retry: 60
             Master_Log_File: master-bin.000001
         Read_Master_Log_Pos: 949
              Relay_Log_File: relay-bin.000002
               Relay_Log_Pos: 1237
       Relay_Master_Log_File: master-bin.000001
            Slave_IO_Running: Yes
           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: 949
             Relay_Log_Space: 1528
             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: 0
               Last_IO_Error:
              Last_SQL_Errno: 0
              Last_SQL_Error:
 Replicate_Ignore_Server_Ids:
            Master_Server_Id: 1
              Master_SSL_Crl:
          Master_SSL_Crlpath:
                  Using_Gtid: No
                 Gtid_IO_Pos:
1 row in set (0.00 sec)


   slave的I/O和SQL線程都已經開始運行,而且Seconds_Behind_Master不再是NULL。日誌的位置增加了,意味着一些事件被獲取並執行了。如果你在master上進行修改,你可以在slave上看到各種日誌文件的位置的變化,同樣,你也可以看到數據庫中數據的變化。


   你可查看master和slave上線程的狀態。在master上,你可以看到slave的I/O線程創建的連接:

   在master上輸入show processlist\G;

MariaDB [(none)]> SHOW PROCESSLIST\G
*************************** 1. row ***************************
     Id: 8
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: init
   Info: SHOW PROCESSLIST
Progress: 0.000
*************************** 2. row ***************************
     Id: 9
   User: tom
   Host: 172.16.41.2:56446
     db: NULL
Command: Binlog Dump
   Time: 97
  State: Master has sent all binlog to slave; waiting for binlog to be updated
   Info: NULL
Progress: 0.000
2 rows in set (0.04 sec)

行2爲處理slave的I/O線程的連接。


在slave服務器上運行該語句:

MariaDB [(none)]> SHOW PROCESSLIST\G
*************************** 1. row ***************************
     Id: 5
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: init
   Info: SHOW PROCESSLIST
Progress: 0.000
*************************** 2. row ***************************
     Id: 6
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 186
  State: Waiting for master to send event
   Info: NULL
Progress: 0.000
*************************** 3. row ***************************
     Id: 7
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 167883
  State: Slave has read all relay log; waiting for the slave I/O thread to update it
   Info: NULL
Progress: 0.000
3 rows in set (0.00 sec)

MariaDB [(none)]>

行2爲SQL線程狀態,行3爲I/O線程狀態.


2.測試

(1)在Master上面創建一個數據庫:

MariaDB [(none)]> CREATE DATABASES testdb1;

(2)在Slave上面查看:

MariaDB [(none)]> SHOW DATABASES;

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| testdb1           |
+--------------------+
6 rows in set (0.02 sec)

OK!已經同步過來了,下面爲第二種情況假如master已經運行很久了,想對新安裝的slave進行數據同步,甚至它沒有master的數據。如何指定一個位置開始同步複製:爲了效果我將在Master中導入一些新數據,並且將Slave恢復到最初狀態;

在Master上的操作:

(1)導入新數據:

[root@Master ~]# mysql < hellodb.sql MariaDB [(none)]> SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 |    10289 |              |                  |
+-------------------+----------+--------------+------------------+

此時我對數據庫插入一些數據並備份:

MariaDB [(none)]> CREATE DATABASE testdb;
[root@Master ~]# mysqldump --all-databases --flush-logs  --master-data=1 --lock-all-tables > all.sql  //將此文件傳給新Slave.[root@Master ~]# scp all.sql [email protected]:/root/

(2)在從服務器上導入:

[root@Slave ~]# mysql < all.sql

MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.16.41.1', MASTER_USER='tom', MASTER_PASSWORD='qazwsx123', MASTER_LOG_FILE='master-bin.000001',MASTER_LOG_POS=367;

MariaDB [(none)]> START SLAVE;
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| hellodb            |
| information_schema |
| mysql              |
| performance_schema |
| test               |
| testdb             |
+--------------------+
6 rows in set (0.03 sec)

OK! 簡單的主從複製到此結束!


MySQL簡單複製應用擴展:
1、主從服務器時間要同步(ntp):

echo "*/5 * * * * /usr/sbin/ntpdate YOUR NTP_SERVER_IP" >> /var/cron/root

2、如何限制從服務器只讀?
在從服務器上,/etc/my.cnf[mysqld]段中添加下行read-only=ON
注意:僅能限制那不具有SUPER權限用戶無法執行寫操作;
想限制所有用戶:
mysql> FLUSH TABLES WITH READ LOCK;

3、如何主從複製時的事務安全?
在主服務器上配置:
sync_binlog=1


       未完,有續!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章