MySQL:主从报错中的位点解析


老是遇到类似的问题,一直没去看,就随便看了看,记录如下,仅供参考。


分析

报错信息如下:

Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 
'bogus data in log event; the first event '' at 4, the last event read from '/opt/bin/log_bin.000009' 
at 935, the last byte read from '/opt/bin/log_bin.000009' at 954.'

因为多次遇到这种错误,对于几个报错中提到的position不是很熟悉,稍微翻了一下,本错误来自函数Binlog_sender::log_read_error_msg,其由Binlog_sender::read_event调入,也就是dump线程读取event的时候,其中8.0有如下定义:

  • Binlog_read_error::BOGUS "bogus data in log event";
  • Binlog_read_error::EVENT_TOO_LARGE "log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master";
  • Binlog_read_error::MEM_ALLOCATE "memory allocation failed reading log event";
  • Binlog_read_error::TRUNC_EVENT "binlog truncated in the middle of event; consider out of disk space on master";
  • Binlog_read_error::CHECKSUM_FAILURE event read from binlog did not pass crc check";

而我们遇到的就是bogus data in log event,代表的是dump线程读取的event header中的event 长度小于的最小长度,这不可能,而我们遇到的时候是做了主库的binlog清理,而DUMP线程可能还在读取event。
那么几个position是什么意思呢?稍微看了一下总结如下,实际上就是:

snprintf(error_text, sizeof(error_text),
         "%s; the first event '%s' at %lld, "
         "the last event read from '%s' at %lld, "
         "the last byte read from '%s' at %lld.",
         m_errmsg, m_start_file, m_start_pos, m_last_file, m_last_pos,
         log_file, reader.position());
  • the first event '%s' at %lld 为 m_start_file, m_start_pos

为DUMP线程启动时候读取的position,对于auto_position这个值应该是空,因为auto_position传给dump线程的就是空position,其定位依赖的GTID。而对于传统的当然就是传过来的是需要读取的position。正常运行情况下可以直接输出一下这两个值,下面是auto_position的值。

(gdb) p m_start_pos
$8 = 4
(gdb) p m_start_file
$9 = 0x7fff9f2111e0 ""
(gdb) 
  • the last event read from '%s' at %lld 为m_start_pos, m_last_file

为dump线程最后一次无故障读取的event的位置,因为读取的时候要进行错误判断,如果报错了就不计入这个位置了,所谓的故障就是我们前面提到的这些故障。

  • the last byte read from '%s' at %lld. 为log_file, reader.position()

为dump线程最后一次读取的event位置,如果读取没有问题才会计入上面的指标,是不同的,但是一定大于上面的值。

后面两个位点就2行代码就解释了如下:

  if ((error= Log_event::read_log_event(log_cache, &m_packet, m_fdle.get(), NULL, checksum_alg,
                                        NULL, NULL, header))) //读取
    goto read_error;//如果报错走error逻辑

  set_last_pos(my_b_tell(log_cache));//否则记录m_start_pos,和m_last_file  

  void set_last_pos(my_off_t log_pos)
  {
    m_last_file= m_linfo.log_file_name;
    m_last_pos= log_pos;
  }

附录:报错栈

这里用的5.7的栈如下:

com_binlog_dump_gtid
 ->mysql_binlog_send
   ->Binlog_sender::run
     ->Binlog_sender::send_binlog
       ->Binlog_sender::send_events
         ->Binlog_sender::read_event
           ->Binlog_sender::log_read_error_msg

你可能感兴趣的:(MySQL:主从报错中的位点解析)