MySQL逻辑架构MySQL的逻辑架构大致能够分为三层:
第一层:处置客户端毗连、受权认证,平安校验等。
第二层:办事器server层,负责对SQL解释、阐发、优化、施行操做引擎等。
第三层:存储引擎,负责MySQL中数据的存储和提取。
我们要晓得MySQL的办事器层是不办理事务的,事务是由存储引擎实现的,而MySQL中撑持事务的存储引擎又属InnoDB利用的最为普遍,所以后续文中提到的存储引擎都以InnoDB为主。
MySQL数据更新流程记住! 记住! 记住! 上边那张图,她是MySQL更新数据的根底流程,此中包罗redo log、bin log、undo log三种日记间的大致关系,好了闲话少说曲奔主题。
redo log(重做日记)redo log属于MySQL存储引擎InnoDB的事务日记。
MySQL的数据是存放在磁盘中的,每次读写数据都需做磁盘IO操做,若是并发场景下性能就会很差。为此MySQL供给了一个优化手段,引入缓存Buffer Pool。那个缓存中包罗了磁盘中部门数据页(page)的映射,以此来缓解数据库的磁盘压力。
当从数据库读数据时,起首从缓存中读取,若是缓存中没有,则从磁盘读取后放入缓存;当向数据库写入数据时,先向缓存写入,此时缓存中的数据页数据变动,那个数据页称为脏页,Buffer Pool中修改完数据后会根据设定的更新战略,按期刷到磁盘中,那个过程称为刷脏页。
MySQL宕机若是刷脏页还未完成,可MySQL因为某些原因宕机重启,此时Buffer Pool中修改的数据还没有及时的刷到磁盘中,就会招致数据丧失,无法包管事务的耐久性。
为领会决那个问题引入了redo log,redo Log如其名偏重于重做!它记录的是数据库中每个页的修改,而不是某一行或某几行修改成如何,能够用来恢复提交后的物理数据页,且只能恢复到最初一次提交的位置。
redo log用到了WAL(Write-Ahead Logging)手艺,那个手艺的核心就在于修改记录前,必然要先写日记,并包管日记先落盘,才气算事务提交完成。
有了redo log再修改数据时,InnoDB引擎会把更新记录先写在redo log中,在修改Buffer Pool中的数据,当提交事务时,挪用fsync把redo log刷入磁盘。至于缓存中更新的数据文件何时刷入磁盘,则由后台线程异步处置。
留意:此时redo log的事务形态是prepare,还未实正提交胜利,要等bin log日记写入磁盘完成才会变动为commit,事务才算实正提交完成。
如许一来即便刷脏页之前MySQL不测宕机也不妨,只要在重启时解析redo log中的更改记录停止重放,从头刷盘即可。
大小固定redo log接纳固定大小,轮回写入的格局,当redo log写满之后,从头从头起头如斯轮回写,构成一个环状。
那为什么要如斯设想呢?
因为redo log记录的是数据页上的修改,若是Buffer Pool中数据页已经刷磁盘后,那那些记录就失效了,新日记会将那些失效的记录停止笼盖擦除。

上图中的write pos暗示redo log当前记录的日记序列号LSN(log sequence number),写入还未刷盘,轮回往后递增;check point暗示redo log中的修改记录已刷入磁盘后的LSN,轮回往后递增,那个LSN之前的数据已经全落盘。
write pos到check point之间的部门是redo log空余的部门(绿色),用来记录新的日记;check point到write pos之间是redo log已经记录的数据页修改数据,此时数据页还未刷回磁盘的部门。当write pos逃上check point时,会先鞭策check point向前挪动,空出位置(刷盘)再记录新的日记。
留意:redo log日记满了,在擦除之前,需要确保那些要被擦除记录对应在内存中的数据页都已经刷到磁盘中了。擦除旧记录腾出新空间那段期间,是不克不及再领受新的更新恳求的,此刻MySQL的性能会下降。所以在并发量大的情况下,合理调整redo log的文件大小十分重要。
crash-safe因为redo log的存在使得Innodb引擎具有了crash-safe的才能,即MySQL宕机重启,系统会主动去查抄redo log,将修改还未写入磁盘的数据从redo log恢复到MySQL中。
MySQL启动时,不管前次是一般封闭仍是异常封闭,老是会停止恢复操做。会先查抄数据页中的LSN,若是那个 LSN 小于 redo log 中的LSN,即write pos位置,申明在redo log上记录着数据页上尚未完成的操做,接着就会从比来的一个check point动身,起头同步数据。
简单理解,好比:redo log的LSN是500,数据页的LSN是300,表白重启前有部门数据未完全刷入到磁盘中,那么系统则将redo log中LSN序号300到500的记录停止重放刷盘。
undo log(回滚日记)undo log也是属于MySQL存储引擎InnoDB的事务日记。
undo log属于逻辑日记,如其名次要起到回滚的感化,它是包管事务原子性的关键。记录的是数据修改前的形态,在数据修改的流程中,同时会记录一条与当前操做相反的逻辑日记到undo log中。
我们举个栗子:假设更新ID=1记录的name字段,name原始数据为小富,现改name为法式员内点事
事务施行update X set name = 法式员内点事 where id =1语句时,先会在undo log中记录一条相反逻辑的update X set name = 小富 where id =1记录,如许当某些原因招致办事异常事务失败,就能够借助undo log将数据回滚到事务施行前的形态,包管事务的完好性。

