爲什麼要做主從複製?
-
在業務複雜的系統中,有這麼一個情景,有一句sql語句需要鎖表,導致暫時不能使用讀的服務,那麼就很影響運行中的業務,使用主從複製,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現了鎖表的情景,通過讀從庫也可以保證業務的正常運作。通過做主從複製(讀寫分離)來減輕主數據庫的負載
- 做數據的熱備
- 業務量越來越大,I/O訪問頻率過高,單機無法滿足,此時做多庫的存儲,降低磁盤I/O訪問的頻率,提高單個機器的I/O性能。如果對數據庫的讀和寫都在同一個數據庫服務器中操作,業務系統性能會降低
主從複製的原理
- 主庫db的更新事件(update、insert、delete)被寫到binlog
- 從庫發起連接,連接到主庫
- 此時主庫創建一個binlog dump thread,把binlog的內容發送到從庫
- 從庫啓動之後,創建一個I/O線程,讀取主庫傳過來的binlog內容並寫入到relay log
- 還會創建一個SQL線程,從relay log裏面讀取內容,從Exec_Master_Log_Pos位置開始執行讀取到的更新事件,將更新內容寫入到slave的db
注:上面的解釋是解釋每一步做了什麼,整個mysql主從複製是異步的,不是按照上面的步驟執行的。
同步操作通過 3 個線程實現,其基本步驟如下:
主服務器將數據的更新記錄到二進制日誌中(記錄被稱作二進制日誌事件)-- 主庫線程;
從庫將主庫的二進制日誌複製到本地的中繼日誌(relay log)-- 從庫 I/O 線程;
從庫讀取中繼日誌中的事件,將其重放到數據中 -- 從庫 SQL 線程。
本篇博客記錄的是一主一從模式
環境搭建
準備工作
- 主從數據庫版本最好一致
- 主從數據庫內數據保持一致
- 主數據庫:192.168.190.131 從數據庫:192.168.190.132
配置主庫Master
- 修改MySQL配置
mysql查看默認配置文件:mysql --help|grep 'my.cnf',找到主數據庫的配置文件my.cnf,我的在/etc/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Recommended in standard MySQL setup
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
#主服務器唯一ID
server-id=1
#設置需要複製的數據庫
binlog-do-db=testdb
#二進制日誌
#配置開啓 binlog日誌,日誌的文件前綴爲mysqlbin生成的文件名如: mysqlbin.000001, mysqlbin.000002
log_bin=mysqlbin
#配置二進制日誌的格式
binlog_format=STATEMENT
#自動刪除的過期天數
expire_logs_days=3
#該選項用來開啓查詢日誌,可選值:0關閉;1開啓
general_log=1
#設置日誌的文件名,如果沒有指定,默認的文件名爲host_name.log
general_log_file=mysql_query.log
#該參數用來控制慢查詢日誌是否開啓:1開啓,0關閉
slow_query_log=1
#該參數用來指定慢查詢日誌的文件名
slow_query_log_file=slow_query.log
#該選項用來配置查詢的時間限制,超過這個時間將認爲是慢查詢,需要進行日誌記錄,默認是10s
long_query_time=3
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
- 創建用戶
重啓服務,創建用於同步的用戶,用戶:salve密碼:123456
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
-
查看master狀態
mysql> show master status;
+-----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+-------------------+
| mysqlbin.000007 | 2400 | testdb | | |
+-----------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
配置從庫Slave
- 修改MySQL配置
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Recommended in standard MySQL setup
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
#從服務器唯一ID
server-id=2
#啓用中繼日誌
relay-log=mysql-relay
#二進制日誌
#配置開啓 binlog日誌,日誌的文件前綴爲mysqlbin生成的文件名如: mysqlbin.000001, mysqlbin.000002
log_bin=mysqlbin
#配置二進制日誌的格式
binlog_format=STATEMENT
#自動刪除的過期天數
expire_logs_days=3
#該選項用來開啓查詢日誌,可選值:0關閉;1開啓
general_log=1
#設置日誌的文件名,如果沒有指定,默認的文件名爲host_name.log
general_log_file=mysql_query.log
#該參數用來控制慢查詢日誌是否開啓:1開啓,0關閉
slow_query_log=1
#該參數用來指定慢查詢日誌的文件名
slow_query_log_file=slow_query.log
#該選項用來配置查詢的時間限制,超過這個時間將認爲是慢查詢,需要進行日誌記錄,默認是10s
long_query_time=3
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
- 重啓mysql,打開mysql會話,執行同步SQL語句(需要主服務器主機名,登陸憑據,二進制文件的名稱和位置)
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.190.131',
-> MASTER_USER='salve',
-> MASTER_PASSWORD='123456',
-> MASTER_LOG_FILE='mysqlbin.000007',
-> MASTER_LOG_POS=2400;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
- 啓動slave同步進程
mysql>start slave;
停止stop slave;重新配置主從reset master;
- 查看slave狀態
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.190.131
Master_User: salve
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysqlbin.000007
Read_Master_Log_Pos: 2400
Relay_Log_File: mysql-relay.000003
Relay_Log_Pos: 2277
Relay_Master_Log_File: mysqlbin.000007
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: 2400
Relay_Log_Space: 2446
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_UUID: 9510d25d-7d7b-11ea-9a71-000c29980d35
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row in set (0.00 sec)
當Slave_IO_Running和Slave_SQL_Running都爲YES的時候就表示主從同步設置成功了。如果是虛擬機克隆的情況下,注意修改/var/lib/mysql/auto.cnf中的uuid
注意事項
master主節點
在主節點的二進制事件日誌中僅記錄與指定數據庫(數據表)相關的事件日誌,但是主節點的二進制日誌不完整,沒有記錄所有對主節點的修改操作。如果要使用該方式,則在主節點的配置文件中添加如下參數:
binlog_do_db="***,***,***"; #數據庫白名單列表,二進制日誌記錄的數據庫(多數據庫用逗號隔開或重複設置多行),即需要同步的庫.不在內的不同步。(不添加這行表示同步所有)
binlog_ingore_db="***,***,***"; #數據庫黑名單列表, 二進制日誌中忽略的數據庫 (多數據庫用逗號隔開或重複設置多行),即不需要同步,要過濾掉的庫.
slave從節點
從服務器SQL Thread在Replay中繼日誌中的事件時僅讀取於特定數據庫相關的事件,並應用於本地. (但是浪費I/O ,浪費帶寬) 推薦使用從節點複製過濾相關設置項:
replicate_do_db ="webdb"; #複製庫的白名單. 設定需要複製的數據庫(多數據庫使用逗號隔開或重複設置多行)
replicate_ingore_db ="mysql"; #複製庫的黑名單. 設定需要忽略的複製數據庫 (多數據庫使用逗號隔開或重複設置多行)
replicate_do_table="webdb.user"; #複製表的白名單. 設定需要複製的表(多數據庫使用逗號隔開或重複設置多行)
relicate_ingore_table="webdb.uw"; #複製表的黑名單. 設定需要忽略的複製的表(多數據庫使用逗號隔開或重複設置多行)
replicate-wild-do-table #同replication-do-table功能一樣,但是可以通配符. 更高級別的應用,通配符,應用到哪一類表的。
replicate-wild-ignore-table #同replication-ignore-table功能一樣,但是可以加通配符.
當在主庫存在的庫而從庫不存在的庫同步時,會出現sql錯誤,這時候可以排除或者從庫手動導入主庫數據庫。從庫可以使用通配符
"庫名.%"
方式過濾主從同步時某個庫的設置
replicate-wild-do-table=webdb.% #只複製webdb庫下的所有表
replicate-wild-ignore-table=mysql.% #忽略mysql庫下的所有表
特別注意: 生產庫上一般不建議設置過濾規則, 如果非要設置, 強烈建議從庫使用通配符方式過濾某個庫
replicate-wild-do-table= "庫名.%"
replicate-wild-ignore-table= "庫名.%"
而不建議從庫使用DB方式過濾某個庫
replicate_do_db ="庫名"
replicate_ingore_db ="庫名"
驗證
在主服務器創建testdb數據庫,新建mytbl表,插入幾條數據,發現從服務器也能查詢到testdb數據庫,mytbl表,以及表中的數據