MySQL學習筆記十七:複製特性

1、MySQL的複製是將主數據庫(master)的數據複製到從(slave)數據庫上,專業一點講就是將主數據庫DDL和DML操做的二進制日誌傳到從庫上,而後從庫對這些二進制日誌進行重作,使得主數據庫與從數據庫的數據保持同步。mysql

2、MySQL複製的一些優勢:sql

  1. 能夠將大部分的查詢任務放在從庫上進行,下降主庫的負載,提升性能,但要注意實時性要求高的數據仍需在主庫上讀取。
  2. 若是主庫出現了宕機,能夠快速切換到從庫上,提升了可用性。
  3. 能夠在從庫上進行數據備份,下降在備份期間對主庫的影響。
  4. 將數據挖掘和分析等工做放在從庫上進行,能夠下降對主庫的性能影響。

3、MySQL複製處理數據的三種模式:數據庫

  1. 基於語句複製:也稱爲SBR(Statement Based Replication),基於實際執行的SQL語句來進行復制的方案,BINLOG_FORMAT=STATEMENT。
  2. 基於行的複製:也叫RBR(Row Bases Replication),BINLOG_FORMAT=ROW。
  3. 混合複製模式:也成MBR,基於SQL語句複製和行的複製,BINLOG_FORMAT=MIXED。

查看二進制日誌的格式:服務器

mysql> show global variables like 'binlog_format';
+---------------+-----------+
| Variable_name | Value     |  ---value的值有三種:statement,row,mixed
+---------------+-----------+
| binlog_format | STATEMENT |  
+---------------+-----------+
1 row in set (0.00 sec)

設置二進制日誌的格式:session

mysql> set global binlog_format='row';   --設置全局binlog_format,可使用set session binlog_format='row'來設置當前會話的binlog_format
Query OK, 0 rows affected (0.00 sec)
mysql> show GLOBAL variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)

在SQL中查看日誌文件中的事件:多線程

mysql> show binlog events in 'mysql-bin.000027' from 107; --from指定從日誌哪一個位置開始
+------------------+-----+------------+-----------+-------------+---------------------------------------------+
| Log_name         | Pos | Event_type | Server_id | End_log_pos | Info                                        |
+------------------+-----+------------+-----------+-------------+---------------------------------------------+
| mysql-bin.000027 | 107 | Query      |      3306 |         175 | BEGIN                                       |
| mysql-bin.000027 | 175 | Query      |      3306 |         264 | use `test`; insert into t1 values (10)      |
| mysql-bin.000027 | 264 | Query      |      3306 |         333 | COMMIT                                      |
| mysql-bin.000027 | 333 | Query      |      3306 |         401 | BEGIN                                       |
| mysql-bin.000027 | 401 | Query      |      3306 |         495 | use `test`; update t1 set id=70 where id=60 |
| mysql-bin.000027 | 495 | Query      |      3306 |         564 | COMMIT                                      |
| mysql-bin.000027 | 564 | Stop       |      3306 |         583 |                                             |
+------------------+-----+------------+-----------+-------------+---------------------------------------------+
7 rows in set (0.00 sec)

基於SQL語句的二進制日誌記錄原始SQL操做,而基於ROW格式的二進制日誌記錄的是每行數據的變動,採用64位編碼,使用mysqlbinlog查看時須搭配--base64-output='decode-rows' --vv參數來解碼查看。架構

4、MySQL複製流程併發

 MySQL複製基於二進制日誌,開啓二進制日誌功能是必須的。當從庫啓動複製時(start slave),首先建立一個I/O線程鏈接主庫,主庫接着建立Binlog Dump線程讀取二進制日誌事件發送給從庫的I/O線程,I/O線程獲取數據後更新從庫的中繼日誌Relay Log,而後從庫的SQL線程讀取中繼日誌中更新的數據庫事件並應用,以下圖所示:異步


可使用SHOW PROCESSLIST命令在主庫和從庫上分別執行,查看主庫BINLOG DUMP線程和從庫SQL線程狀態:函數

----------------------在主庫上-------------
mysql> show processlist\G
*************************** 3. row ***************************
     Id: 18
   User: repl
   Host: localhost:2275
     db: NULL
