1.1.3 slowlog与binlog

前面就MySQL服务层中几个重要组件做了讲解,并重点讲解了整个执行过程。在执行过程中,最重要的两个日志是slowlog和binlog。

前面也提到,slowlog有两个函数,其中一个是thd->update_slow_query_status();另一个是log_slow_statement(thd, query_start_status_ptr)。为什么需要这两个函数呢?

因为第一个函数用于判断查询时间是否超过了long_query_time的阈值;而第二个函数是真正写slowlog的函数,相对比较复杂,它会先判断是否启用了无索引告警,然后判断是否开启了超时标志位。

说明

在代码中,确实会分开记录两个标志位,用于判断是否有long_query_time超时和no_index命中。

接下来会判断语句的耗时,它也是会被计入slowlog的时间开销。

slowlog在RDS中配置的表引擎是CSV引擎,这个引擎的特点是简单、好读取,缺点是不支持行锁,只有表级锁。对应的Handler会请求到这个引擎的函数上。

binlog则是MySQL服务层最重要的复制日志,很多图书和文献在解释binlog时都做了非常全面的介绍,尤其是MySQL 5.6和MySQL 5.7中半同步/增强半同步的区别,因此这里就不做过多介绍了。但是有一个复制的区别要注意,就是阿里云RDS for MySQL 5.6版本已经支持表级别的并发复制,而MySQL社区版是从5.7版本才开始有这个特性的。

binlog本身的好处就是易于解读,所以下游生态非常丰富。但作为复制日志,却不是多么先进的设计,因为基于binlog的复制,本质上就是逻辑复制,基本等价于Oracle Logical DataGuard,稳定性不能和物理复制相比。它的主要缺点如下:

在复制可靠性方面,因为不是物理复制,所以Master和Slave节点的空间不一样大,无法做页面级别的校验。

在复制性能方面,因为Slave节点还是要执行SQL语句的,所以可能会出现用错索引的情况。因此,RDS做了优化,加了隐式主键。即便这样,在某些极端场景下,比如UK有大量空值时,还是会出现复制性能问题。

在I/O影响方面,因为binlog文件是自然增长的,并不像redo日志文件天然就固定大小,所以写redo日志文件是Replace I/O,不需要更新文件系统的元数据;而写binlog文件则会带来元数据更新的Append I/O。这个细微差别,在I/O密集以后,容易导致文件系统抖动,jbd2进程容易hang住,这时候MySQL就会秒级响应异常。

关于如何彻底解决这个问题,将在2.3.2小节中再和大家探讨。

综上所述,我们要辩证地看待MySQL binlog,虽然在性能上存在一定程度的瓶颈,但正是因为binlog的易用性、易读性,才造就了MySQL生态圈的繁荣,这也是不可否认的事实。