Andy Niu Help
1.0.0.0
|
变量 | |
主主复制的配置流程 | |
show_slave_status | |
Mysql复制错误 | |
Reconnecting_after_a_failed_master_event_read | |
Client_requested_master_to_start_replication_from_impossible_position | |
半同步复制 | |
查看二进制日志 | |
详细描述
变量说明
Client_requested_master_to_start_replication_from_impossible_position |
1、错误如下: mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.1.176 Master_User: root Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000010 Read_Master_Log_Pos: 994941638 Relay_Log_File: mysqld-relay-bin.000261 Relay_Log_Pos: 4 Relay_Master_Log_File: mysql-bin.000010 Slave_IO_Running: No Slave_SQL_Running: Yes Replicate_Do_DB: ibp 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: 994941638 Relay_Log_Space: 106 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: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 1236 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position' Last_SQL_Errno: 0 Last_SQL_Error: 1 row in set (0.00 sec) 2、从对方去复制一个不可能的位置,查看Master端的二进制日志,如下: [root@localhost mysql]# ll |grep mysql-bin.000010 -rw-rw---- 1 mysql mysql 994934249 2015-12-03 16:27 mysql-bin.000010 3、也就是说,Slave去复制位置994941638,而Master端的位置只有994934249 4、查看Master端的错误日志,如下: InnoDB: Log scan progressed past the checkpoint lsn 0 670781756 151204 9:12:26 InnoDB: Database was not shut down normally! InnoDB: Starting crash recovery. InnoDB: Reading tablespace information from the .ibd files... InnoDB: Restoring possible half-written data pages from the doublewrite InnoDB: buffer... InnoDB: Doing recovery: scanned up to log sequence number 0 671228026 151204 9:12:26 InnoDB: Starting an apply batch of log records to the database... InnoDB: Progress in percents: 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 8 1 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 InnoDB: Apply batch completed InnoDB: Last MySQL binlog file position 0 994941638, file name ./mysql-bin.000010 151204 9:12:27 InnoDB: Started; log sequence number 0 671228026 也就是说,Master端异常关闭,重启之后,进行崩溃恢复,而且也记录了崩溃前的二进制日志位置994941638, 但是恢复之后,位置只有994934249,通过show binlog events 和 mysqlbinlog查看恢复后的日志文件,位置确实只到了994934249 5、也就是说,mysql异常关闭(直接断电),重启恢复二进制日志的时候出现错误,而Slave端还从旧的位置复制,出错。 这个时候,两边的数据还是一致的。因为Master也写入数据库了,Slave端也复制了。 只不过Master端恢复出现错误,同时Slave复制的位置没有了。 6、解决办法是,手工调整复制的文件和位置,从下一个文件的位置0开始。 7、异常关闭mysql(直接断电),除了会导致上面的问题。还会导致下面的问题: 对于增删改操作,mysql记录二进制日志不会实时刷新到磁盘。通过sync_binlog可以设置刷新到磁盘的频率。 为0,mysql不控制binlog的刷新,靠文件系统自己控制。 大于0,mysql调用文件系统的刷新操作,刷新到磁盘。sync_binlog=1表示提交一次事务,就刷新。 没有很好的理由,mysql建议不要修改sync_binlog的值,靠文件系统自己控制刷新。 因为设置小了,导致频繁刷新到磁盘,性能很差。设置大了,刷新的延迟时间长,主从一致性的延迟也就大。 那么问题来了: 异常关闭mysql,可能出现数据已经修改了,但是二进制日志没有刷新到磁盘。这部分的修改没有发给Slave,主从不一致。 对于这个问题,可以通过半同步复制来避免,但是这个要使用mysql5.5上面的一个插件,暂时不做了。 8、也就是说,根据mysql复制的实现原理,异常关闭mysql会导致一些问题,因此尽量避免直接断电关闭mysql,先正常关闭,再断电。 如果出现了异常关闭,人工介入,进行调整。
Mysql复制错误 |
主备切换的流程: 1、hau彼此通信,初始化,认为当前设备是备机,收不到对方的消息,把自己切换为主机。 2、hau认为当前设备是备机,调用rpu_sdk的OnSlave,hau认为当前设备是主机,调用OnMaster 3、OnSlave做的事情: a、调用黄彪的脚本,禁用外网卡,删除外网卡的网关,同时把网关设置为对端内网ip b、把cmu,uac,uas,virgo等服务的可用状态设置为0,因为备机上的这些服务是不启动的。 而dmu,vtdu要负载均衡,两边都可用,mysql,hau两边也都可用。 c、然后关闭cmu,uac,uas,virgo,虽然guard是活着的,但是这些服务不可用,不会启动。 4、OnMaster做的事情: a、调用黄彪的脚本,激活外网卡,设置外网卡的网关,免费ARP,查询自身Ip地址对应的MAC地址, 设置路由规则,对于出去的修改ip地址,发到外部,对于进来的,根据端口转发。 b、所有服务的可用状态设置为1,guard会把它们启动。
经过反复测试,基本可以确定的是: 1、mysql正常的启动关闭,复制是不存在问题的。 2、对于目前的处理流程,正常的操作,复制是没有问题的。
问题是: 这两次出现的错误,错误码都是1236,就是Slave端的IO线程,从Master断读取二进制日志,出现错误。 1、第一次的错误信息是,Slave从Master读取一个不存在的问题 2、第二次的错误信息是,Master端的二进制日志被截断。 网上查了,基本上是出现这种问题,怎么解决? 出现这种情况,需要stop slave,需要使用change master to,修改Slave从Master复制的位置。然后start slave。 为什么出现这种情况?如何避免出现? 1、第一次的错误信息是,Slave从Master读取一个不存在的问题 原因是:安装有问题,主主复制一端卸载又安装。比如A,B目前复制正常。A记到85位置,B也跟到85位置,A卸载,再安装。 A安装的时候清除二进制日志,新的位置从0开始,而B还认为从85位置复制,出现错误,从一个不可能的位置复制。 2、第二次的错误信息是,Master端的二进制日志被截断。 原因是:主库意外死机,导致binlog有问题。
注意:二进制日志,使用二进制格式保存,如果查看? 需要使用程序 mysqlbinlog
Reconnecting_after_a_failed_master_event_read |
1、rpu2000T 测试环境,mysql复制出现问题,如下: mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Reconnecting after a failed master event read Master_Host: 192.168.1.176 Master_User: root Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 49136994 Relay_Log_File: mysqld-relay-bin.000006 Relay_Log_Pos: 48636785 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: No Slave_SQL_Running: Yes Replicate_Do_DB: ibp 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: 49136994 Relay_Log_Space: 48637086 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: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 2013 Last_IO_Error: error reconnecting to master '[email protected]:3306' - retry-time: 60 retries: 86400 Last_SQL_Errno: 0 Last_SQL_Error: 1 row in set (0.00 sec) 2、出现这种情况的原因是,对端作为master的mysql服务器关闭了,本地作为slave的mysql,读取二进制日志出现错误,然后会重连Master。 重连间隔是60秒,重连86400次。 注:在配置文件中,master-connect-retry重连间隔时间,master-retry-count重连次数 3、当对端的Master重新启动之后,slave重连成功,会接着读取二进制日志。 这个场景,我已经模拟测试多次,是没有问题的。 4、现在的问题是,出现了一直重连不成功,我看到slave端的mysql错误日志如下: 151124 15:05:05 [Note] Slave: received end packet from server, apparent master shutdown: 151124 15:05:05 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log 'mysql-bin.000011' at position 37827 151124 15:05:05 [ERROR] Slave I/O: error reconnecting to master '[email protected]:3306' - retry-time: 60 retries: 86400, E rror_code: 2013 151124 15:06:05 [Note] Slave: connected to master '[email protected]:3306',replication resumed in log 'mysql-bin.000011' at position 37827 151125 9:35:26 [Note] Slave: received end packet from server, apparent master shutdown: 151125 9:35:26 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log 'mysql-bin.000018' at position 6366231 151125 9:35:26 [ERROR] Slave I/O: error reconnecting to master '[email protected]:3306' - retry-time: 60 retries: 86400, E rror_code: 2013 151203 10:10:35 [Note] Error reading relay log event: slave SQL thread was killed 在151124 15:05:05 对端的master关闭了,后面有重新连接成功, 但是在151125 9:35:26 ,对端的master关闭了,后面没有重新连接成功,而且现在也没有超过重连次数,超过重连次数需要60*86400/86400=60天。 5、出现了这种情况,我通过在slave端执行 stop slave; 然后start slave,就可以了。但是为什么出现一直重连不上,原因还不清楚。
show_slave_status |
Slave_IO_State: Waiting for master to send event Master_Host: 10.1.1.1 Master_User: rep_user Master_Port: 3306 Connect_Retry: 10 Master_Log_File: binlog.000026 从库I/O线程读取主库binlog文件名 Read_Master_Log_Pos: 446 从库I/O线程读取主库binlog的位置 Relay_Log_File: relay.000008 从库SQL线程正在应用的relay-log文件名 Relay_Log_Pos: 589 从库SQL线程正在应用的relay-log位置 Relay_Master_Log_File: binlog.000026 从库SQL线程正在应用的relay-log对应的binlog 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: 446 从库SQL线程正在应用的relay-log对应binlog的位置 Relay_Log_Space: 878 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: 2211 可以这样理解: 1、从库I/O线程到主库中读取二进制文件,记录读取哪个二进制文件,以及读取到的位置。 2、从库I/O线程把读取到二进制内容,放入中继日志。 3、从库SQL线程重放中继日志,记录重放哪个中继日志,以及重放到中继日志的哪个位置。 中继日志重放之后,产生一个位置,这个位置对应主库二进制的位置。 中继日志的位置,和重放之后产生的位置(对应主库的二进制位置)完全不搭嘎。 4、这是典型的生产者/消费者模式,中继日志就是共享区,I/O往里面放,SQL从里面取。 Slave有两个线程: 1、I/O线程从Master接收二进制日志文件,写入本地的中继日志 2、SQL线程,读取中继日志,重放。典型的生产者/消费者模型 中继日志有三个位置: 1、中继日志的结尾,I/O从Master读到了哪个位置 2、SQL执行中继日志,执行到了哪个位置 3、重放之后,产生一个位置,这个位置对应Master上面的二进制文件位置。 Read_Master_Log_Pos与Master上面的show master status 位置相等,说明没有需要读取的内容,二者已经完全同步。 Read_Master_Log_Pos和Exec_Master_Log_Pos相等,说明没有需要重放的内容了。 要完全同步,满足两个条件: 1、Read_Master_Log_Pos与Master上面的show master status 位置相等,说明没有需要读取的内容。 2、Read_Master_Log_Pos和Exec_Master_Log_Pos相等,说明没有需要重放的内容了。 特别注意:Seconds_Behind_Master不是表示Slave比Master落后多少,而是对于SQL线程,中继日志中还有多少没有执行。 Seconds_Behind_Master=0 不表示Slave与Master完全同步,而是中继日志执行完了。 要判断是否完全同步,还需要判断Master记录到了哪个位置和Slave读到了哪个位置。 注: 1、二进制日志中,不包括数据查询语句。因为只是select,不会修改数据,因此不写入二进制日志。 2、在Master端,可以并行执行增删改操作,串行记录二进制日志。 Slave端串行接收二进制日志,对于接收的二进制写入到中继日志。 对于写入的中继日志,Slave只有一个SQL线程重放中继日志,不能并发执行,这往往会成为瓶颈。
主主复制的配置流程 |
1、先关闭B,把A的数据导出来,mysqldump -hlocalhost -uroot -p123456 ibprpu >ibprpu.sql 注意:如果只导出表结构,使用 -d, --no-data No row information. 详见mysqldump --help 2、关闭A,启动B,进入mysql建立一个新的数据库 create database ibprpu 3、导入数据库 mysql -hlocalhost -uroot -p123456 <ibprpu.sql, 或者进入mysql,通过命令 source /root/ibprpu.sql 导入数据库 4、修改A和B的配置文件,my.cnf,重启A和B 5、注意:有些版本my.cnf中的复制属性配置不起作用,先关闭slave,再change master 6、stop slave; change master to master_host='192.168.1.101',master_port=3306,master_user='root',master_password='123456'; 必要的时候还需要指定master_log_file 和 master_log_pos。 7、Last_IO_Errno: 1236 错误的原因是 从master读取一个无效的位置,在主机上执行 show master status 查看二进制日志的位置, 在备机上,关闭slave,change master 重新指定master_log_pos。 如果还有错误,stop slave; set global sql_slave_skip_counter=1; start slave; 8、主机要记录二进制日志,配置如下: log-bin=mysql-bin 这种情况下,查询mysql的版本,后面带有log,如下 mysql> select version(); +------------+ | version() | +------------+ | 5.1.66-log | +------------+
半同步复制 |
1、mysql的复制是异步的,也就是说,Master提交事务后,写入二进制日志(可能还没有刷新到磁盘),然后成功返回给客户端。 并不等待二进制日志传送给Slave。 2、考虑下面的极端情况,Master提交事务,写入二进制日志(可能还没有刷新到磁盘),这个时候主库宕机,磁盘故障或者内存故障, 导致这个事务丢失,Slave损失这个事务,主从不一致。 3、怎么解决这个问题? Master提交事务,写入二进制日志时,并不及时回复客户端成功,而是等待这个事务的二进制日志成功发给Slave,回复客户端成功。 这样就保证了两份日志记录,一份在Master的二进制日志,一份在Slave的中继日志。这就是半同步复制。 4、为什么叫半同步复制? 如果要完全同步复制,需要Master提交事务,写入二进制日志,成功发给Slave,Slave的SQL线程执行完毕,两边的数据一致,再回复给客户端。 但是这里,只是成功发给了Slave,Slave还没有执行,数据还不一致,只要执行了,理论上是一致的。因此叫半同步复制。 5、注意:二进制日志,mysql不会删除,因为可能好几天之后在配置Slave去复制,因此最早的二进制日志也要保存。 需要手工处理二进制日志。对于中继日志,mysql会定时清除,它只是复制过来,然后执行。
查看二进制日志 |
1、使用mysqlbinlog程序,mysqlbinlog --help 或者 mysqlbinlog -? 查看帮助文档。 注意:如果是binlog格式是ROW,使用mysqlbinlog查看会是乱码,此时需要使用选项 -vv --base64-output=decode-rows 2、mysql登录之后,使用语法 show binlog events in 'mysql-bin.000010' limit 10,2\G help show binlog events; 查看帮助文档 3、注意:使用mysqlbinlog,--start-position必须是二进制日志中存在的位置,这个位置就是字节个数,如下: [root@localhost mysql]# mysqlbinlog mysql-bin.000010 --start-position=994934222 -vv --base64-output=decode-rows /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; # at 994934222 #151203 3:03:39 server id 213 end_log_pos 994934249 Xid = 4154885 COMMIT/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; 如果使用了没有存在的位置,报错如下: [root@localhost mysql]# mysqlbinlog mysql-bin.000010 --start-position=994934221 -vv --base64-output=decode-rows /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; ERROR: Error in Log_event::read_log_event(): 'read error', data_len: 6912, event_type: 86 DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; 4、那么问题来了,如果不知道位置怎么办? 5、可以先使用show binlog events找到位置,show binlog events in 'mysql-bin.000010' limit 0,2 中的limit是指操作的个数。 mysql> show binlog events in 'mysql-bin.000010' limit 5092175,10\G *************************** 1. row *************************** Log_name: mysql-bin.000010 Pos: 994933417 Event_type: Query Server_id: 213 End_log_pos: 994933547 Info: use `ibp`; delete from dev_accesory where DEVID= NAME_CONST('_devid',1867) *************************** 2. row *************************** Log_name: mysql-bin.000010 Pos: 994933547 Event_type: Xid Server_id: 213 End_log_pos: 994933574 Info: COMMIT /* xid=4154883 */ *************************** 3. row *************************** Log_name: mysql-bin.000010 Pos: 994933574 Event_type: Query Server_id: 213 End_log_pos: 994933646 Info: BEGIN *************************** 4. row *************************** Log_name: mysql-bin.000010 Pos: 994933646 Event_type: Query Server_id: 213 End_log_pos: 994934222 Info: use `ibp`; insert into dev_accesory(DEVID,LOCATIONTYPEID,DESCRIPTION,MODEL,INSTALLSPOT,INSTALLTIME,CONTRACTOR,MAINTAINER,PHONE,VISIBLE,LONGITUDE,LATITUDE,FAST,UPDATETIME) values( NAME_CONST('_devid',1867), NAME_CONST('_lid',0), NAME_CONST('_desc',NULL), NAME_CONST('_mod',NULL), NAME_CONST('_inspot',NULL), NAME_CONST('_iname',NULL), NAME_CONST('_con',NULL), NAME_CONST('_mant',NULL), NAME_CONST('_phone',NULL), NAME_CONST('_vis',1), NAME_CONST('_longt',0), NAME_CONST('_latt',0), NAME_CONST('_fast',0),now()) *************************** 5. row *************************** Log_name: mysql-bin.000010 Pos: 994934222 Event_type: Xid Server_id: 213 End_log_pos: 994934249 Info: COMMIT /* xid=4154885 */ 5 rows in set (4.81 sec) 注意:一个增删改操作或者事物,分为3个操作,一个BEGIN,一个执行sql语句,一个COMMIT 6、二进制日志中的位置就是文件大小,多少个字节数,需要注意的是:文件大小是最后一个操作的end_log_pos,如下: [root@localhost mysql]# ll |grep mysql-bin.000010 -rw-rw---- 1 mysql mysql 994934249 2015-12-03 16:27 mysql-bin.000010 [root@localhost mysql]# mysqlbinlog mysql-bin.000010 --start-position=994934222 -vv --base64-output=decode-rows /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; # at 994934222 #151203 3:03:39 server id 213 end_log_pos 994934249 Xid = 4154885 COMMIT/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
Copyright (c) 2015~2016, Andy Niu @All rights reserved. By Andy Niu Edit.