那可能有人会问:统一个事物内的一笔记录被屡次修改,那是不是每次都要把数据修改前的形态都写入undo log呢?
谜底是不会的!
undo log只负责记录事务起头前要修改数据的原始版本,当我们再次对那行数据停止修改,所产生的修改记录会写入到redo log,undo log负责完成回滚,redo log负责完成前滚。
回滚未提交的事务,即事务未施行commit。但该事务内修改的脏页中,可能有一部门脏块已经刷盘。若是此时数据库实例宕机重启,就需要用回滚来将先前那部门已经刷盘的脏块从磁盘上撤销。
前滚未完全提交的事务,即事务已经施行commit,但该事务内修改的脏页中只要一部门数据被刷盘,别的一部门还在buffer pool缓存上,若是此时数据库实例宕机重启,就需要用前滚来完成未完全提交的事务。将先前那部门因为宕机在内存上的将来得及刷盘数据,从redo log中恢复出来并刷入磁盘。
数据库实例恢复时,先做前滚,后做回滚。
若是你认真看过了上边的 MySQL数据更新流程图 就会发现,undo log、redo log、bin log三种日记都是在刷脏页之前就已经刷到磁盘了的,彼此协做更大限度包管了用户提交的数据不丧失。
bin log(归档日记)bin log是一种数据库Server层(和什么引擎无关),以二进造形式存储在磁盘中的逻辑日记。bin log记录了数据库所有DDL和DML操做(不包罗 SELECT 和 SHOW等号令,因为那类操做对数据自己并没有修改)。
默认情况下,二进造日记功用是封闭的。能够通过以下号令查看二进造日记能否开启:
mysql> SHOW VARIABLES LIKE 'log_bin';+---------------+-------+| Variable_name | Value |+---------------+-------+| log_bin | OFF |+---------------+-------+bin log也被叫做归档日记,因为它不会像redo log那样轮回写擦除之前的记录,而是会不断记录日记。一个bin log日记文件默认更大容量1G(也能够通过max_binlog_size参数修改),单个日记超越更大值,则会新创建一个文件继续写。
mysql> show binary logs;+-----------------+-----------+| Log_name | File_size |+-----------------+-----------+| mysq-bin.000001 | 8687 || mysq-bin.000002 | 1445 || mysq-bin.000003 | 3966 || mysq-bin.000004 | 177 || mysq-bin.000005 | 6405 || mysq-bin.000006 | 177 || mysq-bin.000007 | 154 || mysq-bin.000008 | 154 |bin log日记的内容格局其实就是施行SQL号令的反向逻辑,那点和undo log有点类似。一般来说开启bin log城市给日记文件设置过时时间(expire_logs_days参数,默认永久保留),要否则日记的体量会十分庞大。
mysql> show variables like 'expire_logs_days';+------------------+-------+| Variable_name | Value |+------------------+-------+| expire_logs_days | 0 |+------------------+-------+1 row in setmysql> SET GLOBAL expire_logs_days=30;Query OK, 0 rows affectedbin log次要应用于MySQL主从形式(master-slave)中,主从节点间的数据同步;以及基于时间点的数据复原。
主从同步通过下图MySQL的主从复造过程,来领会下bin log在主从形式下的应用。