Command: Binlog Dump
   Time: 76
  State: Master has sent all binlog to slave; waiting for binlog to be updated
   Info: NULL
3 rows in set (0.00 sec)
--------------------在從庫上---------------
*************************** 2. row ***************************
     Id: 27
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 301
  State: Waiting for master to send event
   Info: NULL
*************************** 3. row ***************************
     Id: 28
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 246703
  State: Slave has read all relay log; waiting for the slave I/O thread to update it
   Info: NULL

5、搭建複製環境

因爲本人苦逼學生一枚,只有一臺電腦,因此只能在一臺電腦上開啓多個MySQL服務,開啓過程以下所示:

  1.中止mysql服務

  2.copy mysql安裝目錄到指定目錄E:\,這裏隨意,不要和原目錄重疊便可

  3.copy mysql data數據文件到E:\data

  4.copy一份my.ini文件到上面指定的目錄下

  5.修改複製後的配置文件my.ini,內容以下:

  [client]

  port=3307 #第一個數據庫的默認端口是3306 這裏須要另外啓用一個端口

  # The TCP/IP Port the MySQL Server will listen on

  port=3307

  # Path to installation directory. All paths are usually resolved relative to this.

  basedir="E:\MySQL\MySQL Server 5.5\"         #第二個數據庫basedir

  # Path to the database root

  datadir="E:\MySQL\MySQL Server 5.5\data\"    #第二個數據庫datadir

  6.建立新的mysql服務

  mysqld install MySQLSLAVE  --defaults-file="E:\MySQL\MySQL Server 5.5\my.ini"

  7.修改註冊表,以下:

  KEY_LOCAL_MACHINE-->SYSTEM-->CurrentControlSet-->Services

  找到剛纔建立的MySQLSLAVE,將ImagePath修改爲以下":

  "E:\MySQL\MySQL Server 5.5\bin\mysqld" --defaults-file="E:\MySQL\data\my.ini" mysqlsalve

複製環境搭建過程以下:

  1.修改主數據庫的配置文件my.ini,修改內容以下:

server-id=3306
#主從複製是經過二進制文件來進行,因此要開啓日誌功能
log-bin=mysql-bin
#主機,讀寫均可以
read-only=0
#須要備份數據,多個寫多行
binlog-do-db=test
#不須要備份的數據庫,多個寫多行
binlog-ignore-db=mysql

  2.修改從數據庫的配置文件my.ini,修改內容以下:

#主從配置
server-id=3307
log-bin=mysql-bin
#若是從服務器發現主服務器斷掉,從新鏈接的時間差(秒)
#master-connect-retry=60
#只複製某個庫
replicate-do-db=test
#不復制某個庫
replicate-ignore-db=mysql

  3.保持主從的test庫初始狀態一致

mysql> flush tables with read lock;  
Query OK, 0 rows affected (0.05 sec)
---首先鎖定表爲讀有效,防止數據庫有更新操做,而後利用COPY/CP命令將數據文件目錄複製到從庫數據目錄下
---或者直接關閉mysql服務,手動複製數據文件目錄到指定目錄下
---拷貝完後,恢復寫操做

 mysql> unlock tables;
 Query OK, 0 rows affected (0.00 sec)

 

  4.在主庫上建立一個專門用來複制的用戶repl

mysql> GRANT REPLICATION SLAVE ON *.* TO 'REPL'@'127.0.0.1' IDENTIFIED BY '1234567';
Query OK, 0 rows affected (0.31 sec)

  5.重啓主庫,而後執行show master status,記下file和position字段對應的參數

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000031 |      262 | test         | mysql            |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

  六、在從庫設置它的master:

mysql> change master to master_host='127.0.0.1',master_port=3306,master_user='repl',master_password='asdf',master_log_file='mysql-bin.000031',master_log_pos=262;

Query OK, 0 rows affected (0.19 sec)
----這裏的master_log_file和master_log_pos對應剛纔show master status記下的參數。

  7.在從庫上開啓複製start slave

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)  --這裏有個warning,是由於我已經開啓了slave

  8.驗證複製搭建是否成功

