主从复制时,从服务器开启一个io_thread线程连接到主服务器,将主服务器二进制日志中记录的内容保存到本机的中继日志中,复制时从服务器开启一个sql_thread线程,将中继日志中的内容读到内存中进行重放,完成复制操作。
一主一从
node1为主
node2为从
在node1上
vim /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
skip_name_resolve=on
innodb_file_per_table=on
log_bin=bin-log
server_id=1 #服务器标识,不能与从服务器一样
systemctl start mariadb
grant replication slave,replication client on *.* to 'kej'@'192.168.91.137' identified by '12233
3';
grant all on *.* to 'kang'@'192.168.91.137' identified by '122333';
flush privileges;
记录现在二进制日志的位置
MariaDB [(none)]> show master logs;
+----------------+-----------+
| Log_name | File_size |
+----------------+-----------+
| bin-log.000001 | 30379 |
| bin-log.000002 | 1038814 |
| bin-log.000003 | 3919 |
| bin-log.000004 | 245 |
+----------------+-----------+
在node2上
vim /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
skip_name_resolve=on
innodb_file_per_table=on
#log_bin=bin-log #二进制日志,当从服务器作为其他从服务器的主时开启
server_id=2 #服务器标识,与主的不一样
read_only=on #服务器数据只读,当从服务器作为其他从服务器的主时关闭
relay_log=relay-log
systemctl start mariadb
用mysqldump从全量备份主服务器
mysqldump -ukang -p122333 -h192.168.91.139 -A -F --single-transaction --master-data=2 --flush-privileges --triggers -E -R > backup.sql
把全量备份文件还原
mysql < backup.sql
MariaDB [(none)]> select * from mydb.mytable;
+-------+------+--------+
| name | age | gender |
+-------+------+--------+
| stu1 | 19 | m |
| stu2 | 31 | m |
| stu3 | 18 | m |
| stu4 | 31 | m |
| stu5 | 62 | m |
| stu6 | 71 | m |
| stu7 | 42 | m |
| stu8 | 20 | m |
| stu9 | 73 | m |
| stu10 | 73 | m |
| stu11 | 84 | m |
| stu12 | 75 | m |
| stu13 | 22 | m |
| stu14 | 69 | m |
| stu15 | 22 | m |
+-------+------+--------+
MariaDB [(none)]> show master logs;
+----------------+-----------+
| Log_name | File_size |
+----------------+-----------+
| bin-log.000001 | 30379 |
| bin-log.000002 | 1038814 |
| bin-log.000003 | 3919 |
| bin-log.000004 | 502 |
| bin-log.000005 | 429 |
+----------------+-----------+
在node2上
MariaDB [(none)]> change master to master_host='192.168.91.139',master_user='kej',master_password='122333',master_
port=3306,master_log_file='bin-log.000004',master_log_pos=502;
MariaDB [(none)]> start slave;
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.91.139
Master_User: kej
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: bin-log.000005
Read_Master_Log_Pos: 429
Relay_Log_File: relay-log.000003
Relay_Log_Pos: 711
Relay_Master_Log_File: bin-log.000005
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: 429
Relay_Log_Space: 1281
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
在node1上生成一些新数据,查看node2,发现数据一样,同步成功
半同步复制
半同步复制指当一个主节点有多个从节点时,其中一个或几个从节点使用同步复制的方式,其他从节点使用异步复制的方式,称为半同步复制,同步复制时客户端在访问mysql数据库并完成一个写操作后,从节点会立即将数据同步到本地并将结果反馈给主节点,证明自己已经同步完成,客户端才能进行第二次写操作,如果主节点等待从节点反馈的时间超过了规定的超时时间,这个从节点会自动降级为异步复制模方式。
前提:配置主从集群
在node1上
安装半同步插件,rpl_semi_sync_master为插件的名字,semisync_master.so为模块的名字,可以通过rpm -ql mariadb-server获得模块的名字
MariaDB [(none)]> install plugin rpl_semi_sync_master soname 'semisync_master.so';
查看已安装的插件
MariaDB [(none)]> show plugins;
开启半同步插件
MariaDB [(none)]> set global rpl_semi_sync_master_enabled=on;
MariaDB [(none)]> show global variables like '%semi%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | ON | #半同步复制已开启
| rpl_semi_sync_master_timeout | 10000 | #定义超时时长,如果10s没有反馈结果给主节点,这个从节点就自动降级为异步复制
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON | #没有从节点时是否开启同步复制
+------------------------------------+-------+
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%rpl%';
+--------------------------------------------+-------------+
| Variable_name | Value |
+--------------------------------------------+-------------+
| Rpl_semi_sync_master_clients | 0 | #目前没有从服务器
| 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 |
| Rpl_status | AUTH_MASTER |
+--------------------------------------------+-------------+
在node2上
MariaDB [(none)]> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
MariaDB [(none)]> set global rpl_semi_sync_slave_enabled=on;
MariaDB [(none)]> show global variables like '%rpl_semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
MariaDB [(none)]> show global status like '%rpl%';
+----------------------------+-------------+
| Variable_name | Value |
+----------------------------+-------------+
| Rpl_semi_sync_slave_status | OFF | #此时仍是关闭状态
| Rpl_status | AUTH_MASTER |
+----------------------------+-------------+
MariaDB [(none)]> stop slave io_thread;
MariaDB [(none)]> start slave io_thread;
MariaDB [(none)]> show global status like '%rpl%';
+----------------------------+-------------+
| Variable_name | Value |
+----------------------------+-------------+
| Rpl_semi_sync_slave_status | ON | #此时已经开启
| Rpl_status | AUTH_MASTER |
+----------------------------+-------------+
在node1上
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%rpl%';
+--------------------------------------------+-------------+
| 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 |
| Rpl_status | AUTH_MASTER |
+--------------------------------------------+-------------+
生成一些新数据
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%rpl%';
+--------------------------------------------+-------------+
| Variable_name | Value |
+--------------------------------------------+-------------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 1322 | #平均等待时间
| Rpl_semi_sync_master_net_wait_time | 5291 | #总等待时间
| Rpl_semi_sync_master_net_waits | 4 | #网络等待次数
| 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 | 1142 | #传送平均等待时间
| Rpl_semi_sync_master_tx_wait_time | 4570 | #传送等待时间
| Rpl_semi_sync_master_tx_waits | 4 | #传送等待次数
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 4 | #传送成功次数
| Rpl_status | AUTH_MASTER |
+--------------------------------------------+-------------+
复制过滤器
仅复制有限一个或几个数据库相关的数据,而非所有;由复制过滤器进行;
有两种实现思路:
(1) 主服务器
主服务器仅向二进制日志中记录有关特定数据库相关的写操作;
问题:其它库的time-point recovery将无从实现,因为二进制日志不全,所以对于其他库无法进行重放二级制日志,一般这种方法不会使用;
binlog_do_db=
binlog_ignore_db=
(2) 从服务器
从服务器的SQL _THREAD仅重放关注的数据库或表相关的事件,并将其应用于本地;
问题:网络IO和磁盘IO,因为会将所有库的数据复制到从服务器的中继日志中,只是从中继日志中重放的时候只会挑选特定的数据库或表进行重放;
Replicate_Do_DB= 只复制某个库
Replicate_Ignore_DB= 除了某个库都复制
Replicate_Do_Table=
Replicate_Ignore_Table=
Replicate_Wild_Do_Table= 可以用通配符表示表明,比如*mydb
Replicate_Wild_Ignore_Table=
事例:
在node2上
MariaDB [(none)]> show global variables like '%replicate%';
+----------------------------------+-----------+
| Variable_name | Value |
+----------------------------------+-----------+
| replicate_annotate_row_events | OFF |
| replicate_do_db | |
| replicate_do_table | |
| replicate_events_marked_for_skip | replicate |
| replicate_ignore_db | |
| replicate_ignore_table | |
| replicate_wild_do_table | |
| replicate_wild_ignore_table | |
+----------------------------------+-----------+
MariaDB [(none)]> stop slave;
MariaDB [(none)]> set global replicate_ignore_db=mydb;
MariaDB [(none)]> start slave;
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.91.139
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: bin-log.000003
Read_Master_Log_Pos: 419
Relay_Log_File: relay-log.000003
Relay_Log_Pos: 527
Relay_Master_Log_File: bin-log.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mydb #忽略mydb
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
在node1上创建mydb数据库,不会复制到node2上
复制的监控和维护
清理二进制日志:PURGE
PURGE { BINARY | MASTER } LOGS { TO ‘log_name’ | BEFORE datetime_expr };
使用purge删除二进制日志后,mysql重新启动时不会读取删除的二进制日志文件,这样不会报错
MariaDB [mydb]> show master logs;
+----------------+-----------+
| Log_name | File_size |
+----------------+-----------+
| bin-log.000001 | 30379 |
| bin-log.000002 | 1038814 |
| bin-log.000003 | 686 |
+----------------+-----------+
3 rows in set (0.00 sec)
MariaDB [mydb]> purge master logs to 'bin-log.000003';
Query OK, 0 rows affected (0.00 sec)
MariaDB [mydb]> show master logs;
+----------------+-----------+
| Log_name | File_size |
+----------------+-----------+
| bin-log.000003 | 686 |
+----------------+-----------+
1 row in set (0.00 sec)
[root@localhost ~]#ls /var/lib/mysql/
aria_log.00000001 bin-log.000003 ibdata1 ib_logfile1 mysql performance_schema test1
aria_log_control bin-log.index ib_logfile0 mydb mysql.sock test
[root@localhost ~]#cat /var/lib/mysql/bin-log.index #发现对应的数据目录下的二进制日志的索引也会被删除
./bin-log.000003
主从复制常用命令
主服务器命令
MariaDB [(none)]> show binary logs;
+----------------+-----------+
| Log_name | File_size |
+----------------+-----------+
| bin-log.000003 | 686 |
+----------------+-----------+
MariaDB [(none)]> show master logs;
+----------------+-----------+
| Log_name | File_size |
+----------------+-----------+
| bin-log.000003 | 686 |
+----------------+-----------+
MariaDB [(none)]> show master status;
+----------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+----------------+----------+--------------+------------------+
| bin-log.000003 | 686 | | |
+----------------+----------+--------------+------------------+
MariaDB [(none)]> flush logs;
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> show binary logs;
+----------------+-----------+
| Log_name | File_size |
+----------------+-----------+
| bin-log.000003 | 727 |
| bin-log.000004 | 245 |
+----------------+-----------+
MariaDB [(none)]> SHOW BINLOG EVENTS in 'bin-log.000004';
+----------------+-----+-------------+-----------+-------------+-------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+----------------+-----+-------------+-----------+-------------+-------------------------------------------+
| bin-log.000004 | 4 | Format_desc | 1 | 245 | Server ver: 5.5.56-MariaDB, Binlog ver: 4 |
+----------------+-----+-------------+-----------+-------------+-------------------------------------------+
从服务器
MariaDB [(none)]> stop slave;
MariaDB [(none)]> start slave;
MariaDB [(none)]> show slave status\G
MariaDB [(none)]> reset slave