用户在主库master施行DDL和DML操做,修改记录挨次写入bin log;
从库slave的I/O线程毗连上Master,并恳求读取指定位置position的日记内容;
Master收到从库slave恳求后,将指定位置position之后的日记内容,和主库bin log文件的名称以及在日记中的位置推送给从库;
slave的I/O线程领受到数据后,将领受到的日记内容依次写入到relay log文件最末端,并将读取到的主库bin log文件名和位置position记录到master-info文件中,以便鄙人一次读取用;
slave的SQL线程检测到relay log中内容更新后,读取日记并解析成可施行的SQL语句,如许就实现了主从库的数据一致;
基于时间点复原我们看到bin log也能够做数据的恢复,而redo log也能够,那它们有什么区别?
条理差别:redo log 是InnoDB存储引擎实现的,bin log 是MySQL的办事器层实现的,但MySQL数据库中的任何存储引擎关于数据库的更改城市产生bin log。
感化差别:redo log 用于碰碰恢复(crash recovery),包管MySQL宕机也不会影响耐久性;bin log 用于时间点恢复(point-in-time recovery),包管办事器能够基于时间点恢复数据和主从复造。
内容差别:redo log 是物理日记,内容基于磁盘的页Page;bin log的内容是二进造,能够按照binlog_format参数自行设置。
写入体例差别:redo log 接纳轮回写的体例记录;binlog 通过逃加的体例记录,当文件大小大于给定值后,后续的日记会记录到新的文件上。
刷盘时机差别:bin log在事务提交时写入;redo log 在事务起头时即起头写入。
bin log 与 redo log 功用其实不抵触而是起到相辅相成的感化,需要二者同时记录,才气包管当数据库发作宕机重启时,数据不会丧失。
relay log(中继日记)relay log日记文件具有与bin log日记文件不异的格局,从上边MySQL主从复造的流程能够看出,relay log起到一个直达的感化,slave先从主库master读取二进造日记数据,写入从库当地,后续再异步由SQL线程读取解析relay log为对应的SQL号令施行。
slow query log慢查询日记(slow query log): 用来记录在 MySQL 中施行时间超越指按时间的查询语句,在 SQL 优化过程中会经常利用到。通过慢查询日记,我们能够查找出哪些查询语句的施行效率低,耗时严峻。
出于性能方面的考虑,一般只要在排查慢SQL、调试参数时才会开启,默认情况下,慢查询日记功用是封闭的。能够通过以下号令查看能否开启慢查询日记:
mysql> SHOW VARIABLES LIKE 'slow_query%';+---------------------+--------------------------------------------------------+| Variable_name | Value |+---------------------+--------------------------------------------------------+| slow_query_log | OFF || slow_query_log_file | /usr/local/mysql/data/iZ2zebfzaequ90bdlz820sZ-slow.log |+---------------------+--------------------------------------------------------+通过如下号令开启慢查询日记后,我发现 iZ2zebfzaequ90bdlz820sZ-slow.log 日记文件里并没有内容啊,可能因为我施行的 SQL 都比力简单没有超越指按时间。
mysql> SET GLOBAL slow_query_log=ON;Query OK, 0 rows affected上边提到超越 指按时间 的查询语句才算是慢查询,那么那个时间阈值又是几嘞?我们通过 long_query_time 参数来查看一下,发现默认是 10 秒。
mysql> SHOW VARIABLES LIKE 'long_query_time';+-----------------+-----------+| Variable_name | Value |+-----------------+-----------+| long_query_time | 10.000000 |+-----------------+-----------+那里我们将 long_query_time 参数改小为 0.001秒再次施行查询SQL,看看慢查询日记里能否有变革。
mysql> SET GLOBAL long_query_time=0.001;Query OK, 0 rows affected公然再施行 SQL 的时,施行时间大于 0.001秒,发现慢查询日记起头记录了。
慢查询日记general query log一般查询日记(general query log):用来记录用户的所有操做,包罗客户端何时毗连了办事器、客户端发送的所有SQL以及其他事务,好比 MySQL 办事启动和封闭等等。MySQL办事器会根据它领受到语句的先后挨次写入日记文件。
因为一般查询日记记录的内容过于详细,开启后 Log 文件的体量会十分庞大,所以出于对性能的考虑,默认情况下,该日记功用是封闭的,凡是会在排查毛病需获得详细日记的时候才会临时开启。
我们能够通过以下号令查看一般查询日记能否开启,号令如下:
mysql> show variables like 'general_log';+---------------+-------+| Variable_name | Value |+---------------+-------+| general_log | OFF |+---------------+-------+下边开启一般查询日记并查看日记存放的位置。
mysql> SET GLOBAL general_log=on;Query OK, 0 rows affectedmysql> show variables like 'general_log_file';+------------------+---------------------------------------------------+| Variable_name | Value |+------------------+---------------------------------------------------+| general_log_file | /usr/local/mysql/data/iZ2zebfzaequ90bdlz820sZ.log |+------------------+---------------------------------------------------+施行一条查询 SQL 看看日记内容的变革。
mysql> select * from t_config;+---------------------+------------+---------------------+---------------------+| id | remark | create_time | last_modify_time |+---------------------+------------+---------------------+---------------------+| 1325741604307734530 | 我是播送表 | 2020-11-09 18:06:44 | 2020-11-09 18:06:44 |+---------------------+------------+---------------------+---------------------+我们看到日记内容详细的记录了所有施行的号令、SQL、SQL的解析过程、数据库设置等等。
一般查询日记error log错误日记(error log): 应该是 MySQL 中更好理解的一种日记,次要记录 MySQL 办事器每次启动和停行的时间以及诊断和出错信息。
默认情况下,该日记功用是开启的,通过如下号令查找错误日记文件的存放途径。
mysql> SHOW VARIABLES LIKE 'log_error';+---------------+----------------------------------------------------------------+| Variable_name | Value |+---------------+----------------------------------------------------------------+| log_error | /usr/local/mysql/data/LAPTOP-UHQ6V8KP.err |+---------------+----------------------------------------------------------------+留意:错误日记中记录的可并不是满是错误信息,像 MySQL 若何启动 InnoDB 的表空间文件、若何初始化本身的存储引擎,初始化 buffer pool 等等,那些也记录在错误日记文件中。
总结MySQL做为我们工做中最常接触的中间件,纯熟利用只算是入门,若是要在简历写上一笔精通,还需要深切领会其内部工做原理,而那7种日记也只是深切进修过程中的一个起点,学无行境,兄嘚干就完了!
以上。我们下篇见。







还没有评论,来说两句吧...