以下:html
MYSQL主從複製方式有默認的複製方式異步複製,5.5版本以後半同步複製,5.6版本以後新增GTID複製,包括5.7版本的多源複製。mysql
MYSQL版本:5.7.20linux
操做系統版本:linux 6.7 64bitsql
MYSQL 默認的複製方式,就是主庫寫入binlog日誌後便可成功返回客戶端,無須等待binlog日誌傳遞給從庫的過程。但這樣一旦主庫發生宕機,就有可能出現數據丟失的狀況。數據庫
一、 server-id 不同安全
二、 開啓binlog,建議開啓log_slave_updates,讓從庫也寫binlog,方便後期擴展架構服務器
三、 binlog格式爲row。session
主庫操做:架構
建立主從複製帳號異步
create user 'rep'@'192.16.20.%' identified by 'mysql';
grant replication slave on *.* to 'rep'@'192.16.20.%';
初始化:
mysqldump -S /tmp/mysql3307.sock --single-transaction -uroot -pmysql --master-data=2 -A > salve.sql (我全庫導入的有問題,只用的test庫)
注意:必須加參數 –master-data=2,讓備份出來的文件中記錄備份這一刻binlog文件與position號,爲搭建主從環境作準備。查看備份文件中記錄的當前binlog文件和position號。
scp salve.sql 172.16.20.21:/binlogbak
mysql -S /tmp/mysql3307.sock -uroot -pmysql < slave_test.sql
在數據庫命令行執行配置主從命令。
change master to
master_host='172.16.20.32',
master_user='rep',
master_password='mysql',
master_port=3307,
master_log_file='mysql-binlog.000010',
MASTER_LOG_POS=797;
start slave;
stop slave;
reset slave all; 清空從庫的全部配置信息。
start slave;
當前從庫I/O和SQL thread都是呈現Yes狀態,表明從庫上面操做已經完成了。
Master_Log_File= Relay_Master_Log_File;
Read_Master_Log_Pos= Exec_Master_Log_Pos
證實目前沒有主從延遲狀態。
Slave_IO_Running:從庫上I/O thread 負責請求和接收主庫傳遞來的binlog信息。
Slave_SQL_Running:從庫上SQL thread負責應用relay中的binlog的信息。
1、主從故障之主鍵衝突,錯誤代碼爲1062
緣由:因爲誤操做,從從庫上執行寫操做,致使再在主庫上執行相同的操做,因爲主鍵衝突,主從複製狀態會報錯。因此生產環境建議在從庫上開啓read only,避免在從庫執行寫操做。
在主庫上建表t1;
如今從庫插入數據,後面再在主庫上插入相同的語句。
主庫:
從庫:
主庫執行相同語句:
從庫報錯以下:
報錯代碼:
Last_Errno: 1062
處理辦法:
利用percona-toolkit 工具:
mount /dev/sr0 /mnt
yum -y install perl-DBD-MySQL
./pt-slave-restart -S /tmp/mysql3307.sock -uroot -pmysql
在查看主從狀態,已經恢復正常:
2、主從故障之主庫更新數據,從庫找不到而報錯,錯誤代碼爲10032
上一個錯誤是主從都有相同的數據,咱們能夠直接經過percona-toolkit工具跳過錯誤。但若是從庫上少數據,就不能跳過錯誤了,須要找到缺乏的數據,在從庫上重新執行一遍。
故障緣由:因爲誤操做,在從庫上執行delete 刪除操做,致使主從數據不一致。這時再在主庫執行同條數據的更新操做,因爲從庫沒有該數據,SQL沒法再從庫上實現。
模擬故障:
先在從庫服務器的test庫下的t表中,執行delete刪除語句操做。
再在主庫上執行:相同數據的update更新操做。
從庫報錯以下:
報錯代碼1032。
解決辦法:
根據報錯信息所知道Binlog文件和position(7153)號,在主庫上,經過mysqlbinlog 命令,找到在主庫上執行的那條SQL語句致使的主從報錯。
/usr/local/mysql5.7/bin/mysqlbinlog --no-defaults -v -v --base64-output=decode-rows /mydata/mysql/mysql3307/logs/mysql-binlog.000010 |grep -A 10 7153
insert into t2 values(1,'bbb');
生產上若是丟失數以萬計條的數據,建議從新搭建主從確保數據一致性。
從庫跳過錯誤:
./pt-slave-restart -S /tmp/mysql3307.sock -uroot -pmysql
從新同步成功:
show slave status\G;
因爲粗心,安裝的時候用模板並無修改servier-id。(修改從庫server-id成不一樣的值)
緣由:在主庫中設置binlog-do-db參數,使用的binlog記錄格式爲statement模式,致使在主庫上執行跨庫操做時,從庫沒有複製成功,丟失數據。
故障操做描述:
在主庫的參數文件中添加binlog-do-db=test,表明只複製zs這個庫,而且主庫binlog_format 設置爲statement。
異步複製方式不足之處在於,當主庫把event寫入二進制日誌後,並不知道從庫是否已經接受並應用日誌了;若是主庫發生意外宕機或者是奔潰,頗有可能主庫提交的事物沒有傳到任何一臺從庫機器上。在高可用集羣架構下作主備切換,就會形成新的主庫丟失數據。
mysql5.5版本以後引入了半同步複製功能,主從服務器必須安裝半同步複製插件,才能開啓該複製功能。該功能確保從庫接收完主庫傳遞過來的binlog內容已經寫入到本身的relay log裏面了,纔會通知主庫上面的等待線程,該操做完畢。
若是等待超時,超過rpl_semi_sync_master_timeout 參數設置時間,則關閉半同步複製,並自動轉換爲異步複製模式,直到至少有一臺從庫通知主庫已經接收到binlog信息位置。
半同步複製提高了主從之間數據的一致性,讓複製更加安全可靠,在mysql5.7版本中又增長了rpl_semi_sync_master_wait_point 參數,用來控制半同步模式下主庫在返回給session事物成功以前的事務提交方式。
該參數有兩個值:
AFTER_SYNC(缺省值):主服務器將每一個事務寫入其二進制日誌和從服務器,並將二進制日誌同步到磁盤。同步後,主設備等待從設備確認事務接收。在收到確認後,主服務器將事務提交給存儲引擎,並將結果返回給客戶端,而後客戶端能夠繼續。
AFTER_COMMIT:主服務器將每一個事務寫入其二進制日誌和從服務器,同步二進制日誌,並將事務提交給存儲引擎。主提交後等待從服務器確認事務接收。在收到確認後,主人將結果返回給客戶端,而後客戶端能夠繼續。
主庫上先安裝複製插件和開啓半同步複製功能:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
set global rpl_semi_sync_master_enabled=on;
show variables like '%rpl_semi_sync_master%';
主庫參數文件添加:
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000
show plugins;
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
同理從庫也安裝插件和開啓半同步複製功能:
從庫安裝複製插件和開啓半同步複製功能:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
set global rpl_semi_sync_slave_enabled=on;
備庫參數文件添加:
rpl_semi_sync_slave_enabled=1
因爲以前是異步複製,須要重啓從庫IO線程,激活半同步複製。
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
此時查看主庫:
已經有一個從庫鏈接到主庫了。並且是半同步方式。
show variables like '%rpl_semi_sync_master%';
一、主庫超時超過指定參數時間
rpl_semi_sync_master_timeout 時間爲10s。生產上建議設置的儘量大。
set global rpl_semi_sync_master_timeout=xxx;
二、手動切換
主庫
set rpl_semi_sync_master_enabled=off;
從庫:
set rpl_semi_sync_slave_enabled=off
關閉從庫I/O thread
stop salve io_thread;
start salve io_thread;
GTID複製又叫全局事物ID(global transaction ID),是一個已提交事物的編號,而且是一個全局惟一的編號,MYSQL5.6版本以後在主從複製類型上新增了GTID複製。
GTID是由server_uuid和事物id組成的,即GTID=servier_uuid:transacton_id。Server_uuid是在數據庫啓動過程當中自動生成的,每臺機器的server-uuid不同。UUID存放在數據目錄的auto.cnf文件下。而trasaciton_id就是事物提交時由系統順序分配的一個不會重複的序列號。
一、GTID使用master_auto_position=1 代替了基於binlog和position號的主從複製搭建的方式,更便於主從複製的搭建。
二、GTID能夠知道事務在最開始是在哪一個實例上提交的。
三、GTID方便實現主從之間的failover,不再用不斷的去找position和binlog。
GTID不須要傳統的binlog和position號了,而是在從庫」change master to」時使用」master_auto_position=1」的方式搭建,這就讓操做變得更加方便和可靠了。
在安裝好主從數據庫以後:
主庫須要如下配置:
gtid_mode=on
enforce_gtid_consistency=on
log_bin=on
從庫須要如下配置:
servier-id 主從庫不能同樣。
gtid_mode=on
enforce_gtid_consistency=on
log_slave_updates=1
主庫操做:
建立主從複製帳號
create user 'rep'@'192.16.20.%' identified by 'mysql';
grant replication slave on *.* to 'rep'@'172.16.20.%';
show grants for 'rep'@'172.16.20.%';
若是不一樣網段建議主從各建各的。
初始化:
/usr/local/mysql5.7/bin/mysqldump -S /tmp/mysql3307.sock --single-transaction -uroot -pmysql --master-data=2 -A > slave.sql(我全庫導入的有問題,換成絕對路徑就行,只用的test庫)
注意:必須加參數 –master-data=2,讓備份出來的文件中記錄備份這一刻binlog文件與position號,爲搭建主從環境作準備。查看備份文件中記錄的當前binlog文件和position號。
scp salve.sql 172.16.20.21:/binlogbak
test庫操做:
mysqldump -S /tmp/mysql3307.sock --single-transaction -uroot -pmysql --master-data=2 --database test > slave_test.sql
注意,若是主從GTI不同,數據一致能夠:
set global gtid_purged='*******';
若是數據不同,GTID也不同,建議按照下面先reset從庫:reset master;
mysql -S /tmp/mysql3307.sock -uroot -pmysql < slave_test.sql
注意:屢次恢復會報錯,由於裏面已經有gtid的信息了。
若是你還想繼續強制恢復,能夠在從庫上 reset master ;reset後,gtid_executed,gtid_purged爲空。
show global variables like '%gtid%';
一、若是是在已經跑的服務器,你須要重啓一下mysql server。
二、啓動以前,必定要先關閉master的寫入,保證全部slave端都已經和master端數據保持同步。
三、全部slave須要加上skip_slave_start=1的配置參數,避免啓動後仍是使用老的複製協議。
在數據庫命令行執行配置主從命令。
change master to master_host='172.16.20.32',master_port=3307,master_user='rep',master_password='mysql',master_auto_position=1;
提示:master_log_file='mysql-binlog.000010',MASTER_LOG_POS=797 這兩個參數替換成了 master_auto_position=1
show slave status\G;
start slave;
stop slave;
reset slave all; 清空從庫的全部配置信息。
start slave;
通常複製建議半同步+GTID複製:
附帶主從參數:
主:
[root@mysql5 ~]# cat /etc/my3307.cnf
[client]
port = 3307
socket = /tmp/mysql5.7.sock
[mysql]
prompt="\u@db \R:\m:\s [\d]> "
no-auto-rehash
[mysqld]
user = mysql
port = 3307
basedir = /usr/local/mysql5.7
datadir = /mydata/mysql/mysql3307/data
socket = /tmp/mysql3307.sock
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000
lower_case_table_names=1
secure_file_priv=/tmp
character-set-server = utf8mb4
skip_name_resolve = 1
open_files_limit = 65535
back_log = 1024
max_connections = 500
max_connect_errors = 1000000
table_open_cache = 1024
table_definition_cache = 1024
table_open_cache_instances = 64
thread_stack = 512K
external-locking = FALSE
max_allowed_packet = 32M
sort_buffer_size = 4M
join_buffer_size = 4M
thread_cache_size = 768
query_cache_size = 0
query_cache_type = 0
interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 32M
max_heap_table_size = 32M
slow_query_log = 1
slow_query_log_file = /mydata/mysql/mysql3307/logs/slow.log
log-error = /mydata/mysql/mysql3307/logs/error.log
long_query_time = 0.5
server-id = 3307101
log-bin = /mydata/mysql/mysql3307/logs/mysql-binlog
sync_binlog = 1
binlog_cache_size = 4M
max_binlog_cache_size = 1G
max_binlog_size = 500M
expire_logs_days = 7
master_info_repository = TABLE
relay_log_info_repository = TABLE
gtid_mode = on
enforce_gtid_consistency = 1
log_slave_updates
binlog_format = row
relay_log_recovery = 1
relay-log-purge = 1
key_buffer_size = 32M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M
lock_wait_timeout = 3600
explicit_defaults_for_timestamp = 1
innodb_thread_concurrency = 0
innodb_sync_spin_loops = 100
innodb_spin_wait_delay = 30
transaction_isolation = REPEATABLE-READ
innodb_buffer_pool_size = 1024M
innodb_buffer_pool_instances = 8
innodb_buffer_pool_load_at_startup = 1
innodb_buffer_pool_dump_at_shutdown = 1
innodb_data_file_path = ibdata1:1G:autoextend
innodb_flush_log_at_trx_commit = 1
innodb_log_buffer_size = 32M
innodb_log_file_size = 2G
innodb_log_files_in_group = 2
innodb_max_undo_log_size = 4G
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
innodb_flush_neighbors = 0
innodb_write_io_threads = 8
innodb_read_io_threads = 8
innodb_purge_threads = 4
innodb_page_cleaners = 4
innodb_open_files = 65535
innodb_max_dirty_pages_pct = 50
innodb_flush_method = O_DIRECT
innodb_lru_scan_depth = 4000
innodb_checksum_algorithm = crc32
innodb_lock_wait_timeout = 10
innodb_rollback_on_timeout = 1
innodb_print_all_deadlocks = 1
innodb_file_per_table = 1
innodb_online_alter_log_max_size = 500M
internal_tmp_disk_storage_engine = InnoDB
innodb_stats_on_metadata = 0
innodb_status_file = 1
innodb_status_output = 0
innodb_status_output_locks = 0
#performance_schema
performance_schema = 1
performance_schema_instrument = '%=on'
#innodb monitor
innodb_monitor_enable="module_innodb"
innodb_monitor_enable="module_server"
innodb_monitor_enable="module_dml"
innodb_monitor_enable="module_ddl"
innodb_monitor_enable="module_trx"
innodb_monitor_enable="module_os"
innodb_monitor_enable="module_purge"
innodb_monitor_enable="module_log"
innodb_monitor_enable="module_lock"
innodb_monitor_enable="module_buffer"
innodb_monitor_enable="module_index"
innodb_monitor_enable="module_ibuf_system"
innodb_monitor_enable="module_buffer_page"
innodb_monitor_enable="module_adaptive_hash"
[mysqldump]
quick
max_allowed_packet = 32M
從:
[root@rac1 ~]# cat /etc/my3307.cnf
[client]
port = 3307
socket = /tmp/mysql5.7.sock
[mysql]
prompt="\u@db \R:\m:\s [\d]> "
no-auto-rehash
[mysqld]
user = mysql
port = 3307
basedir = /usr/local/mysql5.7
datadir = /mydata/mysql/mysql3307/data
socket = /tmp/mysql3307.sock
character-set-server = utf8mb4
lower_case_table_names=1
rpl_semi_sync_slave_enabled=1
skip_name_resolve = 1
open_files_limit = 65535
back_log = 1024
max_connections = 500
max_connect_errors = 1000000
table_open_cache = 1024
table_definition_cache = 1024
table_open_cache_instances = 64
thread_stack = 512K
external-locking = FALSE
max_allowed_packet = 32M
sort_buffer_size = 4M
join_buffer_size = 4M
thread_cache_size = 768
query_cache_size = 0
query_cache_type = 0
interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 32M
max_heap_table_size = 32M
slow_query_log = 1
slow_query_log_file = /mydata/mysql/mysql3307/logs/slow.log
log-error = /mydata/mysql/mysql3307/logs/error.log
long_query_time = 0.1
server-id = 3307102
log-bin = /mydata/mysql/mysql3307/logs/mysql-binlog
sync_binlog = 1
binlog_cache_size = 4M
max_binlog_cache_size = 500m
max_binlog_size = 200m
expire_logs_days = 7
master_info_repository = TABLE
relay_log_info_repository = TABLE
gtid_mode = on
enforce_gtid_consistency = 1
log_slave_updates
binlog_format = row
relay_log_recovery = 1
relay-log-purge = 1
key_buffer_size = 32M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M
lock_wait_timeout = 3600
explicit_defaults_for_timestamp = 1
innodb_thread_concurrency = 0
innodb_sync_spin_loops = 100
innodb_spin_wait_delay = 30
transaction_isolation = REPEATABLE-READ
innodb_buffer_pool_size = 1024M
innodb_buffer_pool_instances = 8
innodb_buffer_pool_load_at_startup = 1
innodb_buffer_pool_dump_at_shutdown = 1
innodb_data_file_path = ibdata1:1G:autoextend
innodb_flush_log_at_trx_commit = 1
innodb_log_buffer_size = 32M
innodb_log_file_size = 1g
innodb_log_files_in_group = 2
innodb_max_undo_log_size = 1G
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
innodb_flush_neighbors = 0
innodb_write_io_threads = 8
innodb_read_io_threads = 8
innodb_purge_threads = 4
innodb_page_cleaners = 4
innodb_open_files = 65535
innodb_max_dirty_pages_pct = 50
innodb_flush_method = O_DIRECT
innodb_lru_scan_depth = 4000
innodb_checksum_algorithm = crc32
innodb_lock_wait_timeout = 10
innodb_rollback_on_timeout = 1
innodb_print_all_deadlocks = 1
innodb_file_per_table = 1
innodb_online_alter_log_max_size = 4G
internal_tmp_disk_storage_engine = InnoDB
innodb_stats_on_metadata = 0
innodb_status_file = 1
innodb_status_output = 0
innodb_status_output_locks = 0
performance_schema = 1
performance_schema_instrument = '%=on'
#innodb monitor
innodb_monitor_enable="module_innodb"
innodb_monitor_enable="module_server"
innodb_monitor_enable="module_dml"
innodb_monitor_enable="module_ddl"
innodb_monitor_enable="module_trx"
innodb_monitor_enable="module_os"
innodb_monitor_enable="module_purge"
innodb_monitor_enable="module_log"
innodb_monitor_enable="module_lock"
innodb_monitor_enable="module_buffer"
innodb_monitor_enable="module_index"
innodb_monitor_enable="module_ibuf_system"
innodb_monitor_enable="module_buffer_page"
innodb_monitor_enable="module_adaptive_hash"
[mysqldump]
quick
max_allowed_packet = 32M
主:172.16.20.32
從:172.16.10.21
從庫信息:
show slave status\G;
主庫:
從庫切換操做:
stop slave;
change master to master_auto_position=0,master_host='172.16.20.32', master_port=3307,master_user='rep',master_password='mysql',Master_Log_File='mysql-binlog.000007',Master_Log_Pos=194;
start slave;
主從數據庫服務器上同時,依次執行如下操做:
set global gtid_mode='on_permissive';
set global gtid_mode='off_permissive';
主從關閉GTID功能:
set global enforce_gtid_consistency=off;
set global gtid_mode=off;
把gtid_mode=off和enforce_gtid_consistency=off寫入配置文件my3307.cnf中。重啓後能夠繼續生效,並進行測試。
主從數據庫服務器同時修改如下參數:
set global enforce_gtid_consistency=warn; error log 不會出現警告信息,若是有,須要先修復,才能繼續後面操做。
set global enforce_gtid_consistency=on;
set global gtid_mode=off_permissive;
set global gtid_mode=on_permissive;
確認從庫沒等待的事務:
show global status like '%ongoing%';
0表明沒有等待的事務。
主從庫上同時設置gtid_mode=on;
set global gtid_mode=on;
show variables like '%gtid%';
把傳統複製模式改成(GTID)複製。
stop slave;
change master to master_auto_position=1;
查看並進行測試:
主:
從:
例如主庫:
從庫:
分類: MYSQL