面試被問MySQL 主從複製,怎麼破?

1、前言

隨着應用業務數據不斷的增大,應用的響應速度不斷降低,在檢測過程當中咱們不難發現大多數的請求都是查詢操做。html

此時,咱們能夠將數據庫擴展成主從複製模式,將讀操做和寫操做分離開來,多臺數據庫分攤請求,從而減小單庫的訪問壓力,進而應用獲得優化。整理了一份328頁MySQLPDF文檔mysql

本次測試使用兩個虛擬機:ip:192.168.2.21(主) ip:192.168.2.22(從)sql

2、主從複製原理

 

同步操做經過 3 個線程實現,其基本步驟以下:數據庫

主服務器將數據的更新記錄到二進制日誌中(記錄被稱做二進制日誌事件)-- 主庫線程;
從庫將主庫的二進制日誌複製到本地的中繼日誌(relay log)-- 從庫 I/O 線程;
從庫讀取中繼日誌中的事件,將其重放到數據中 -- 從庫 SQL 線程。

3、配置主庫

# 3.1 建立用戶

爲了安全起見,準備建立一個新用戶用於從庫鏈接主庫。vim

# 建立用戶
create user 'repl'@'%' identified by 'repl';

# 受權,只授予複製和客戶端訪問權限
grant replication slave,replication client on *.* to 'repl'@'%' identified by 'repl';

# 3.2 修改配置文件

1)vim /etc/my.cnf 在[mysqld]下添加:安全

log-bin         = mysql-bin
log-bin-index   = mysql-bin.index
binlog_format   = mixed
server-id       = 21
sync-binlog     = 1
character-set-server = utf8

2)保存文件並重啓主庫:服務器

service mysqld restart

配置說明:網絡

log-bin:設置二進制日誌文件的基本名;
log-bin-index:設置二進制日誌索引文件名;
binlog_format:控制二進制日誌格式,進而控制了複製類型,三個可選值
    -STATEMENT:語句複製
    -ROW:行復制
    -MIXED:混和複製,默認選項
server-id:服務器設置惟一ID,默認爲1,推薦取IP最後部分;
sync-binlog:默認爲0,爲保證不會丟失數據,需設置爲1,用於強制每次提交事務時,同步二進制日誌到磁盤上。

# 3.3 備份主數據庫數據

若主從數據庫都是剛剛裝好且數據都是一致的,直接執行 show master status 查看日誌座標。ide

若主庫能夠停機,則直接拷貝全部數據庫文件。測試

若主庫是在線生產庫,可採用 mysqldump 備份數據,由於它對全部存儲引擎都可使用。

1)爲了獲取一個一致性的快照,需對全部表設置讀鎖:

flush tables with read lock;

2)獲取二進制日誌的座標:

show master status;

返回結果:

+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      120 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

3)備份數據:

# 針對事務性引擎
mysqldump -uroot -ptiger --all-database -e --single-transaction --flush-logs --max_allowed_packet=1048576 --net_buffer_length=16384 > /data/all_db.sql

# 針對 MyISAM 引擎,或多引擎混合的數據庫
mysqldump -uroot --all-database -e -l --flush-logs --max_allowed_packet=1048576 --net_buffer_length=16384 > /data/all_db.sql
1 row in set (0.00 sec)

4)恢復主庫的寫操做:

unlock tables;

4、配置從庫

# 4.1 修改配置文件

1)vim /etc/my.cnf 在[mysqld]下添加:

log-bin             = mysql-bin
binlog_format       = mixed
log-slave-updates   = 0
server-id           = 22
relay-log           = mysql-relay-bin
relay-log-index     = mysql-relay-bin.index
read-only           = 1
slave_net_timeout   = 10

2)保存文件並重啓從庫:

service mysqld restart

配置說明:

log-slave-updates:控制 slave 上的更新是否寫入二進制日誌,默認爲0;若 slave 只做爲從服務器,則沒必要啓用;若 slave 做爲其餘服務器的 master,則需啓用,啓用時需和 log-bin、binlog-format 一塊兒使用,這樣 slave 從主庫讀取日誌並重作,而後記錄到本身的二進制日誌中;
relay-log:設置中繼日誌文件基本名;
relay-log-index:設置中繼日誌索引文件名;
read-only:設置 slave 爲只讀,但具備super權限的用戶仍然可寫;
slave_net_timeout:設置網絡超時時間,即多長時間測試一下主從是否鏈接,默認爲3600秒,即1小時,這個值在生產環境過大,咱們將其修改成10秒,即若主從中斷10秒,則觸發從新鏈接動做。

# 4.2 導入備份數據

若是 3.3 步驟中沒進行備份,忽略此步驟。

mysql -uroot -p < /data/all_db.sql

# 4.3 統一二進制日誌的座標

根據 3.3 步驟獲取的座標,統一到從庫中:

change master to
master_host='192.168.2.21',
master_user='repl',
master_password='repl',
master_port=3306,
master_log_file='mysql-bin.000001',
master_log_pos=120;

注意:此處使用的是新建立的帳戶。

# 4.4 啓動主從複製

1)啓動從庫 slave 線程:

start slave;

2)查看從服務器複製功能狀態:

show slave status\G;

返回結果:

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.2.21
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 120
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 283
        Relay_Master_Log_File: mysql-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: 120

此處只張貼部分返回結果。

結果說明:

Slave_IO_Running:此進程負責 slave 從 master 上讀取 binlog 日誌,並寫入 slave 上的中繼日誌。
Slave_SQL_Running:此進程負責讀取並執行中繼日誌中的 binlog 日誌。

這兩個進程的狀態需所有爲 YES,只要有一個爲 NO,則複製就會中止。

當 Relay_Master_Log_File = Master_Log_File 且 Read_Master_Log_Pos = Exec_Master_Log_Pos 時,則代表 slave 和 master 處於徹底同步的狀態。

5、驗證

使用一個簡單的例子:

在主庫建立名爲 mysql_test 的數據庫,若是同步成功,那麼在從庫中也能查詢出名爲 mysql_test 數據庫。

 

6、參考資料

 
相關文章
相關標籤/搜索