目录
1、MySQL的主从复制是一个
异步
的复制过程(虽然一般情况下感觉是实时的),数据将从一个MySQL数据库(我们称之为Master)复制到另一个MySQL数据库(我们称之为Slave),在Master与Salve之间实现整个主从复制的过程是由三个线程
参与完成的。其中有两个线程(SQL线程
和IO线程
)在Slave端,另外一个线程(I/O线程
)在Master端。
2、要实现MySQL的主从复制,首先必须打开Master端的binlog
记录功能,否则就无法实现。因为整个复制过程实际上就是Slave从Master端获取binlog日志,然后再在Slave上以相同顺序执行获取的binlog日志中所记录的各种SQL操作。注意binlog日志只记录增删改(不记录查询语句)
3、从库IO在第一次把信息放入到relay
中后会触发SQL线程
,然后后边就交给SQL线程来处理,把binlog文件中的SQL语句解析出来后变成SQL语句放入数据库中
1)主从复制是异步的逻辑的SQL语句级的复制。
2)复制时,主库有一个I/O线程,从库有两个线程,I/O和SQL线程
3)实现主从复制的必要条件是主库要开启记录binlog功能
4)作为复制的所有MySQL节点的server-id都不能相同(0
5)binlog文件只记录对数据库有更改的SQL语句(来自主数据库内容的变更,不记录任何查询(select,show)语句。
主从复制条件
1)主库开启binlog功能(从库除非做双向复制)
2)主库建立同步账号
3)从库配置master.info(CHANGE MASTER TO …来实现)
4)复制开关:start slave
需要了解一下概念
1)3线程,主库(IO),从库IO和SQL,及作用
2)master.info作用
3)relay-log作用
4)异步复制和同步复制的区别
5)binlog作用
主库:
# 1、查看binlog功能是否开启
[root@db02 ~]# grep log-bin /data/{3306,3307}/my.cnf
/data/3306/my.cnf:log-bin = /data/3306/mysql-bin
/data/3307/my.cnf:log-bin = /data/3307/mysql-bin
# 2、查看监听端口及server-id是否一样
[root@db02 ~]# netstat -lntup |grep 330*
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 47293/mysqld
tcp 0 0 0.0.0.0:3307 0.0.0.0:* LISTEN 5804/mysqld
[root@db02 ~]# grep server-id /data/{3306,3307,3308}/my.cnf
/data/3306/my.cnf:server-id = 1
/data/3307/my.cnf:server-id = 3
/data/3308/my.cnf:server-id = 8
# 3、登录3306主数据库,授权3307 slave登录用户
mysql> grant replication slave on *.* to rep@'172.16.1.%' identified by '123456';
Query OK, 0 rows affected (0.01 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host from mysql.user;
+---------+------------+
| user | host |
+---------+------------+
| root | 127.0.0.1 |
| rep | 172.16.1.% |
| oldboy2 | localhost |
| root | localhost |
| test | localhost |
| test2 | localhost |
+---------+------------+
6 rows in set (0.00 sec)
mysql> show grants for rep@'172.16.1.%';
+-------------------------------------------------------------------------------------------------------------------------+
| Grants for [email protected].% |
+-------------------------------------------------------------------------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO 'rep'@'172.16.1.%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' |
+-------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
# 4、锁表,查看binlog文件及位置点
mysql> flush table with read lock;
Query OK, 0 rows affected (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000010 | 2892 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
# 5、新开窗口全备数据(下边可能会报错,由于mysql5.5之后添加了新特性,实验环境可以不锁表操作)
[root@db02 ~]# mysqldump -uroot -p123456 -A -B --events -S /data/3306/mysql.sock |gzip >/server/backup/req_$(date +%F).sql.gz
mysqldump: Got error: 1142: SELECT,LOCK TABL command denied to user 'root'@'localhost' for table 'cond_instances' when using LOCK TABLES
[root@db02 backup]# ll
total 152
-rw-r--r-- 1 root root 152756 Jun 9 14:02 req_2018-06-09.sql.gz
# 6、解锁
mysql> unlock table;
Query OK, 0 rows affected (0.00 sec)
从库:
# 确保server-id不同
[root@db02 ~]# grep log-bin /data/{3306,3307}/my.cnf
/data/3306/my.cnf:log-bin = /data/3306/mysql-bin
/data/3307/my.cnf:log-bin = /data/3307/mysql-bin
# 开启服务
/data/3307/mysql start
# 把主库的全备导入到从库
[root@db02 backup]# gzip -d /server/backup/req_2018-06-09.sql.gz
[root@db02 backup]# ls
req_2018-06-09.sql
[root@db02 backup]# mysql -uroot -p123456 -S /data/3307/mysql.sock
[root@db02 backup]# mysql -uroot -p123456 -S /data/3307/mysql.sock
# 找位置点,配置master.info文件
# (若change master内容有误,不要修改master.info文件,直接reset slave all)
CHANGE MASTER TO
MASTER_HOST='172.16.1.52',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000010',
MASTER_LOG_POS=2892;
[root@db02 ~]# ll /data/3307/data/master.info
-rw-rw---- 1 mysql mysql 77 Jun 9 14:15 /data/3307/data/master.info
[root@db02 ~]# cat /data/3307/data/master.info
18
mysql-bin.000010
2892
172.16.1.52
rep
123456
3306
60
0
0
1800.000
0
# 开启从库开关
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.1.52
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000010
Read_Master_Log_Pos: 3194
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 555
Relay_Master_Log_File: mysql-bin.000010
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
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: 3194
Relay_Log_Space: 705
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
1 row in set (0.00 sec)
mysql>
测试:
# 主库创建数据库
mysql> create database rsq123;
Query OK, 1 row affected (0.00 sec)
# 从库查看
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| oldboy |
| oldgirl |
| performance_schema |
| rsq123 |
| test |
+--------------------+
7 rows in set (0.00 sec)
和上边实验不同步,此为后来添加的
主库:
1、开启binlog功能
2、确保所有实例server-id不同
3、授权复制的用户rep(grant replication slave on . to rep@’172.16.1.%’ identified by ‘123456’;)
4、锁表(flush table with read lock;),查看binlog文件及位置点(show master status;/–master-data=2)
5、新开窗口导出全备(mysqldump -uroot -p123456 -A -B –events -S /data/3306/mysql.sock |gzip >/server/backup/req_$(date +%F).sql.gz)
6、解锁,开放用户写入功能(unlock table)
从库
1、确保所有实例server-id不同
2、把主库的全备导入到从库
3、找位置点,配置master.info
CHANGE MASTER TO
MASTER_HOST=’172.16.1.52’,
MASTER_PORT=3306,
MASTER_USER=’rep’,
MASTER_PASSWORD=’123456’,
MASTER_LOG_FILE=’mysql-bin.000010’,
MASTER_LOG_POS=2892;
4、start slave;show slave status\G
若出现slave中的两线程状态为YES,基本上就成功了
# 先备份前一个从库数据,用--master-data=2参数,可以省去锁表的步骤
mysqldump -uroot -p123456 -S /data/3306/mysql.sock -A -B -R -F -x --master-data=2 --events|gzip >/server/backup/rep3308_$(date +%F).sql.gz
# 解压后导入新的从库
gzip -d /server/backup/rep3308_2018-06-09.sql.gz
mysql -uroot -p123456 -S /data/3308/mysql.sock 06-09.sql
# 查找解压后的sql文件,查找CHANGE,复制出来
vim /server/backup/rep3308_2018-06-09.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000011', MASTER_LOG_POS=107;
# 分别执行两条CHANGE
CHANGE MASTER TO
MASTER_HOST='172.16.1.52',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='123456';
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000011', MASTER_LOG_POS=107;
# 开启slave
start slave;
show slave status\G
# 完事
# 出现SQL线程问题
mysql> show slave status\G
... ...
Slave_IO_Running: Yes
Slave_SQL_Running: No
... ...
Last_SQL_Errno: 1008
Last_SQL_Error: Error 'Can't drop database 'rsq'; database doesn't exist' on query. Default database: 'rsq'. Query: 'drop database rsq'
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
stop slave;
set global sql_slave_skip_counter = 1; # 将同步指针向下移动一个,如果多次不同步,可以重复操作,增大指针值都可以。
start slave;
# 方法二:把Last_SQL_Errno值给提前加入配置文件中,这样再有类似错误值的报错就直接忽略了
grep slave-skip /data/3306/my.cnf
slave-skip-errors = 1032,1062,1007
Last_SQL_Errno错误代码集
其他可能引起复制故障的问题: