MYSQL 8 日志系统到底比MYSQL 5.X 好在哪里
实际上MYSQL 5.x的日志系统存在两个问题,导致一些性能问题,尤其在高并发写入和对数据修改的情况下,其中的瓶颈的问题在于两个瓶颈, 当多线程访问数据在落入到 log_buffer 的情况下,还是需要获取锁让写入有顺序性, 同时在获取redo已经将数据页面写入后,也会在log_buffer中将写入到日志中的顺序进行一个重排,这也是需要有顺序性.
有顺序性则就会有锁的需求,否则无法保证系统的硬性需求,所以性能的问题在这个部分就会产生. 下面的源代码中 log_sys->mutex, log_sys->flush_order_mutex, 对于日志的写入产生了两个锁.
为什么MYSQL 8 要解决这个问题,主要的原因是多CPU 在MYSQL中的使用越来越被支持,而瓶颈在于并发和顺序之间的矛盾.
MYSQL 8 解决关于锁的问题,采用了另一种方式,因为记录必须有顺序性,而不在增加锁,则顺序性如何完成, 这里MYSQL 8 采用的方式是预留空间的方式来对还未写的日志预留空间,然后
通过预留的方式,将log_sys->mutex 数据锁去掉 ,预留空间的方式可以进行并发的写入,保证了之前的部分的顺序性,但又没有相关的写入的强制的顺序性.
但这还没有完全解决问题,log_sys->flush_order_mutex 锁是解决最终刷入到日志中的锁. 如何避免这个锁.
MYSQL 8 提出了新的一个数据结构,来解决以下几个问题
1 填补的数据并没有完全填充满, 而其中有空洞的问题
2 怎么能不使用锁来将信息继续有序的刷入到日志中
这里MYSQL 8 采用了log_writer线程来检测日志中LOG BUFFER 有没有空洞的问题,如果有写入就会等待,通过并集的方式来确认LOG BUFFER 写入的日志是否有空洞,
上图是官方给出的图,通过并集很快的可以知道某个块是否是空, 写数据到log buffer也就从左到右的方式,并且看似是无序的但无序最终是有序的写入,但不在使用原来的两个锁,进行写入数据的控制.
通过更细化的设计,将原来的数据中的瓶颈化解, 这点的设计,其实和MYSQL GROUP REPLICATION 的化解原有数据复制的瓶颈的想法有共同的地方.
其中把log buffer 中的对应的dirty page 并不按照顺序添加到flush list. 用户写完log buffer 可以将相应的 log buffer 对应的dirty page 添加到flush list列表中,InnoDB 用一个recent_closed 来记录添加到flush list 的这一段log buffer 确认是否连续, 那么容易得出, flush list 上page lsn - recent_closed.size() 得到的lsn 用于做checkpoint同时InnoDB 后台有Log_closer 线程定期检查recent_closed 是否连续, 如果连续就把 recent_closed buffer 向前推进, 那么checkpoint 的信息也可以往前推进了.
这里借用某帖子关于MYSQL 8 改进后整体的数据写入的流程总结
在整体将MYSQL 8 相关的改进过了一遍后, 发现以下几个问题
1 有锁的设计相对简单,但有锁的设计并发性差
2 无锁的设计复杂,其中,中间段是优化的方面,将原来有序的写入,变为了无序的写入,加大了由于顺序+锁的方式造成的写入的性能瓶颈
3 虽然是无锁的设计,但最终数据的写入与原先设计的方式并没有区别,都是有序的.
这里面觉得相关的数据处理方式,由整体,变为分散处理,在重新归位整体, 增加了多线程并发写入的方式, 并且部分预处理了数据刷新到磁盘的方式提高了写入的速度.