以下: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