当前位置: 首页 > 科技观察

关于MySQL的日志,我跟阿里P9聊了什么?

时间:2023-03-13 02:21:59 科技观察

作者个人研发在高并发场景下提供了一个简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。开源半年多以来,已成功为十几家中小企业提供精准定时调度解决方案,经受住了生产环境的考验。为了造福更多的童鞋,这里放上开源框架的地址:https://github.com/sunshinelyz/mykit-delay前周末写的,和一位阿里P9资深技术达人聊天(我赢了'在这里提到这个名字)。MySQL的话题,为什么要讲这个?因为他看到我出了一本书《MySQL技术大全:开发、优化与运维实战》,而且书的评价也不错。后来我们聊了几个关于MySQL的话题,其中之一就是MySQL的日志机制。今天,我将一些一般聊天的内容,以文章的形式分享给大家。希望能给朋友们带来实质性的帮助!文章已收录于:https://github.com/sunshinelyz/technology-binghehttps://gitee.com/binghe001/technology-bingheMySQL日志说起MySQL日志,对MySQL至关重要的日志有以下三种,即:Binlog、UndoLog、RedoLog。由于Binlog和UndoLog有相似之处,我们将按照以下顺序介绍MySQL中的三大日志原理:UndoLog-->RedoLog-->Binlog。什么是撤消日志?UndoLog顾名思义就是undo操作的日志,指的是将MySQL中的数据恢复到某种状态。在MySQL数据库中,在事务开始之前,MySQL会将要修改的记录保存在UndoLog中。如果数据库崩溃或者事务需要回滚,MySQL可以使用UndoLog日志将数据库中的数据回滚到之前的状态。当MySQL增加、修改和删除数据时,它会在事务开始前将信息写入UndoLog。当事务提交时,UndoLog不会立即被删除。InnoDB存储引擎会将事务对应的UndoLog放入待删除列表中,然后在后台通过purge线程删除待删除列表。这里,值得注意的是:UndoLog是一种逻辑日志,记录了一个变化的过程。比如MySQL执行了一次删除操作,UndoLog会记录一次插入操作;如果MySQL执行了插入操作,UndoLog会记录删除操作;如果MySQL执行更新操作,UndoLog会记录相反的更新操作。UndoLog分段管理和记录日志信息。在InnoDB存储引擎的数据文件中,包含一个回滚段,称为rollbacksegment,其中包含1024条undologsenments。UndoLog的作用UndoLog对MySQL实现事务起着至关重要的作用。它实现了事务的原子性和多版本并发控制,也就是我们常说的MVCC。实现事务的原子性UndoLog可以实现MySQL事务的原子性。在事务处理过程中,如果MySQL发生错误或者用户手动执行了事务回滚操作(rollbackoperationperformed),MySQL可以使用UndoLog日志将数据库中的数据恢复到之前的状态。实现MVCC机制UndoLog实现了MySQL的InnoDB存储引擎中的多版本并发控制(MVCC)机制。在事务提交之前,UndoLog保存未提交的版本数据,UndoLog中的数据可以作为旧版本数据的副本或快照,供其他并发事务读取。事务A手动启动事务后,更新goods数据表中id为1的数据,首先将更新命中的数据写入UndoBuffer。在事务A提交之前,此时事务B手动启动事务,对goods数据表中id为1的数据进行查询操作。此时事务B会读取UndoLog中的数据返回给客户端。这就是MySQL中的MVCC机制。可以在MySQL中使用以下命令查看控制UndoLog日志的参数。showvariableslike'%innodb_undo%';RedoLog说的是MySQL中的UndoLog,我们来看看MySQL中的RedoLog。什么是重做日志?顾名思义,RedoLog字面意思就是重做日志,指的是当数据库出现意外情况时,能够重新执行某些操作的能力。在MySQL中,任何在事务中修改的数据都会将最新的数据写入RedoLog进行备份。在MySQL中,随着事务操作的执行,会产生RedoLog日志。当事务提交时,会产生RedoLog并写入RedoBuffer。事务提交后不会立即写入RedoBuffer。事务操作的脏页写入磁盘后,RedoLog的使命就完成了。此时RedoLog占用的空间可以被复用,会被后续的RedoLog覆盖。RedoLog的原理RedoLog可以实现事务的持久化,防止故障时脏页被写入表的ibd文件,MySQL服务重启时根据RedoLog重做,使未使用的Committed事务被持久化。这个过程可以简化如下图所示。RedoLog的写入机制RedoLog文件的内容是按顺序、循环的方式写入到文件中的。写满后返回第一个文件覆盖。WritePos是当前记录的位置。它在书写时向后移动。写到最后一个文件的末尾后,返回到0号文件的开头;更新记录到数据文件;WritePos和CheckPoint之间的空白部分可以用来记录新的操作。如果WritePos追上了CheckPoint,就说明满了,需要将CheckPoint向后移动来擦除数据。每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组至少有2个重做日志文件,默认为ib_logfile0和ib_logfile1。在MySQL中可以使用以下命令查看控制RedoLog的参数。showvariableslike'%innodb_log%';RedoLog写入机制当RedoLog日志信息从RedoBuffer持久化到RedoLog时,可以通过innodb_flush_log_at_trx_commit参数设置具体的持久化策略,具体策略如下。0:Redobuffer->OScache->flushcachetodisk每秒提交一次,一秒内的交易数据可能会丢失。该操作由后台主线程每1秒执行一次。1(默认值):RedoBuffer->OScache->flushcachetodiskisexecutedeverytimeatransactioniscommitted.这种方式最安全,性能也是最差的。2:RedoBuffer->每次事务提交都会执行OScache,然后后台Master线程每1秒执行一次OScache->flushcachetodisk。一般建议选择2这个值,因为MySQL挂了不会丢失数据,整个服务器宕机只会丢失1秒的事务提交数据。Binlog日志是什么?Binlog是记录所有MySQL数据库表结构变化和表数据修改的二进制日志。不记录select、show等查询操作的日志。Binlog日志以事件的形式记录,也包括语句执行的耗时。启用Binlog日志记录有两个最重要的使用场景。主从复制:在主库开启Binlog功能,让主库将Binlog传递给从库,从库拿到Binlog后进行数据恢复,实现主从数据一致性。数据恢复:使用mysqlbinlog等工具恢复数据。Binlog文件记录方式Binlog文件记录方式分为三种:STATEMENT、ROW、MIXED。具体含义如下。ROW模式ROW(row-basedreplication,RBR):日志会记录每一行数据的修改,然后在slave端修改相同的数据。优点:可以清楚的记录每一行数据的修改细节,可以完全实现主从数据同步和数据恢复。缺点:批量操作会产生大量的日志,尤其是altertable会让日志暴增。STATMENT模式STATMENT(statement-basedreplication,SBR):每条被修改数据的SQL都会记录在master的Binlog中。当slave在replicating的时候,SQL过程会被解析成原来master端执行过的SQL,然后再执行。简称SQL语句复制。优点:日志量小,减少磁盘IO,提高存储和恢复速度缺点:在某些情况下,会导致主从数据不一致,如last_insert_id()、now()等函数。MIXED模式MIXED(mixed-basedreplication,MBR):以上两种模式的混合使用,一般使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作,使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择写入模式。Binlog文件结构MySQL的Binlog文件结构共有三种版本,如下图所示。关于Binlog文件结构的具体信息,朋友们可以参考MySQL官方文档,具体链接为:https://dev.mysql.com/doc/internals/en/event-header-fields.htmlBinlog写入机制根据记录方式和操作触发事件事件产生日志事件(事件触发执行机制)。将事务执行过程中产生的日志事件(logevent)写入一个缓冲区,每个事务线程都有一个缓冲区。LogEvent存储在一个binlog_cache_mngr数据结构中,其中有两个buffer,一个是stmt_cache,用于存储不支持事务的信息;另一个是trx_cache,用于存储支持交易的信息。在提交阶段,事务会将产生的日志事件写入外部的binlog文件。不同事务将日志事件串行写入Binlog文件,因此一个事务包含的日志事件信息在binlog文件中是连续的,中间不会插入其他事务的日志事件。Binlog文件操作Binlog状态查看showvariableslike'log_bin';启用Binlog功能需要修改my.cnf或my.ini配置文件,在[mysqld]下添加log_bin=mysql_bin_log,重启MySQL服务。binlog-format=ROWlog-bin=mysqlbinloguseshowbinlogeventscommandshowbinarylogs;//相当于showmasterlogs;showmasterstatus;showbinlogevents;showbinlogeventsin'mysqlbinlog.000001';usemysqlbinlog命令mysqlbinlog"filename"mysqlbinlog"filename">"test.sql"usebinlogtorestoredata//根据指定时间恢复mysqlbinlog--start-datetime="2021-02-2818:00:00"--stopdatetime="2021-03-0100:00:00"mysqlbinlog.000001|mysql-uroot-p123456//根据事件位置号恢复mysqlbinlog--start-position=1789--stop-position=2674mysqlbinlog.000001|mysql-uroot-p123456删除Binlog文件purgebinarylogsto'mysqlbinlog.000001';//删除thespecifiedfilepurgebinarylogsbefore'2021-03-0100:00:00';//删除指定时间之前的文件resetmaster;//清除所有文件可以通过设置expire_logs_days参数来开启自动清理功能。默认值为0表示不启用。大于0的整数表示超过天数binlog文件将被自动清除。本文转载自微信公众号“银禾科技”,可通过以下二维码关注。转载本文请联系冰川科技公众号。