澳门十大赌场最新排名 > 澳门十大赌场 > GTID复制错误处理之跳过错误,MySQL游标循环取出

原标题:GTID复制错误处理之跳过错误,MySQL游标循环取出

浏览次数:50 时间:2019-07-29

某Slave报错信息:

早上同事要我写个MySQL去除重复数据的SQL,想起来上次写过一篇MySQL去除重复数据的博客,使用导入导出加唯一索引实现的,但是那种方式对业务影响较大,所以重新写一个存储过程来删重复数据,这一写就写了一个上午,这种BUG确实是很令人沮丧和浪费时间的。

SQL2008无法附加数据库,提示“无法显示请求的对话框”(nColIndex实际值是-1)图文解决方法

mysql> show slave statusG;

这里把流程简单的描述一下,删重复数据的逻辑很简单:

SQL2008无法附加数据库,提示“无法显示请求的对话框”(nColIndex实际值是-1)图文解决方法 

图片 1图片 2

1.根据重复判断条件找出重复记录的最小主键(一般是ID列)。

 

mysql> show slave statusG;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.206.140
                  Master_User: u_repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 499
               Relay_Log_File: localhost-relay-bin.000002
                Relay_Log_Pos: 367
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1007
                   Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '9e2c7c0f-0908-11e7-8230-000c29ab7544:1' at master log mysql-bin.000001, end_log_pos 313. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 154
              Relay_Log_Space: 1513
              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: 0
                Last_IO_Error: 
               Last_SQL_Errno: 1007
               Last_SQL_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '9e2c7c0f-0908-11e7-8230-000c29ab7544:1' at master log mysql-bin.000001, end_log_pos 313. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 140
                  Master_UUID: 9e2c7c0f-0908-11e7-8230-000c29ab7544
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: 
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 170316 04:25:29
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 9e2c7c0f-0908-11e7-8230-000c29ab7544:1-2
            Executed_Gtid_Set: 347cbac6-0906-11e7-b957-000c2981a46e:1,
c59a2526-08fd-11e7-a5c7-000c296f2953:1-2
                Auto_Position: 1
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

ERROR: 
No query specified

2.在符合重复条件的记录中,把主键大于最小主键的记录全部删掉即可。

 

View Code

假设我有如下表,需要删除start_time和end_time都一样的重复记录。

今天,我在工作室换了一台电脑写Code,当我在附加数据库的时候,出现如下异常,折腾了半天,还是不行。于是我就重装SQL,重装之后还是不行。纠结了,当时我也忘记去google,傻傻的就把系统重装了(新机)。折腾差不多一天之后,系统、SQL、VS2010、补丁等等全都搞定之后,总算“大功告成了”,这个时候,我又跑去附加数据库。这回蛋疼了~~依然是失败。于是乎,有了这篇文章(好记性不如烂笔头):

GTID的复制对于错误信息的可读性不是很好,但可以通过错误代码(1007)从监控表replication_applier_status_by_worker查看:

图片 3

 

mysql> select * from performance_schema.replication_applier_status_by_worker where LAST_ERROR_NUMBER=1007G

那么存储过程如下:

出现错误 

图片 4图片 5

DELIMITER //
DROP PROCEDURE IF EXISTS Del_Dup_FOR_TEST;
CREATE PROCEDURE Del_Dup_FOR_TEST()
BEGIN
DECLARE min_id INT;
DECLARE v_start_time,v_end_time DATETIME;
DECLARE v_count INT;
DECLARE done INT DEFAULT 0;
DECLARE my_cur CURSOR FOR SELECT start_time,end_time,min(id),count(1) AS count FROM leo.test GROUP BY start_time,end_time HAVING count>1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN my_cur;
  myloop: LOOP
  FETCH my_cur INTO v_start_time,v_end_time,min_id,v_count;
  IF done=1 THEN
  LEAVE myloop;
  END IF;
  DELETE FROM leo.test WHERE start_time=v_start_time AND end_time=v_end_time AND id>min_id;
  COMMIT;
  END LOOP myloop;
CLOSE my_cur;
END;
//
DELIMITER ;

 

mysql> select * from performance_schema.replication_applier_status_by_worker where LAST_ERROR_NUMBER=1007G
*************************** 1. row ***************************
         CHANNEL_NAME: 
            WORKER_ID: 2
            THREAD_ID: NULL
        SERVICE_STATE: OFF
LAST_SEEN_TRANSACTION: 9e2c7c0f-0908-11e7-8230-000c29ab7544:1
    LAST_ERROR_NUMBER: 1007
   LAST_ERROR_MESSAGE: Worker 1 failed executing transaction '9e2c7c0f-0908-11e7-8230-000c29ab7544:1' at master log mysql-bin.000001, end_log_pos 313; Error 'Can't create database 'mydb'; database exists' on query. Default database: 'mydb'. Query: 'create database mydb'
 LAST_ERROR_TIMESTAMP: 2017-03-16 04:25:29
1 row in set (0.00 sec)

逻辑很清晰,就是根据重复判断条件依次删掉重复组中主键大于最小主键的记录们。

 

View Code

但是在编写过程中却遇到一个很恶心的BUG,我最初的内容是这么写的:

 图片 6

使用GTID跳过错误的方法:找到错误的GTID跳过(通过Exec_Master_Log_Pos去binlog里找GTID,或则通过上面监控表replication_applier_status_by_worker找到GTID,也可以通过Executed_Gtid_Set算出GTID),这里使用监控表来找到错误的GTID。找到GTID之后,跳过错误的步骤

