专职DBA-MySQL主从异步复制
MySQL主从复制企业级应用场景
1.从服务器作为主服务器的实时数据备份。
2.主从服务器实现读写分离,从服务器实现负载均衡。
3.根据业务重要性对多个从服务器进行拆分访问。
MySQL主从读写分离实现方案
1.通过开发程序实现读写分离(需要程序支持)
2.通过开源的软件实现读写分离。
3.大型门户独立开发DAL层综合软件。
mysql主从复制原理重点小结:
1.主从复制是异步的逻辑的SQL语句级的复制。
2.复制时,主库有一个binlog dump线程,从库有两个线程,I/O线程和SQL线程。
3.从mysql 5.6起,slave从库的SQL线程可以是多个。
4.实现主从复制的必要条件是主库要开启记录binlog的功能。
5.用于复制的所有mysql节点配置中的server-id都不能相同。
6.binlog文件只记录对数据库有更改的SQL语句(来自主库内容的更改),不记录任何(select,show)查询以及未对数据库做出更改的语句。
链接克隆两台主机,模板机安装请参考install_linux_os.sh
VMware克隆Centos6.4虚拟机网卡无法启动问题
# cat /etc/sysconfig/network-scripts/ifcfg-eth0
# sed -i '/UUID/d' /etc/sysconfig/network-scripts/ifcfg-eth0
# sed -i '/HWADDR/d' /etc/sysconfig/network-scripts/ifcfg-eth0
# >/etc/udev/rules.d/70-persistent-net.rules
# reboot
如果是克隆安装好的mysql虚拟机,还要修改数据目录下auto.cnf文件的UUID
/data/mysql/3306/data/auto.cnf
MySQL数据目录中通常存在一个名为auto.cnf文件,存储了server-uuid的值,
MySQL启动时,会自动从data_dir/auto.cnf 文件中获取server-uuid值,并将这个值存储在全局变量server_uuid中。
如果这个值或者这个文件不存在,那么将会生成一个新的uuid值,并将这个值保存在auto.cnf文件中。
server-uuid与server-id一样,用于标识MySQL实例在集群中的唯一性,这两个参数在主从复制中具有重要作用,
默认情况下,如果主从库的server-uuid或者server-id的值一样,将会导致主从复制报错中断。
你可以把auto.cnf删除或者mv走,数据库启动会自动生成auto.cnf
主、从库server-uuid值一样,导致主从复制异常中断
主、从库server-id值一样,同样导致主从复制异常中断
参考文章https://www.jianshu.com/p/2347b1a9eacd
参考文章https://www.jianshu.com/p/2347b1a9eacd
主机规划
数据库角色 主机名 bond0(ssh连接ip) bond1(内网通信ip) 数据库端口
主库master db01 10.0.0.11 192.168.10.11 3306
从库slave db02 10.0.0.12 192.168.10.12 3306
按照专职DBA数据库安装文档,先把数据库安装上。
[root@db01 ~]# vim /etc/my.cnf
[mysql]
#prompt ="\\u@\\h [\\d]> \"
#prompt ="mysql [\\d]> \"
prompt ="Master [\\d]> \"
#prompt ="Slave [\\d]> \"
[root@db02 ~]# vim /etc/my.cnf
[mysql]
#prompt ="\\u@\\h [\\d]> \"
#prompt ="mysql [\\d]> \"
#prompt ="Master [\\d]> \"
prompt ="Slave [\\d]> \"
数据库配置文件示例
[root@db01 ~]# cat /data/mysql/3306/my.cnf
[mysqld]
# for mysql global
user = mysql
basedir = /usr/local/mysql
datadir = /data/mysql/3306/data
tmpdir = /data/mysql/3306/tmp
pid_file = /data/mysql/3306/3306.pid
socket = /data/mysql/3306/mysql.sock
port = 3306
server_id = 113306
character-set-server = utf8
# for binlog
binlog_format = row
log_bin = /data/mysql/3306/logs/mysql-bin
# for error log
log_error = /data/mysql/3306/error.log
# general log
general_log = off
general_log_file = /data/mysql/3306/general.log
# for slow query log
slow_query_log = on
slow_query_log_file = /data/mysql/3306/slow.log
long_query_time = 1.000000
# for gtid
gtid_mode = on
enforce_gtid_consistency = on
# for replication
# for innodb
[mysql]
character-set-client = utf8
#prompt ="\\u@\\h [\\d]> \"
#prompt ="mysql [\\d]> \"
#prompt ="Master [\\d]> \"
#prompt ="Slave [\\d]> \"
检查数据库的当前状态
[root@db01 ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf &
[1] 6735
[root@db01 ~]# ss -tunlp | grep mysql
tcp LISTEN 0 80 :::3306 :::* users:(("mysqld",pid=6735,fd=34))
[root@db01 ~]# netstat -tunlp | grep mysql
tcp6 0 0 :::3306 :::* LISTEN 6735/mysqld
[root@db01 ~]# lsof -i :3306
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 6735 mysql 34u IPv6 35637 0t0 TCP *:mysql (LISTEN)
[root@db01 ~]# lsof -i :mysql
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 6735 mysql 34u IPv6 35637 0t0 TCP *:mysql (LISTEN)
[root@db01 ~]# ps -aux | grep mysql
mysql 6735 2.0 35.0 1118452 171692 pts/0 Sl 06:02 0:01 mysqld --defaults-file=/data/mysql/3306/my.cnf
root 6787 0.0 0.1 112708 976 pts/0 R+ 06:03 0:00 grep --color=auto mysql
[root@db01 ~]# ps -ef | grep mysql
mysql 6735 6697 1 06:02 pts/0 00:00:01 mysqld --defaults-file=/data/mysql/3306/my.cnf
root 6790 6697 0 06:03 pts/0 00:00:00 grep --color=auto mysql
[root@db02 ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf &
[1] 6761
[root@db02 ~]# ps -ef | grep mysql
mysql 6761 6739 10 06:04 pts/0 00:00:01 mysqld --defaults-file=/data/mysql/3306/my.cnf
root 6790 6739 0 06:04 pts/0 00:00:00 grep --color=auto mysql
在主库master上执行操作配置
1.设置server_id的值,并开启binlog功能参数
(1).修改主库的配置文件/etc/my.cnf
[root@db01 ~]# egrep "server_id|log_bin" /data/mysql/3306/my.cnf
server_id = 113306
log_bin = /data/mysql/3306/logs/mysql-bin
(2).登录数据库检查参数的更改情况
[root@db01 ~]# mysql -S /data/mysql/3306/mysql.sock -p
Master [(none)]> show global variables like "server_id";
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| server_id | 113306 |
+---------------+--------+
1 row in set (0.00 sec)
Master [(none)]> show global variables like "log_bin";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.01 sec)
2.在主库上创建用于主从复制的账号
从库要想与主库同步,必须要有一个可以连接主库的账号,并且这个账号是在主库上创建的,权限是允许从库连接主库并同步数据。
Master [(none)]> grant replication slave on *.* to 'rep'@'192.168.10.%' identified by '123';
Query OK, 0 rows affected, 1 warning (0.00 sec)
Master [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)
Master [(none)]> select user,host from mysql.user;
+---------------+--------------+
| user | host |
+---------------+--------------+
| rep | 192.168.10.% |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+---------------+--------------+
4 rows in set (0.00 sec)
Master [(none)]> show grants for 'rep'@'192.168.10.%';
+--------------------------------------------------------+
| Grants for rep@192.168.10.% |
+--------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO 'rep'@'192.168.10.%' |
+--------------------------------------------------------+
1 row in set (0.00 sec)
3、对主库锁表只读后进行备份(当前窗口不要关闭)
(1).对主库锁表只读
Master [(none)]> reset master;
Query OK, 0 rows affected (0.01 sec)
Master [(none)]> flush table with read lock;
Query OK, 0 rows affected (0.01 sec)
a.窗口关闭后锁表会失效。
b.超时参数设置的时间到了,锁表也会失效。
对于不同引擎,这个锁表命令的时间会受到下面参数的控制。锁表时,如果超过了设置的时间则会自动解锁。
Master [(none)]> 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.00 sec)
(2).锁表后查看主库的状态
Master [(none)]> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
(3).导出主库数据
锁表后,一定要再打开一个CRT窗口去操作
[root@db01 ~]# mysqldump -S /data/mysql/3306/mysql.sock -p -A -B |gzip > /backup/bak_$(date +%F).sql.gz
也可以加上-x --master-data=1就可以在从库配置复制参数的时候省去以下两个参数:
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=407;
[root@db01 ~]# ls -l /backup/
total 200
-rw-r--r-- 1 root root 196911 Jul 15 06:25 bak_2019-07-15.sql.gz
drwxr-xr-x 2 root root 29 Jul 12 03:50 conf
-rw-r--r-- 1 root root 2243 Jul 15 05:28 eth0123.zip
drwxr-xr-x 2 root root 54 Jul 12 05:39 sh
drwxr-xr-x 2 root root 49 Jul 12 03:52 sql
为了确保导出数据期间,数据库没有数据插入操作,导库完毕后再检查一下主库的状态信息。
Master [(none)]> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
(4).导出数据完毕后,解锁主库,恢复可写,因为主库还要对外提供服务,因此不能一直锁定不让用户访问吧。
Master [(none)]> unlock tables;
Query OK, 0 rows affected (0.00 sec)
4.把主库导出的mysql数据迁移到从库
[root@db01 ~]# ping -c 3 192.168.10.12
PING 192.168.10.12 (192.168.10.12) 56(84) bytes of data.
64 bytes from 192.168.10.12: icmp_seq=1 ttl=64 time=0.633 ms
64 bytes from 192.168.10.12: icmp_seq=2 ttl=64 time=0.718 ms
64 bytes from 192.168.10.12: icmp_seq=3 ttl=64 time=0.543 ms
--- 192.168.10.12 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.543/0.631/0.718/0.074 ms
[root@db01 ~]# scp -rp /backup/bak_$(date +%F).sql.gz root@192.168.10.12:/backup/
The authenticity of host '192.168.10.12 (192.168.10.12)' can't be established.
ECDSA key fingerprint is SHA256:auBeaQTHqMvqa5fgR9w9UDEho26UWpxRqc0bHUwCv/Y.
ECDSA key fingerprint is MD5:fc:ad:3a:4d:d7:83:20:a5:a1:49:c6:59:39:0b:1c:e5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.10.12' (ECDSA) to the list of known hosts.
root@192.168.10.12's password:
bak_2019-07-15.sql.gz 100% 192KB 16.0MB/s 00:00
在slave从库上执行的操作过程
1.设置server_id的值,并关闭binlog功能参数
从库的server_id不能与主库以及其他从库一样,并且需要注释掉从库binlog参数配置。
这里开启binlog反而会增加从库磁盘I/O的压力。
以下两种情况需要开启从库的binlog参数配置,记录数据库更新的sql语句:
•级联同步复制A--->B--->C,中间的B数据库服务需要开启binlog记录功能。
•在从库中做数据库备份时需要开启binlog记录功能。因为数据库备份必须要有全备和binlog日志,才是完整的备份。
(1).修改配置文件
[root@db02 ~]# egrep "server_id|log_bin" /data/mysql/3306/my.cnf
server_id = 123306
#log_bin = /data/mysql/3306/logs/mysql-bin
(3).重启从库
[root@db02 ~]# mysqladmin -S /data/mysql/3306/mysql.sock -p shutdown
[root@db02 ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf &
(4).登录数据库检查参数的改变情况
[root@db02 ~]# mysql -S /data/mysql/3306/mysql.sock -p
Enter password:
Slave [(none)]> show global variables like "server_id";
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| server_id | 123306 |
+---------------+--------+
1 row in set (0.03 sec)
Slave [(none)]> show global variables like "log_bin";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | OFF |
+---------------+-------+
1 row in set (0.01 sec)
2.将刚才主库mysqldump导出的数据恢复到从库
[root@db02 ~]# zcat /backup/bak_2019-07-15.sql.gz | mysql -S /data/mysql/3306/mysql.sock -p
Enter password:
3.登录从库配置复制参数
CHANGE MASTER TO
MASTER_HOST='192.168.10.11',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='123',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
参数的值不能有空格!!!
Slave [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.10.11',
-> MASTER_PORT=3306,
-> MASTER_USER='rep',
-> MASTER_PASSWORD='123',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
以上操作原理是把用户密码等信息写入从库新的master.info文件中
[root@db02 ~]# ls -l /data/mysql/3306/data/master.info
-rw-r----- 1 mysql mysql 86 Jul 15 06:37 /data/mysql/3306/data/master.info
[root@db02 ~]# cat /data/mysql/3306/data/master.info
25
mysql-bin.000001
154
192.168.10.11
rep
123
3306
60
0
0
30.000
0
86400
0
4.启动从库同步开关并测试主从复制
(1).启动从库主从复制开关,并查看复制状态。
Slave [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)
Slave [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.11
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 154
Relay_Log_File: db02-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
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: 154
Relay_Log_Space: 526
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: 113306
Master_UUID: 7c145945-a680-11e9-baea-000c29a14cf7
Master_Info_File: /data/mysql/3306/data/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:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
[root@db02 ~]# mysql -S /data/mysql/3306/mysql.sock -p -e "show slave status\G;"|egrep "IO_Running|SQL_Running:|_Behind_Master"
Enter password:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0 #0表示状态已经同步
测试主从同步,在主库写入数据。
Master [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
Master [(none)]> create database shenzhen;
Query OK, 1 row affected (0.00 sec)
Master [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| shenzhen |
| sys |
+--------------------+
5 rows in set (0.00 sec)
Slave [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| shenzhen |
| sys |
+--------------------+
5 rows in set (0.01 sec)
Master [shenzhen]> create table t1(id int);
Query OK, 0 rows affected (0.03 sec)
Master [shenzhen]> insert into t1(id) values(1);
Query OK, 1 row affected (0.04 sec)
Slave [(none)]> select * from shenzhen.t1;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
Master [(none)]> show slave hosts;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 123306 | | 3306 | 113306 | ab0bfc5a-a681-11e9-bf5d-000c296165a9 |
+-----------+------+------+-----------+--------------------------------------+
1 row in set (0.00 sec)
Master [(none)]> show processlist;
+----+------+---------------------+------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+---------------------+------+-------------+------+---------------------------------------------------------------+------------------+
| 6 | root | localhost | NULL | Query | 0 | starting | show processlist |
| 8 | rep | 192.168.10.12:55924 | NULL | Binlog Dump | 270 | Master has sent all binlog to slave; waiting for more updates | NULL |
+----+------+---------------------+------+-------------+------+---------------------------------------------------------------+------------------+
2 rows in set (0.00 sec)
[root@db01 ~]# cat /data/mysql/3306/data/auto.cnf
[auto]
server-uuid=7c145945-a680-11e9-baea-000c29a14cf7
[root@db02 ~]# mysql -S /data/mysql/3306/mysql.sock -p -e "show slave status\G;"|egrep "Master_UUID"
Enter password:
Master_UUID: 7c145945-a680-11e9-baea-000c29a14cf7
5.MySQL主从复制线程状态说明及用途
(1).登录主库查看mysql主从复制线程状态说明
Master [(none)]> show full processlist;
+----+------+---------------------+------+-------------+------+---------------------------------------------------------------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+---------------------+------+-------------+------+---------------------------------------------------------------+-----------------------+
| 6 | root | localhost | NULL | Query | 0 | starting | show full processlist |
| 8 | rep | 192.168.10.12:55924 | NULL | Binlog Dump | 386 | Master has sent all binlog to slave; waiting for more updates | NULL |
+----+------+---------------------+------+-------------+------+---------------------------------------------------------------+-----------------------+
2 rows in set (0.00 sec)
Master [(none)]> show full processlist\G
*************************** 1. row ***************************
Id: 6
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: starting
Info: show full processlist
*************************** 2. row ***************************
Id: 8
User: rep
Host: 192.168.10.12:55924
db: NULL
Command: Binlog Dump #用于复制的主库线程
Time: 401
State: Master has sent all binlog to slave; waiting for more updates #当前状态
Info: NULL
2 rows in set (0.00 sec)
(2).登录从库查看mysql主从复制线程状态说明
Slave [(none)]> show processlist\G
*************************** 1. row ***************************
Id: 2
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: starting
Info: show processlist
*************************** 2. row ***************************
Id: 4
User: system user
Host:
db: NULL
Command: Connect
Time: 510
State: Waiting for master to send event #线程已经连接上主服务器,正在等待二进制binlog日志事件的到达。
Info: NULL
*************************** 3. row ***************************
Id: 5
User: system user
Host:
db: NULL
Command: Connect
Time: 319
State: Slave has read all relay log; waiting for more updates
Info: NULL
3 rows in set (0.00 sec)
6.主从复制存在的问题
(1).主库show master status;没有返回状态结果
原因是binlog功能没打开或者没生效。
(2).change master to的时候参数不能有空格。
(3).mysql服务无法启动
数据库目录权限和用户属主问题,数据库目录使用mysql用户。
my.cnf文件参数出错。
数据库初始化有问题,需要重新初始化。
(4).先在从库创建一个库,然后在主库创建同名的库,导致主从数据冲突。
stop slave;
set global sql_slave_skip_counter=1;
start slave;
(5).mysql自身的原因,以及人为重复插入数据。
(6).不同的数据库版本会引起不同步,主从数据库版本不一致。
(7).mysql运行错误,或者程序有bug.
(8).binlog记录模式,例如row level模式就比默认的语句模式要好。
来源:https://www.cnblogs.com/zhouwanchun/p/11186312.html