前言:
MySQL内建的复制功能是构建大型,高性能应用程序的基础
通过将MySQL的某一台主机(master)的数据复制到其他主机(slaves)上,并重新执行一遍来执行
复制过程中一台服务器充当主服务器,而其他一个或多个其他服务器充当从服务器
简单来说:就是在开启主从复制后,从库将主库日志复制过来放到自己的中继日志然后将此日志
目录
- 1、MySQL支持的复制类型
- 2、为什么要做主从复制
- 3、主从复制基本架构
- 4、主从复制原理
- 5、MySQL复制常用的拓扑结构
- 配置MySQL数据库一主两从的主从复制
- 环境准备
- 1)设置server-id值并开启binlog参数
- 2)在从服务器上需要开启的功能
- 3) 建立同步账号
- 4)锁表设置只读
- 5)查看主库状态 这一步很重要,后续很需要
- 6)备份数据库数据(在mysql执行Linux命令需要加上system)
- 7)将备份的数据库通过scp传递给另外两台从服务器
- 8)在另外两台从主机上解压传递到的数据库
- 9)设定从库与主库同步
- 10)启动从库同步开关,和查看从库信息
- 6、主从状况监测主要参数
- 7、常见状态错误排除
- 8、生产环境其他常用设置
1、MySQL支持的复制类型
基于语句(statement)的复制
在主服务器上执行SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。
基于行(row)的复制
把改变的内容复制过去,而不是把命令在从服务器上执行一遍。从MySQL 5.0开始支持。
混合型(mixed)的复制
默认采用基于语句的复制,一旦发现基于语句的无法精确复制时,就会采用基于行的复制。
2、为什么要做主从复制
灾备
数据分布
负载平衡
读写分离
提高并发能力
3、主从复制基本架构
主从复制基本架构图:
4、主从复制原理
主要基于MySQL二进制日志
主要包括三个线程(2个I/O线程,1个SQL线程)
主从复制原理图
1、MySQL将数据变化记录到二进制日志中;//也就是bin-log日志中
2、Slave将MySQL的二进制日志拷贝到Slave的中继日志中;
3、Slave将中继日志中的事件在做一次,将数据变化,反应到自身(Slave)的数据库
详细步骤:
1、从库通过手工执行change master to 语句连接主库,提供了连接的用户一切条件
(user 、password、port、ip),并且让从库知道,二进制日志的起点位置(file名 position 号); start slave
2、从库的IO线程和主库的dump线程建立连接。
3、从库根据change master to 语句提供的file名和position号,IO线程向主库发起binlog的请求。
4、主库dump线程根据从库的请求,将本地binlog以events的方式发给从库IO线程。
5、从库IO线程接收binlog events,并存放到本地relay-log中,传送过来的信息,会记录到master.info中
6、从库SQL线程应用relay-log,并且把应用过的记录到relay-log.info中,默认情况下,已经应用过的relay 会自动被清理purge
开启之后
检查主库的my.cnf有没有开启bin-log日志,然后检查主库有没有配置server-id
检查主库有没有对同步用户进行授权;
5、MySQL复制常用的拓扑结构
主从类型(Master-Slave)
主主类型(Master-Master)
级联类型(Master-Slave-Slave)
配置MySQL数据库一主两从的主从复制
环境准备
两台机器一主一从。
主库(MySQL Master):[ip为192.168.95.120 port为3306]
从库(MySQL Slave ) :[ip为192.168.95.130 port为3306]
主库配置
1)设置server-id值并开启binlog参数
(每一个主机都要开启,并且server-id不能一样)
vim /etc/my.cnf
[mysqld]
log_bin = mysql-bin
server_id = 11
2)在从服务器上需要开启的功能
//开启日志功能
slow_query_log=ON
slow_query_log_file=/var/lib/mysql/node1-slow.log
long_query_time=3
#开启日志文件和server id
log_bin=mysql-bin
server_id=12
//开启GTID
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
重启数据库
3) 建立同步账号
在主库上建立同步账号
mysql> grant replication slave on *.* to 'rep'@'192.168.142.%' identified by '123456';
mysql> show grants for 'rep'@'192.168.142.%';
4)锁表设置只读
为后面备份准备,注意生产环境要提前申请停机时间;
mysql> flush tables with read lock;
提示:如果超过设置时间不操作会自动解锁。
mysql> show variables like '%timeout%';
+-----------------------------+----------+
| Variable_name | Value |
+-----------------------------+----------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| have_statement_timeout | YES |
| innodb_flush_log_at_timeout | 1 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 | //等待时间很长也可以自己解锁
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 60 |
| wait_timeout | 28800 |
+-----------------------------+----------+
13 rows in set (0.16 sec)
5)查看主库状态 这一步很重要,后续很需要
查看主库状态,即当前日志文件名和二进制日志偏移量
主从复制会基于mysql-bin 来复制
mysql> show master status;
+------------------+----------+--------------+------------------+----------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+----------------------------------------------+
| mysql-bin.000017 | 22989540 | | | 5df41ab1-ad1b-11ec-84f9-000c290eccc5:1-80175 |
+------------------+----------+--------------+------------------+----------------------------------------------+
1 row in set (0.00 sec)
6)备份数据库数据(在mysql执行Linux命令需要加上system)
创建目录备份到此目录并添加时间备份
mysql> system mkdir -p /server/backup
mysql> system mysqldump -uroot -p -A -B |gzip > /server/backup/mysql_bak.$(date +%F).sql.gz
Enter password:
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events.
mysql>
7)将备份的数据库通过scp传递给另外两台从服务器
[root@node1 ~]# scp /server/backup/mysql_bak.$(date +%F).sql.gz 192.168.142.154:/root
root@192.168.142.154's password:
mysql_bak.2022-05-08.sql.gz
[root@node1 ~]# scp /server/backup/mysql_bak.$(date +%F).sql.gz 192.168.142.139:/root
root@192.168.142.139's password:
mysql_bak.2022-05-08.sql.gz
8)在另外两台从主机上解压传递到的数据库
[root@node2 ~]# zcat mysql_bak.2022-05-08.sql.gz | mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@node3 ~]# zcat mysql_bak.2022-05-08.sql.gz | mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
在另外的两台从库上配置
9)设定从库与主库同步
mysql> change master to
-> master_host='192.168.142.153',
-> master_user='rep',
-> master_password='123456',
-> master_log_file='mysql-bin.000017',
-> master_log_pos=22989540;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> change master to
-> master_host='192.168.142.153',
-> master_user='rep',
-> master_password='123456',
-> master_log_file='mysql-bin.000017',
-> master_log_pos=22989540;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
10)启动从库同步开关,和查看从库信息
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)
检查状态:
mysql> show slave status\G
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.142.153
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000017
Read_Master_Log_Pos: 22989540
Relay_Log_File: node3-relay-bin.000003
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000017
Slave_IO_Running: Yes //主要看这两个有没有开启yes
Slave_SQL_Running: Yes //主要看这两个有没有开启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: 22989540
Relay_Log_Space: 527
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: 11
Master_UUID: 5df41ab1-ad1b-11ec-84f9-000c290eccc5
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 more updates
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: 5df41ab1-ad1b-11ec-84f9-000c290eccc5:1-80175
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
ERROR:
No query specified
6、主从状况监测主要参数
Slave_IO_Running: IO线程是否打开 YES/No/NULL
Slave_SQL_Running: SQL线程是否打开 YES/No/NULL
Seconds_Behind_Master: NULL #和主库比同步的延迟的秒数
配置完成后可以创建数据库查看主从同步信息
主库上创建数据库test
从库1上查询数据库test
在从库2上查询是否有test数据库
7、常见状态错误排除
发现IO进程错误,检查日志,排除故障:
# tail localhost.localdomain.err
...
2015-11-18 10:55:50 3566 [ERROR] Slave I/O: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. Error_code: 1593
找到原因:从5.6开始复制引入了uuid的概念,各个复制结构中的server_uuid得保证不一样
解决方法:(从库是克隆机器)
修改从库的uuid
[root@node1 ~]# vim /var/lib/mysql/auto.cnf
server-uuid= //这里数字可以改一下;位数要一样长,一定不能删除
常见状态错误排除
show slave status;报错:Error xxx doesn’t exist
解决方法:
stop slave;
set global sql_slave_skip_counter = 1;
start slave;
8、生产环境其他常用设置
1、配置忽略权限库同步参数(设置某些数据库不想同步过去的)
binlog-ignore-db='information_schema mysql test'
2、从库备份开启binlog
log-slave-updates
log_bin = mysql-bin
expire_logs_days = 7(日志保存时间)
应用场景:级联复制或从库做数据备份。
3、从库只读
read-only来实现
innodb_read_only = ON或1,或者innodb_read_only
结论:当用户权限中没有SUPER权限(ALL权限是包括SUPER的)时,从库的read-only生效!