DELIMITER //
DROP PROCEDURE IF EXISTS Del_Dup_FOR_TEST;
CREATE PROCEDURE Del_Dup_FOR_TEST()
BEGIN
DECLARE min_id INT;
DECLARE start_time,end_time DATETIME;
DECLARE count INT;
DECLARE done INT DEFAULT 0;
DECLARE my_cur CURSOR FOR SELECT start_time,end_time,min(id),count(1) AS count FROM leo.test GROUP BY start_time,end_time HAVING count>1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN my_cur;
  myloop: LOOP
  FETCH my_cur INTO start_time,end_time,min_id,count;
  IF done=1 THEN
  LEAVE myloop;
  END IF;
  DELETE FROM leo.test WHERE start_time=start_time AND end_time=end_time AND id>min_id;
  COMMIT;
  END LOOP myloop;
CLOSE my_cur;
END;
//
DELIMITER ;

 

mysql> stop slave; #停止同步
Query OK, 0 rows affected (0.02 sec)

mysql> set @@session.gtid_next='9e2c7c0f-0908-11e7-8230-000c29ab7544:1';  #跳过错误的GTID
Query OK, 0 rows affected (0.00 sec)

mysql> begin; #提交一个空事务,因为设置gtid_next后,gtid的生命周期就开始了,必须通过显性的提交一个事务来结束,否则报错:ERROR 1790 (HY000): @@SESSION.GTID_NEXT cannot be changed by a client that owns a
Query OK, 0 rows affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> set @@session.gtid_next=automatic; #设置回自动模式  
Query OK, 0 rows affected (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

不同的部分在于变量定义的名称,即:

这个是由于权限不足导致的,我们必须在【本地账号】的SQL中,新建一个【域帐号】的SQL用户,设置完成之后,还需要手动分配权限。详情如下:

再次确认slave同步状况

FETCH INTO的变量名绝对不能是你定义CURSOR时SQL语句查出来的列名或者列别名,也就说你定义的变量名既不能是表中已经存在的列名,也不能是你定义游标时用过的别名(如本例中的count),只要一个条件不符合,FETCH INTO就把全部的变量赋NULL值,这点你可以尝试在FETCH INTO后加一句Select打印变量名验证。

 

mysql> show slave statusG;

在查询到这个BUG之前去官网页面特地看了一下是否是我的语法有错误: ,确信语法没问题,但倒数第二条评论显示可能是列名的隐藏BUG,最后一条评论反驳了BUG说法,但没有办法我还是根据BUG REPORT做了以上修改,然后功能就正常了。

解决方法

图片 7图片 8

关于此BUG的BUG报告页面详见MySQL BUG:#28227 和 BUG:#5967

 

mysql> show slave statusG;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.206.140
                  Master_User: u_repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 499
               Relay_Log_File: localhost-relay-bin.000004
                Relay_Log_Pos: 454
        Relay_Master_Log_File: mysql-bin.000002
             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: 499
              Relay_Log_Space: 2024
              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: 140
                  Master_UUID: 9e2c7c0f-0908-11e7-8230-000c29ab7544
             Master_Info_File: mysql.slave_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: 9e2c7c0f-0908-11e7-8230-000c29ab7544:1-2
            Executed_Gtid_Set: 347cbac6-0906-11e7-b957-000c2981a46e:1,
9e2c7c0f-0908-11e7-8230-000c29ab7544:1-2,
c59a2526-08fd-11e7-a5c7-000c296f2953:1-2
                Auto_Position: 1
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

ERROR: 
No query specified

那么再回头看一下官网文档下的最后一条评论,开始我认为最后一条反驳BUG的评论完全是扯淡,是哪个傻X说这不是个BUG的?后来仔细想了想,他俩都对,这确实也算个BUG,傻X的也是我。

 图片 9

View Code

贴一下页面下最后两条评论(截止2018.08.01):

01、回到你系统的本地账号,然后登陆你的SQL,我这篇文章以登录(.)为例,如果你想登陆(.SQLEXPRESS),方法也一样,不做解释。

打完收工

Posted by Brent Roady on May 9, 2012
It should be noted that the local variable names used in FETCH [cursor] INTO must be different than the variable names used in the SELECT statement 
defining the CURSOR. Otherwise the values will be NULL. 
In this example, 
DECLARE a VARCHAR(255);
DECLARE cur1 CURSOR FOR SELECT a FROM table1;
FETCH cur1 INTO a;
the value of a after the FETCH will be NULL.
This is also described here: http://bugs.mysql.com/bug.php?id=28227

Posted by Jérémi Lassausaie on February 3, 2015
Answer for Brent Roady :
I don't see any bug in the bahaviour described.
DECLARE a VARCHAR(255);
/* you declare a variable "a" without a specified default value, a=NULL */
DECLARE cur1 CURSOR FOR 
SELECT a FROM table1;
/* You declare a cursor that selects "a" FROM a table */
OPEN cur1;
/* You execute your cursor query, a warning is raised because a is ambiguously defined but you don't see it */
FETCH cur1 INTO a;
/* you put your unique field in your unique row into a (basically you do "SET a=a;") so a is still NULL */
There is no bug report, just a misunderstanding.

 

本文由澳门十大赌场最新排名发布于澳门十大赌场,转载请注明出处:GTID复制错误处理之跳过错误,MySQL游标循环取出

关键词:

上一篇:澳门十大赌场最新排名事务日志概述,使用java实

下一篇:没有了