mysql> show processlist\G;
*************************** 2. row ***************************
     Id: 27
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 6349
  State: Waiting for master to send event
   Info: NULL
*************************** 3. row ***************************
     Id: 28
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 580
  State: Slave has read all relay log; waiting for the slave I/O thread to update it
   Info: NULL
3 rows in set (0.00 sec)
----以上信息表名slave已經連上了master,並開始接收和執行日誌---

  9.使用show slave status來查看slave信息

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 127.0.0.1
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000031
          Read_Master_Log_Pos: 262
               Relay_Log_File: Lenovo-PC-relay-bin.000059
                Relay_Log_Pos: 408
        Relay_Master_Log_File: mysql-bin.000031
             Slave_IO_Running: Yes  --I/O線程已開啓
            Slave_SQL_Running: Yes --SQL線程也開啓
              Replicate_Do_DB: test
          Replicate_Ignore_DB: mysql
           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: 262
              Relay_Log_Space: 714
              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  --I/O沒有錯誤
                Last_IO_Error:
               Last_SQL_Errno: 0  --sql應用也沒有錯誤
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 3306
1 row in set (0.00 sec)

  10.驗證複製的正確性

-------在主庫上的test庫建立表cc------
mysql> create table cc (id int not null);
Query OK, 0 rows affected (0.10 sec)

mysql> insert into cc values (10),(20);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0
-------在從庫上查看是否存在表cc-----
mysql> show tables like 'cc';
+---------------------+
| Tables_in_test (cc) |
+---------------------+
| cc                  |
+---------------------+
1 row in set (0.00 sec)

mysql> select *  from cc;
+----+
| id |
+----+
| 10 |
| 20 |
+----+
2 rows in set (0.00 sec)
------------說明覆制搭建已經成功------

6、半同步複製

MySQL複製默認採用異步的同步機制,主庫和從庫的數據之間存在必定的延時,不能保證數據的一致性和及時性。所以有必要開啓半同步複製,而半同步複製模式是由mysql插件來實現,主從庫使用不一樣的插件(semisync_master.so/semisync_slave.so),安裝插件以下所示。

檢查mysql服務是否支持動態加載插件

mysql> show variables like '%dynamic_loading%';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| have_dynamic_loading | YES   |
+----------------------+-------+
1 row in set (0.00 sec)
----也能夠直接執行select @@have_dynamic_loading

安裝插件

mysql> install plugin  rpl_semi_sync_master soname 'semisync_master.dll';
ERROR 1125 (HY000): Function 'rpl_semi_sync_master' already exists   --我已經安裝了該插件

查看插件安裝是否成功

mysql> select * from mysql.plugin;
+----------------------+---------------------+
| name                 | dl                  |
+----------------------+---------------------+
| rpl_semi_sync_master | semisync_master.dll |
+----------------------+---------------------+
1 row in set (0.03 sec)

從庫也使用一樣的方法安裝semisync_slave插件

mysql> select * from mysql.plugin;
+---------------------+--------------------+
| name                | dl                 |
+---------------------+--------------------+
| rpl_semi_sync_slave | semisync_slave.dll |
+---------------------+--------------------+
1 row in set (0.00 sec)

打開半同步複製,由於mysql默認是關閉的

mysql> show variables like '%semi_sync%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | OFF   |
| rpl_semi_sync_master_timeout       | 10000 |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
+------------------------------------+-------+
---------主庫------
mysql> set global rpl_semi_sync_master_enabled=on;
Query OK, 0 rows affected (0.01 sec)
---------從庫-------------
mysql> set global rpl_semi_sync_slave_enabled=on;
Query OK, 0 rows affected (0.00 sec)
----重啓I/O線程
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.01 sec)

mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

半同步複製配置完畢後,查看半同步複製的狀態信息,在主庫上執行show global status like '%semi_sync%';

mysql> show global status like '%semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     | --表示不是經過半同步複製及時響應的事務數
| Rpl_semi_sync_master_status                | ON    | --表示當前半同步複製已經打開
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     | --表示經過半同步模式複製到從庫的事務數
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

