1、MySQL的複製是將主數據庫(master)的數據複製到從(slave)數據庫上,專業一點講就是將主數據庫DDL和DML操做的二進制日誌傳到從庫上,而後從庫對這些二進制日誌進行重作,使得主數據庫與從數據庫的數據保持同步。mysql
2、MySQL複製的一些優勢:sql
3、MySQL複製處理數據的三種模式:數據庫
查看二進制日誌的格式:服務器
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.全部應用指向新的主庫。