大家好,我是冰河~~
今天是《MySQL核心知识》专栏的第18章,今天为大家系统的讲讲MySQL中的复制特性,希望通过本章节的学习,小伙伴们能够举一反三,彻底掌握MySQL中复制相关的知识。好了,开始今天的正题吧。
MySQL复制简介
MySQL 从3.25.15版本开始提供数据库复制功能(replication)。MySQL复制是指从一个MySQL主服务器(MASTER)将数据复制到另一台或多台MySQL从服务器(SLAVE)的过程,将主数据库的DDL和DML操作通过二进制日志传到复制服务器上,然后在从服务器上对这些日志重新执行,从而使从服务器的数据保持同步。
在MySQL中,复制操作是异步进行的,slave服务器不需要持续的保持连接接收master服务器的数据MySQL支持一台主服务器同时向多台从服务器进行复制操作,从服务器同时可以作为其他从服务器的主服务器,如果MySQL主服务器访问量大,可以通过复制数据,然后在从服务器上进行查询操作,从而降低主服务器的访问压力(读写分离),同时从服务器作为主服务器的备份,可以避免主服务器因为故障数据丢失的问题。
MySQL数据库复制操作大致可以分为三个步骤
1、主服务器将数据的改变记录到二进制日志(binlog)中。
2、从服务器将主服务器的binary log events复制到他的中继日志(relay log)中。
3、从服务器做中继日志中的事件,将数据的改变与从服务器保持同步。
首先,主服务器会记录二进制日志,每个事务更新完毕数据之前,主服务器将这些操作的信息记录在二进制日志里面,在事件写入
二进制日志完成后,主服务器 通知存储引擎提交事务。SLAVE上面的I/O进程连接上MASTER,并发出日志请求,MASTER接收到来自SLAVE的I/O进程的请求后,通过负责复制的I/O进程根据请求信息读取指定日志位置之后的日志信息,返回给SLAVE的I/O进程。
返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到MASTER端的binlog文件的名称以及binlog的位置SLAVE的I/O进程接收到信息后,将接收到的日志内容依次添加到SLAVE端的relay-log文件的最末端,并将读取到的MASTER端的binlog文件名和位置记录到master-Info文件中。
SLAVE的SQL进程检测到relay-log中新增了内容后,会马上解析relay-log的内容成为在master端真实执行时候的那些可执行内容,并在自身执行mysql复制环境,90%以上都是一个master带一个或者多个slave的架构模式。如果master和slave压力不是太大的话,异步复制的延时一般都很少。尤其是slave端的复制方式改成两个进程处理之后,更是减少了slave端的延时。
❝提示:对于数据实时性要求不是特别严格的应用,只需要通过廉价的电脑服务器来扩展slave的数量,将读压力分散到多台slave的机器上面即可解决数据库端的读压力瓶颈。这在很大程度上解决了目前很多中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在使用类似方案解决数据库瓶颈问题。 ❞
Windows环境下的MySQL主从复制
本章,主要在Windows环境下演示MySQL的主从复制。
复制前的准备工作
在Windows环境下,如果想实现主从复制需要准备的操作环境。
角色 | IP | 端口 | 操作系统 | MySQL版本 |
---|---|---|---|---|
Master | 192.168.1.100 | 3306 | Win7 | 5.7 |
Slave | 192.168.1.102 | 3306 | Win10 | 5.7 |
Windows环境下实现主从复制
准备好两台安装MySQL5.7的服务器,即可实现两台MySQL服务器主从复制备份操作。
具体操作步骤如下:
1、在Windows下安装好两台MySQL服务器,配置好两台主机的ip地址,实现两台计算机可以网络连通
2、配置master的相关配置信息,在master主机上开启binlog日志,首先,看下datadir的具体路径。
代码语言:javascript复制show variables LIKE '�tadir%'
3、此时需要打开在D:Program Files (x86)MySQLMySQL Server 5.7路径下的配置文件my.ini,添加如下代码,开启binlog功能
代码语言:javascript复制[mysqld]
log-bin="D:/MYSQLDataBase/binlog"
expire_logs_days=10
max_binlog_size=100M
提示:此事我们需要在D盘下面创建MYSQLDATABASE文件夹,binlog日志记录在该文件夹里面,该配置文件中的其他参数如下所示
- expire_logs_days:表示二进制日志文件删除的天数
- max_binlog_size:表示二进制日志文件最大的大小
4、登录mysql后,可以执行show VARIABLES LIKE '%log_bin%'命令来测试下log_bin是否成功开启
代码语言:javascript复制show VARIABLES LIKE '%log_bin%';
如果log_bin参数是ON的话,那么表示二进制日志文件已经成功开启,如果为OFF的话,那么表示二进制日志文件开启失败
5、在master上配置复制所需要的账户,这里创建一个repl的用户,%表示任何远程地址的repl用户都可以连接master主机。
代码语言:javascript复制GRANT replication slave ON *.*TO repl@'%' IDENTIFIED BY '123';
flush privileges;
6、在my.ini配置文件里配置master主机的相关信息
代码语言:javascript复制[mysqld]
log-bin="D:/MYSQLDataBase/binlog"
expire_logs_days=10
max_binlog_size=100M
server-id=1
binlog-do-db=test
binlog-ignore-db=mysql
这些配置语句的含义
- server-id:表示服务器表示id号,master和slave主机的server-id不能一样
- binlog-do-db:表示需要复制的数据库,这里以test库为例
- binlog-ignore-db:表示不需要复制的数据库
7、重启master主机上的mysql服务,然后输入show master status命令查询master主机的信息
8、将master主机的数据备份出来,然后导入到slave主机中去,具体执行语句如下
代码语言:javascript复制mysqldump -u root -p -h 127.0.0.1 test >D:TEST.TXT
TEST库里面的表和数据
innodb_monitor表是没有数据的
dump出来的txt文件内容
代码语言:javascript复制-- MySQL dump 10.13 Distrib 5.7.20, for Win32 (x86)
--
-- Host: 127.0.0.1 Database: test
-- ------------------------------------------------------
-- Server version 5.7.20-log
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE=' 00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `book`
--
DROP TABLE IF EXISTS `book`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `book` (
`bookid` int(11) NOT NULL,
`bookname` varchar(255) NOT NULL,
`authors` varchar(255) NOT NULL,
`info` varchar(255) DEFAULT NULL,
`comment` varchar(255) DEFAULT NULL,
`year_publication` year(4) NOT NULL,
KEY `year_publication` (`year_publication`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `book`
--
LOCK TABLES `book` WRITE;
/*!40000 ALTER TABLE `book` DISABLE KEYS */;
INSERT INTO `book` VALUES (12,'dajiahao','NIHAO','??','henhao',1990);
/*!40000 ALTER TABLE `book` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `innodb_monitor`
--
DROP TABLE IF EXISTS `innodb_monitor`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `innodb_monitor` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `innodb_monitor`
--
LOCK TABLES `innodb_monitor` WRITE;
/*!40000 ALTER TABLE `innodb_monitor` DISABLE KEYS */;
/*!40000 ALTER TABLE `innodb_monitor` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2014-08-05 22:36:17
将D:TEST.TXT文件复制到slave机器上,然后执行如下操作
在命令行登录mysql,然后 USE TEST;
记得一定要USE TEST,切换数据库上下文,否则会报错:NO DATABASE SELECTED 的错误信息
然后执行source命令导入TEXT.txt文件的内容
可以看到,数据已经导入到slave上面了。
9、配置slave机器(192.168.1.102)的my.ini配置文件
具体配置信息如下
代码语言:javascript复制[mysql]
default-character-set=utf8
log_bin="C:/MYSQLLOG/binlog"
expire_logs_days=10
max_binlog_size=100M
[mysqld]
server-id=2
提示:配置slave主机my.ini文件的时候,需要将server-id=2写到[mysqld]后面
另外如果配置文件中还有log_bin的配置,可以将他注释掉,如下所示
代码语言:javascript复制#Binary Logging
#log-bin
#log_bin="xxx"
10、重启slave主机(192.168.1.102)的mysql服务,在slave主机(192.168.1.102)的mysql中执行如下命令
关闭slave服务
代码语言:javascript复制stop slave;
11、设置slave从机实现复制相关的信息,命令如下。
代码语言:javascript复制change master to
master_host='192.168.1.100',
master_user='repl',
master_password='123',
master_log_file='binlog。000004',
master_log_pos=107;
Command(s) completed successfully.
各个参数所代表的具体含义如下:
- master_host:表示实现复制的主机ip地址
- master_user:表示实现复制的登录远程主机的用户
- master_password:表示实现复制的登录远程主机的密码
- master_log_file:表示实现复制的binlog日志文件
- master_log_pos:表示实现复制的binlog日志文件的偏移量
12、继续在从机执行操作,显示slave从机的状况,如下所示
代码语言:javascript复制start slave;
Command(s) completed successfully.
<pre>mysql<span style="color:#808080;">></span><span style="color:#000000;"> SHOW SLAVE STATUS G;
</span><span style="color:#808080;">***************************</span> <span style="color:#800000;font-weight: bold;">1</span>. row <span style="color:#808080;">***************************</span><span style="color:#000000;">
Slave_IO_State:
Master_Host: </span><span style="color:#800000;font-weight: bold;">192.168</span>.<span style="color:#800000;font-weight: bold;">1.100</span><span style="color:#000000;">
Master_User: repl
Master_Port: </span><span style="color:#800000;font-weight: bold;">3306</span><span style="color:#000000;">
Connect_Retry: </span><span style="color:#800000;font-weight: bold;">60</span><span style="color:#000000;">
Master_Log_File: binlog銆?</span><span style="color:#800000;font-weight: bold;">00004</span><span style="color:#000000;">
Read_Master_Log_Pos: </span><span style="color:#800000;font-weight: bold;">107</span><span style="color:#000000;">
Relay_Log_File: Steven</span><span style="color:#808080;">-</span>PC<span style="color:#808080;">-</span>relay<span style="color:#808080;">-</span>bin.<span style="color:#800000;font-weight: bold;">000002</span><span style="color:#000000;">
Relay_Log_Pos: </span><span style="color:#800000;font-weight: bold;">4</span><span style="color:#000000;">
Relay_Master_Log_File: binlog銆?</span><span style="color:#800000;font-weight: bold;">00004</span><span style="color:#000000;">
Slave_IO_Running: No
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: </span><span style="color:#800000;font-weight: bold;">0</span><span style="color:#000000;">
Last_Error:
Skip_Counter: </span><span style="color:#800000;font-weight: bold;">0</span><span style="color:#000000;">
Exec_Master_Log_Pos: </span><span style="color:#800000;font-weight: bold;">107</span><span style="color:#000000;">
Relay_Log_Space: </span><span style="color:#800000;font-weight: bold;">107</span><span style="color:#000000;">
Until_Condition: None
Until_Log_File:
Until_Log_Pos: </span><span style="color:#800000;font-weight: bold;">0</span><span style="color:#000000;">
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: </span><span style="color:#0000ff;">NULL</span><span style="color:#000000;">
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: </span><span style="color:#800000;font-weight: bold;">1236</span><span style="color:#000000;">
Last_IO_Error: Got fatal error </span><span style="color:#800000;font-weight: bold;">1236</span> <span style="color:#0000ff;">from</span> master <span style="color:#0000ff;">when</span><span style="color:#000000;"> reading dat
a </span><span style="color:#0000ff;">from</span> <span style="color:#0000ff;">binary</span> <span style="color:#ff00ff;">log</span>: <span style="color:#ff0000;">'</span><span style="color:#ff0000;">Could not find first log file name in binary log index file</span><span style="color:#ff0000;">'</span><span style="color:#000000;">
Last_SQL_Errno: </span><span style="color:#800000;font-weight: bold;">0</span><span style="color:#000000;">
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: </span><span style="color:#800000;font-weight: bold;">1</span>
<span style="color:#800000;font-weight: bold;">1</span> row <span style="color:#808080;">in</span> <span style="color:#0000ff;">set</span> (<span style="color:#800000;font-weight: bold;">0.00</span><span style="color:#000000;"> sec)
ERROR:
No query specified</span>
在上述执行show slave status G命令中很显然存在一些问题,问题如下。
代码语言:javascript复制Last_IO_Errno: 1236
Last_IO_Error: Got fatal error 1236 from master when reading dat
a from binary log: 'Could not find first log file name in binary log index file'
下面的步骤可以解决问题,具体步骤如下
1、重启master(192.168.1.100)主机的mysql服务,执行show master status G命令
记下File和Position的值,后面slave主机会用到,命令执行如下
代码语言:javascript复制SHOW MASTER STATUS;
2、在slave(192.168.1.102)主机上重新设置信息,命令执行如下
代码语言:javascript复制stop slave;
change master to
master_log_file='binlog.000005',
master_log_pos=107;
start slave;
mysql> SHOW SLAVE STATUS G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.100
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000005
Read_Master_Log_Pos: 107
Relay_Log_File: Steven-PC-relay-bin.000002
Relay_Log_Pos: 250
Relay_Master_Log_File: binlog.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: 107
Relay_Log_Space: 410
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)
ERROR:
No query specified
这次正常了,实际上刚才有两个地方是错误的
第一个:在从机的my.ini里面
代码语言:javascript复制[mysql]
default-character-set=utf8
#log_bin="C:/MYSQLLOG/binlog"
#expire_logs_days=10
#max_binlog_size=100M
在从机的my.ini里面的mysql配置节下面配置了binlog,实际上这样做是错误的,要配置binlog需要在[mysqld]配置节下
第二个:第一次配置从机的同步的时候本人写错了标点符号,.号写成。号
代码语言:javascript复制master_log_file='binlog。000004',
这时候,我们可以在从机上面执行show processlist来查询从服务器的进程状态
代码语言:javascript复制mysql> show processlist G
*************************** 1. row ***************************
Id: 4
User: root
Host: localhost:60968
db: information_schema
Command: Sleep
Time: 3613
State:
Info: NULL
*************************** 2. row ***************************
Id: 5
User: system user
Host:
db: NULL
Command: Connect
Time: 3613
State: Waiting for master to send event
Info: NULL
*************************** 3. row ***************************
Id: 6
User: system user
Host:
db: NULL
Command: Connect
Time: 2769
State: Slave has read all relay log; waiting for the slave I/O thread to update it
Info: NULL
*************************** 4. row ***************************
Id: 7
User: root
Host: localhost:61007
db: NULL
Command: Query
Time: 0
State: NULL
Info: show processlist
4 rows in set (0.04 sec)
结果表明slave已经连接上master,开始接收并执行日志relay-log.info文件里面的内容
代码语言:javascript复制.Steven-PC-relay-bin.000002
250
binlog.000005
107
7
relay-log.info文件里面记录了slave端的relaylog的当前文件名和位置,还有master端的binlog文件名和位置
Windows环境下主从复制测试
1、在master端的mysql环境下,执行下面命令
代码语言:javascript复制use test;
create table rep_test(data integer);
insert into rep_test values(2);
2、在slave端的mysql环境下,查看主机刚才添加的表和数据是否成功同步到从机上
代码语言:javascript复制use test;
show tables;
select * FROM REP_TEST;
测试表明,数据已经成功地同步到slave上,实验中只是用到了主从同步,在实际生产环境中MYSQL架构可能会用到一主多从的架构
MySQL主要复制启动选项
(1)log-slave-updates
log-slave-updates这个参数主要用来配置从服务器的更新是否写入二进制日志,该选项默认是不打开的,如果这个从服务器同时也作为其他服务器的主服务器,搭建一个链式的复制,那么就需要开启这个选项,这样从服务器才能获取他的二进制日志进行同步操作。
(2)master-connect-retry
master-connect-retry这个参数用来设置和主服务器连接丢失的时候进行重试的时间间隔,默认是60秒。
(3)read-only
read-only是用来限制普通用户对从数据库的更新操作,以确保从数据库的安全性,不过如果是超级用户依然可以对从数据库进行更新操作。如果主数据库创建了一个普通用户,在默认情况下,该用户是可以更新从数据库的数据的,如果使用read-only选项启动从数据库以后,用户对从数据库进行更新时会提示错误。
在Linux下启动mysql例子
代码语言:javascript复制[root@localhost~]#mysqld_safe -read-only
(4)slave-skip-errors
在复制过程中,从服务器可以会执行BINLOG中的错误SQL语句,此时如果不忽略错误,从服务器会停止复制进程,等待用户处理错误。这种错误如果不能及时发现,将会对应用或者备份产生影响。
slave-skip-errors的作用就是用来定义复制过程中从服务器可以自动跳过的错误号,设置该参数后,mysql会自动跳过所配置的一系列错误,直接执行后面的SQL语句,该参数可以定义多个错误号,如果设置成all,则表示跳过所有的错误,在my.ini或者my.cnf里配置如下。
代码语言:javascript复制slave-skip-errors=1007,1051,1062
如果从数据库主要作为主库的备份,那么就不应该使用这个启动参数,因为一旦设置不当很可能造成主从库的数据不同步。
如果从库仅仅是为了分担主库的查询压力,并且对数据的完整性要求不高,那么这个选项可以减轻DBA维护从库的工作量
查看slave的复制进度
很多情况下,用户都想知道从服务器复制的进度,从而判断从服务器上复制数据的完整性,同时判断是否需要手工来做主从同步工作。
事实上,用户可以通过show processlist列表中的Slave_SQL_Running线程的Time值得到,他记录了从服务器当前执行的SQL时间戳和系统时间之间的差距,例如下面的例子
代码语言:javascript复制 Id: 6
User: system user
Host:
db: NULL
Command: Connect
Time: 2769
State: Slave has read all relay log; waiting for the slave I/O thread to update it
Info: NULL
Time时间说明从服务器最后执行的更新操作大概是主服务器2769秒前的更新操作
日常管理和维护
复制配置完成后,DBA需要进行日常的监控和管理维护工作,以便能够及时发现问题和解决问题。以保证主从数据库能够正常工作。
1、了解服务器的状态
一般使用show slave status命令来检查从服务器,在查看服务器信息中,首先要查看下面的两个进程是否为YES。
代码语言:javascript复制Slave_IO_Running: Yes
Slave_SQL_Running: Yes
- Slave_IO_Running表明此进程是否能够由从服务器到主服务器上正确地读取binlog日志,并写入到从服务器的中继日志中
- Slave_SQL_Running表明此进程能否读取并执行中继日志中的binlog信息
2、服务器复制出错原因
问题一:出现“log event entry exceeded max_allowed_pack”错误
如果在应用中使用大的BLOB列或CLOB列或者长字符串,那么在从服务器上回复时,可能会出现“log event entry exceeded max_allowed_pack”的错误,这是因为含有达文本的记录无法通过网络进行传输而导致的。
解决方法是在主服务器和从服务器上添加max_allowed_packet参数,该参数默认设置为1MB
代码语言:javascript复制show variables LIKE '%max_all%'
Variable_name Value
------------------ -------
max_allowed_packet 1048576
(1 row(s) affected)
set @@global.max_allowed_packet=16777216;
同时在my.ini或my.cnf文件里设置max_allowed_packet=16M,数据库重启之后该参数将有效
问题二:多主复制时的自增长变量冲突问题
大多数情况下使用一台主服务器对一台或者多台从服务器,但是在某些情况下可能会存在多个服务器配置为复制主服务器,使用auto_increment时应采取特殊步骤以防止键值冲突,否则插入时多个主服务器会试图使用相同的auto_increment值。
服务器变量auto_increment_increment和auto_increment_offset可以协调多主服务器复制auto_increment列在多主服务器复制到从服务器的过程中会发生主键冲突问题,可以将不同的主服务器的这两个参数重新进行设置,将A库上设置auto_increment_increment=1,auto_increment_offset=1,此时B库上设置auto_increment_increment=1,auto_increment_offset=0。
提示:一般不建议使用双主或多主,因为这样会带来意想不到的冲突状况,就像SQLSERVER的对等复制,虽然有很多冲突检测措施
但是有时候冲突是不可预料的,出现冲突DBA要排查,维护成本较高,我们生产环境里是没有使用双主和多主,主要使用的是一主多从或一主一从。
切换主从服务器
在实际生产环境,如果主机上的主库发生故障,需要将从机上的从库切换成主库,同时需要修改服务器C的配置文件,使程序连接到从机。下面介绍主从切换的步骤。
1、首先要确保所有的从库都已经执行了relay log中的全部更新,看从库的状态是否是Has read all relay log,是否更新都已经执行完成
在从库上执行下面命令。
代码语言:javascript复制STOP SLAVE IO_THREAD;
Command(s) completed successfully.
mysql> show processlist G
*************************** 1. row ***************************
Id: 4
User: root
Host: localhost:60968
db: test
Command: Sleep
Time: 45
State:
Info: NULL
*************************** 2. row ***************************
Id: 6
User: system user
Host:
db: NULL
Command: Connect
Time: 3949
State: Slave has read all relay log; waiting for the slave I/O thread to update it
Info: NULL
*************************** 3. row ***************************
Id: 7
User: root
Host: localhost:61007
db: NULL
Command: Query
Time: 0
State: NULL
Info: show processlist
3 rows in set (0.00 sec)
2、在从库上停止slave服务,然后执行reset master重置成为主库。
代码语言:javascript复制STOP SLAVE;
Command(s) completed successfully.
RESET MASTER;
Command(s) completed successfully.
注意:如果从库上并未开binlog,那么在执行reset master的时候会报错:ERROR 1186(HY000):BINLOG CLOSED ,CANNOT RESET MASTER。
在切换之后,在从库的数据目录会多出master.info文件。
master.info文件里的内容。
代码语言:javascript复制18
binlog.000005
393
192.168.1.100
repl
123
3306
60
0
0
1800.000
0
0
基本上记录了主库的复制用户、密码和binlog文件名和位置等。
3、在从库B(192.168.1.102)上添加具有replication权限的用户repl,查询主库状态,命令如下。
代码语言:javascript复制GRANT REPLICATION SLAVE ON *.*TO 'repl'@'localhost' identified by '123';
show master status;
4、修改主服务器的my.ini文件里的server-id为1,从服务器的server-id为2。
5、在原来的主库(192.168.1.100)上配置复制参数。
代码语言:javascript复制change master TO
master_host='192.168.1.102',
master_user='repl',
master_password='123',
master_port=3306,
master_log_file='on.000004',
master_log_pos=107;
6、在从库(192.168.1.100)上执行show slave status命令查看从库是否启动成功。
代码语言:javascript复制START SLAVE;
mysql> show slave status G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.102
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: on.000004
Read_Master_Log_Pos: 107
Relay_Log_File: joe-relay-bin.000006
Relay_Log_Pos: 246
Relay_Master_Log_File: on.000004
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: 107
Relay_Log_Space: 436
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)
ERROR:
No query specified
注意:如果在主库上面(192.168.1.102)的复制用户repl没有允许远程主机从库的访问,那么在执行show slave status的时候就会报错。
代码语言:javascript复制Last_IO_Errno: 1130
Last_IO_Error: error connecting to master 'repl@192.168.1.102:3360 retries: 8640006' - retry-time: 60 retries: 86400
这时候,只需要在主库(192.168.1.102)上面执行下面语句即可。
代码语言:javascript复制use mysql;
select * from user where user='repl';
update user set host = '%' where user ='repl';
flush privileges;
7、在主库和从库上面是否成功设置复制功能,首先在主库(192.168.1.102)上查看test库中的表。
代码语言:javascript复制use test;
show tables;
查询从库中(192.168.1.100)test库里表的情况。
代码语言:javascript复制use test;
show tables;
跟主库一样。
8、在主库(192.168.1.102)中增加表rep_t ,并插入数据。
代码语言:javascript复制create table rep_t(data int);
insert into rep_t values(1);
9、在从库(192.168.1.100)上查询表是否已经创建并复制数据到从库中
代码语言:javascript复制USE test;
show variables like '%server%';
show tables;
SELECT * FROM rep_t;
至此,主从库成功切换
主机和从机server-id一样如何解决
通常情况下,master和slave的server-id是不会一样的,如果一样的话会出现报错。出现这种情况,用户可以使用如下命令来查看服务器的server-id,然后手动进行修改,如下所示
代码语言:javascript复制show variables like '%server_id%';
Variable_name Value
------------- -----
server_id 2
(1 row(s) affected)
SET global server_id=1
修改完成后,执行slave start命令,查询slave主机的状态,查看问题可否解决
从机状态显示Last_IO_Error错误代码为2013的原因
有时候会遇到这样的情况,在执行show slave status G 命令中 Slave_IO_Running和Slave_SQL_Running的值都是YES
但是Last_IO_Error发生2013错误
发生这种问题主要原因是网络问题,首先要检查下master主机创建的用户是否授予远程连接的权限
代码语言:javascript复制GRANT replication slave ON *.*TO repl@'%' IDENTIFIED BY '123';
这里%表示任何的repl用户都可以访问master主机,另外需要查看是否有防火墙设置和网络的其他故障
MySQL复制不同步的原因
mysql replication(复制)采用binlog进行网络传输,所以网络延时是产生mysql主从不同步的主要原因,这会给我们进行读写分离带来
一定困难为了避免这种情况,在配置服务器的时候推荐使用INNODB存储引擎的表,在主机上可以设置sync_binlog
下面内容摘抄自《MySQL行调优和架构设计》
❝“sync_binlog”:这个参数是对于 MySQL 系统来说是至关重要的,他不仅影响到 Binlog 对 MySQL 所带来的性能损耗,而且还影响到 MySQL 中数据的完整性。对于“sync_binlog”参数的各种设置的说明如下: ● sync_binlog=0,当事务提交之后,MySQL 不做 fsync 之类的磁盘同步指令刷新 binlog_cache 中的信息到磁盘,而让 Filesystem 自行决定什么时候来做同步,或者 cache 满了之后才同步到磁盘。 ● sync_binlog=n,当每进行 n 次事务提交之后,MySQL 将进行一次 fsync 之类的磁盘同步指令来将 binlog_cache 中的数据强制写入磁盘。 在 MySQL 中系统默认的设置是 sync_binlog=0,也就是不做任何强制性的磁盘刷新指令,这时候的性能是最好的,但是风险也是最大的。因为一旦系统 Crash,在 binlog_cache 中的所有 binlog 信息都会被丢失。而当设置为“1”的时候,是最安全但是性能损耗最大的设置。因为当设置为 1 的时候,即使系统Crash,也最多丢失 binlog_cache 中未完成的一个事务,对实际数据没有任何实质性影响。 从以往经验和相关测试来看,对于高并发事务的系统来说,“sync_binlog”设置为 0 和设置为 1 的系统写入性能差距可能高达 5 倍甚至更多。 ❞
如果master主机上的max_allowed_packet比较大,但是从机上没有配置该值的话,该参数还是使用默认值1MB此时很有可能导致同步失败,建议主从两台机器都设为5MB比较合适
好了,如果文章对你有点帮助,记得给冰河一键三连哦,欢迎将文章转发给更多的小伙伴,冰河将不胜感激~~