半同步同步還有一個超時時間,超過了這個時間,主庫將關閉半同步複製模式,改成異步複製。若是這時從庫從新鏈接主庫,主庫將自動切換到半同步複製模式。查看超時時間

mysql> show variables like '%semi%time%';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| rpl_semi_sync_master_timeout | 10000 | --10s
+------------------------------+-------+
1 row in set (0.00 sec)

7、MySQL複製主要啓動參數

1.master_host,master_port,master_user,master_password這些參數主要用來記錄須要複製的主庫的地址,端口,用戶,密碼等信息,就不具體介紹了。

2.log_slave_updates:用來指定從庫的更新操做是否記錄到二進制日誌中去,若是要搭建的是主-主複製,則該參數必須指定爲ON(set global log_slave_updates=on或在配置文件中永久啓動)

3.read-only:用來限制普通用戶對從庫的更新操做,只接收超級用戶的更新操做。

4.master_connect_retry:指定當和主庫丟失鏈接時重試的時間間隔,默認爲60。

5.replicate_do_db,replicate_ignore_db,replicate_do_table,replicate_ignore_table:這些參數用來指定複製的數據庫或表,好比指定複製的表爲replicate_do_table=test.cc,其餘的表則不會複製。

6.slave_skip_errors:用來指定從庫複製中能夠跳過的錯誤號或跳過所有錯誤,slave_skip_errors=[err_code1,err_code2...|all]

7.master_delay:用來指定延時複製的時間隔間

8、複製的管理維護

1.查看從庫狀態

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 127.0.0.1
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000031
          Read_Master_Log_Pos: 736
               Relay_Log_File: Lenovo-PC-relay-bin.000060
                Relay_Log_Pos: 442
        Relay_Master_Log_File: mysql-bin.000031
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: test
          Replicate_Ignore_DB: mysql
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
----截取部分信息

2.主庫和從庫同步

-----在主庫上執行-----
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
-----在從庫上執行-----
mysql> select master_pos_wait('mysql-bin.000031',' 736');
+--------------------------------------------+
| master_pos_wait('mysql-bin.000031',' 736') |
+--------------------------------------------+
|                                          0 |
+--------------------------------------------+
1 row in set (0.03 sec)
--master_pos_wait的參數值能夠在主庫執行show master status獲得
--該select語句會阻塞到從庫達到指定的日誌文件的偏移量後,返回0,表示與主庫同步了
--完了以後在主庫上執行unlock tables

3.從庫複製出現錯誤

在從庫應用中繼日誌時,可能會出現一些錯誤,例如表結構不對,函數不存在等,若是是不過重要的錯誤,則可以使用sql_slave_skip_counter變量來忽略更新失敗的語句。示例以下:

mysql> stop slave;
Query OK, 0 rows affected (0.02 sec)

mysql> set global sql_slave_skip_counter=1;
----若是是autoincrement或last_insert_id()則爲2

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

4.主-主複製時自增變量衝突的問題

主-主複製須要定製auto_increment_increnment和auto_increment_offset的值來避免重複衝突,這兩個變量的值默認爲1,這也是重複衝突的源頭

mysql> show variables like 'auto_increment_%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.00 sec)

採用如下的設置能夠避免重複

master1:auto_increment_increment=2,auto_increment_offset=1
master1:auto_increment_increment=2,auto_increment_offset=0

5.提升複製性能

方案一:採用一主多從的複製架構,利用replicate_do_db,replicate_ignore_db等參數使得不一樣的從庫複製不一樣的庫/表,下降每一個從庫的寫入壓力。

方案二:利用5.6版本的多線程併發複製,經過設置變量slave_parallel_workers來實現。

stop slave
set global slave_parallel_works=2;
start slave;
---或者在my.ini中天加slave_parallel_workers=2

6.主從切換

1.在每一個從庫上執行stop slave io_thread,中止接收日誌,接着執行show processlist,若是state字段值爲Has read all relay log,表示更新都應用完畢。

2.在須要提高爲主庫的從庫上執行stop slave,reset slave和reset master,將從庫重置成主庫。

3.其餘的從庫執行都執行stop slave,而後執行change master to master_host=新的主庫地址。

4.全部應用指向新的主庫。

相關文章
相關標籤/搜索