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 複製如何工做mysql

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

下圖描述了複製的過程:sql


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/Slave Platfrom IP APP Version
Mater CentOS6.5_X86-64    172.16.41.1   mariadb-10.0.10
Slave CentOS6.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]段中,修改以下行:ide

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-binspa

確保中繼日誌已開啓
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 root@172.16.41.2:/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簡單複製應用擴展:
一、主從服務器時間要同步(ntp):

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

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

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


       未完,有續!

相關文章
相關標籤/搜索