0
点赞
收藏
分享

微信扫一扫

无涯教程-jQuery - jQuery.getScript( url, callback )方法函数

千妈小语 2023-07-27 阅读 76

Mysql原理系列篇 第一章 1条语句的执行

文章目录


前言:

对于mysql 数据存储工具,我们并不陌生,但是当我去执行1条sql 语句时,mysql 执行的流程是怎样的;


1 连接mysql 服务端:

1.1 通信模型:

服务实际上提供了多种通信的模型,可以适应不同的客户端连接到服务端;我们经常使用的是同步,tcp长连接的方式进行接入;
在这里插入图片描述

1.2 通信连接数:

客户端与服务端建立连接的数量并不是无限的,默认情况下,所有客户端共享默认的151 个连接;如果超出最大连接,MySQL 服务器可以将新的连接请求放入一个等待队列中。等待队列中的连接请求将按照先进先出(FIFO)的顺序进行处理。一旦有一个连接释放出来,MySQL 服务器就会将等待队列中的下一个连接请求分配连接资源,并建立新的连接。

MySQL 服务器会对空闲连接进行超时处理,以释放连接资源。连接超时的时间由配置参数 wait_timeout 控制,默认为8小时。当连接空闲时间超过 wait_timeout 的设定值后,MySQL 服务器会自动关闭该连接,并释放相关的资源.

通常我们可以通过调整 max_connections (最大值100000)参数来增加最大连接数:
在这里插入图片描述

2 sql 语句的到达存储引擎的流程:

在这里插入图片描述

  • 解析器:词法解析: 解析每个单词必须正确;语法解析:解析句子整体语法必须正确;语义解析:解析句子整体语义必须正确;
  • 语句优化: 将sql 语句进行相应优化,如:去除多余的嵌套层;
  • 执行计划:生成多个执行计划;
  • 执行器: 得到最终的一个执行计划,然后交由存储引擎执行;
  • 存储引擎:执行sql(不一定按照执行计划 执行sql);

3 数据从存储引擎返回的流程:

  • 存储引擎从磁盘获取数据,按照page 页进行加载,每个page 页为16k,将加载到的数据缓冲到Buffer_pool 内存中;
  • 如果是select:查询执行引擎负责执行查询计划,处理数据的过滤、聚合、排序等操作并将结果返回给 MySQL 服务器;
  • 如果是更新操作(包括update insert delete):则从加载到Buffer_pool 对应的数据,进行修改,修改完成后通过存储引擎将修改后的数据存入到Buffer_pool 内存中;
  • 位于Buffer_pool 内存中的更新数据会有后台线程定期还行,将数据刷到磁盘中;

4 Buffer_pool 脏页的刷脏:

4.1 刷脏的机制:

在缓冲池中进行数据的修改和处理后,并不立即写回到磁盘中。InnoDB 存储引擎会利用一种称为“脏页(Dirty Page)”的机制,将更新的数据页标记为脏页。然后,根据 InnoDB 的内部策略和算法,决定何时将脏页刷新回磁盘,这个过程称为“脏页刷新(Flush)”。

4.2 脏页数据丢失问题:

对于Buffer_pool 内存中的数据,如果出现mysql 服务宕机,其中的数据全部丢失,哪些来不及被刷到磁盘中的数据需要被保存;

redo log 日志:将还没有进行刷脏的更新数据,进行日志记录,当出现msyql宕机,当mysql 服务重启后从 redolog 中进行数据恢复,保证了内存数据的安全性,延迟刷盘时机,进而提升系统吞吐;

4.2 redolog 作用:

  • 为InnoDB提供了崩溃恢复的特性,实现持久性;
  • redo log记录的是“在某个数据页上做了什么修改”。属于物理日志;
  • redo log的大小是固定的,前面的内容会被覆盖,一旦写满,就会触发buffer pool到磁盘的同步,以便腾出空间记录后面的修改;
  • Redo Log的循环使用:Redo Log是循环使用的,意味着当Redo Log写满时,会从头开始覆盖之前的Redo Log数据。在进行循环时,需要确保Checkpoint位置之前的Redo Log数据已经被持久化,以免丢失一致性;

4.3 Buffer_pool 内存回收:

Buffer Pool的内存回收是指在MySQL中管理Buffer Pool的内存空间时,对不再需要的数据页进行回收释放。

MySQL的InnoDB存储引擎使用LRU(Least Recently Used)算法来管理Buffer Pool中的数据页。LRU算法通过维护一个链表,将最近访问的数据页放在链表的前端,而较久未被访问的数据页则放在链表的后端。

当Buffer Pool中的内存空间不足时,InnoDB存储引擎会根据LRU算法,从链表的末端开始,逐渐将较久未被访问的数据页从Buffer Pool中移除,以腾出更多的空间给其他数据页使用。被移除的数据页可能会写回到磁盘中(如果它们是脏页并且是更新操作),或者直接丢弃。

此外,InnoDB还支持一种称为"Adaptive LRU"的机制,它可以动态调整LRU算法的行为。Adaptive LRU根据系统访问模式和数据页使用频率的变化,自动调整链表中的热点数据页位置,以提高缓存命中率。

需要注意的是,Buffer Pool的内存回收是自动进行的,通常由后台线程负责管理。MySQL DBA和开发人员可以通过配置参数来调整Buffer Pool的大小,以适应不同的工作负载需求。

5 Mysql 的 binlog日志:

5.1 binlog 作用:

Binlog是用于记录MySQL服务器上的所有数据更改操作,包括对表结构的更改。Binlog记录了数据库中所有的操作语句,以及这些操作在执行时的上下文信息。Binlog是MySQL服务器层的一个组件,并不依赖于具体的存储引擎。通过读取Binlog,可以重放数据更改操作,进行数据恢复、复制、备份、查找历史数据等操作;

5.2 binlog 和redo log 为什么同时存在:

  • 持久性和事务恢复:Redo Log用于保证事务的持久性,能够在数据库崩溃或断电等故障时进行事务恢复。它只记录InnoDB存储引擎的数据修改操作。Redo Log是物理日志,主要目的是对数据进行恢复。

  • 数据复制和高可用:Binlog则用于实现数据复制和高可用性。通过读取Binlog中的数据变更操作,可以在其他MySQL实例上重放这些操作,从而实现数据的复制和同步。Binlog是逻辑日志,主要目的是对操作进行复制和恢复。

  • Redo Log 主要用于存储Buffer Pool 来不及存入磁盘的数据,提供mysql 宕机后的数据恢复,Redo Log的文件是有大小的,而且数据会被清理;

  • binlog 记录的是执行的操作语句,内容是不会被删除的,所以可以用作mysql的 主从复制;

6 binlog 和 redo log的协同工作:

6.1 工作流程:

在这里插入图片描述

  • 要想操作数据,需要存储引擎向将数据按页加载到 pool buffer 中;
  • 修改数据;
  • 将数据存回到pool buffer;
  • 记录redolog 日志方式数据丢失,二阶段提交记录数据 为prepare;
  • 记录binlog dml 语句;
  • 提交事务;
  • 将redolog 数据标记为commit;

6.2 崩溃恢复:

redolog 二阶段提交保证 redolong 和binlog 保持一致;在崩溃恢复时,判断事务是否需要提交:

  • binlog无记录,redolog无记录 情况:
    在redolog写之前crash,恢复操作: 回滚事务
  • binlog无记录,redolog状态prepare 情况:
    在binlog写完之前的crash,恢复操作: 回滚事务
  • binlog有记录,redolog状态prepare 情况:
    在binlog写完提交事务之前的crash,恢复操作:提交事务
  • binlog有记录,redolog状态commit 情况:
    正常完成的事务,不需要恢复

7 Mysql 的 undolog日志:

7.1 undolog 作用:

MySQL中的Undo Log(回滚日志)是与事务相关的一种日志,用于回滚(撤销)事务对数据库的修改操作。Undo Log记录了事务执行过程中对数据做的修改操作,包括插入、更新和删除等操作,在事务回滚时使用这些日志进行撤销,将数据恢复到事务开始之前的状态。
Undo Log有以下几个主要的作用:

  • 回滚:当事务执行过程中发生错误或者回滚操作时,Undo Log中记录的操作可以用于将数据恢复到之前的状态。

  • MVCC(多版本并发控制):MySQL的默认隔离级别是可重复读(Repeatable Read),通过使用Undo Log来支持MVCC,每个事务都能看到一致性的数据视图。

  • 读一致性:当一个事务在执行过程中,其他事务需要读取被修改的数据时,可以通过Undo Log获取到该数据的先前版本,从而保证了读操作的一致性。

  • 由于Undo Log的存在,MySQL能够提供ACID特性(原子性、一致性、隔离性和持久性),确保事务的可靠性和数据的完整性。

7.2 undolog 回滚机制:

7.2.1 undlog 日志格式:

当开启一个事务时,对于插入、修改和删除操作,MySQL的Undo Log会记录相应的日志。日志格式如下:

  • . 插入操作的日志格式:

    • UNDOINSERT
    • 记录了插入的行的数据(包括所有列的值)和逻辑位置信息(如表和页码)。
    • 这个日志信息可以用来撤销插入操作,即删除对应的行。
  • 修改操作的日志格式:

    • UNDOUPDATE
    • 记录了修改前的行的数据和逻辑位置信息(包括表和页码)。
    • 这个日志信息可以用来撤销修改操作,即恢复到修改前的数据状态。
  • . 删除操作的日志格式:

    • UNDODELETE
    • 记录了被删除的行的数据和逻辑位置信息。
    • 这个日志信息可以用来撤销删除操作,即重新插入已删除的行。

通过记录这些操作的Undo Log,MySQL能够实现数据的回滚。当事务回滚时,MySQL会按照事务的逆序执行Undo Log中的操作,将数据恢复到事务开始之前的状态。

Undo Log的工作方式可以理解为数据库在修改数据时,不是直接修改原始数据,而是将修改操作以日志的形式记录下来。这种日志记录的方式使得数据库具备了回滚的能力。通过从Undo Log中反向执行日志操作,数据库可以撤消对数据的修改,从而实现事务的回滚。

7.2.2 一条数据多次更新 undlog 日志记录:

在一个事务中对一条数据多次更新时,Undo Log会记录每个更新操作的日志,以便回滚事务时可以逆向执行这些更新操作。具体记录方式如下:

  • 首次更新操作:

    • 当第一次更新数据时,MySQL会将原始数据记录到Undo Log中,包括旧值和逻辑位置信息。
    • 这个Undo Log记录的类型为UNDOINSERT或UNDOUPDATE,具体取决于是首次插入还是修改操作。
  • 后续更新操作:

    • 如果在同一个事务中对同一条数据进行多次更新,后续的更新操作也会被记录到Undo Log中。
    • 这些更新操作的Undo Log会记录修改前的旧值和逻辑位置信息。
  • . 回滚操作:

    • 当事务回滚时,MySQL会根据Undo Log中的记录逆向执行相应的更新操作,将数据恢复到事务开始之前的状态。
    • 这些更新操作会按照事务中最后一次到第一次的顺序逆向执行。

通过记录每次更新操作的Undo Log,MySQL可以在回滚事务时按照更新操作的逆序将数据恢复到之前的状态。每个更新操作都会生成相应的Undo Log,包含修改前的旧值和逻辑位置信息。这样,当事务回滚时,Undo Log就能根据这些记录来逆向恢复数据,实现回滚操作。

7.3 undolog 怎么区分不同的事务:

为了区分不同的事务,Undo Log在记录时通常会包含一些标识信息来标记所属的事务。这些标识信息可以用于区分Undo Log属于哪个事务。具体的区分方式如下:

  • 事务ID(Transaction ID):

    • 每个事务在MySQL中都会被分配一个唯一的事务ID。
    • 当Undo Log记录更新操作时,通常会将所属事务的ID也记录下来。
    • 这样,Undo Log中的事务ID就可以用来区分不同的事务。
  • 版本号(Transaction Version):

    • 在一些特定的场景下,Undo Log也可以使用版本号来区分不同的事务。
    • 每个事在执行更新操作时,可能会为每个被修改的行分配一个递增的版本号。
    • 当Undo Log记录时,可以记录修改前的版本号,以便在回滚时恢复到正确的版本。

通过利用事务ID或版本号等标识信息,Undo Log可以区分不同的事务。这样,在回滚或恢复数据时,数据库就能根据这些标识信息来正确地找到属于特定事务的Undo Log,进行相应的操作。需要注意的是,不同数据库系统可能对Undo Log的实现方式和区分事务的方式有所不同。上述的标识信息只是常见的一种方式,具体的实现可能会有所差异。

7.4 undolog 大小和清理规则:

Undolog文件(也称为事务日志或回滚日志)在MySQL中是有大小限制的,通常通过参数配置进行设置。具体而言,undolog文件有以下两种类型:

  • ib_logfile:

    • 这是InnoDB存储引擎使用的undolog文件类型。
    • 默认情况下,每个InnoDB存储引擎的数据库实例会有两个ib_logfile文件,分别命名为ib_logfile0和ib_logfile1。
    • 这些文件的大小可以通过配置参数innodb_log_file_size进行设置,默认大小为48MB。
  • undo表空间:

    • 这是InnoDB存储引擎使用的Undo Log的文件类型。
    • 每个数据库实例可以拥有多个undo表空间文件,其数量和大小可以通过配置参数进行设置。
    • 对于每个undo表空间文件,其大小可以通过配置参数innodb_undo_tablespacesize进行设置,默认大小为10MB。

关于清理undolog文件的规则,具体而言,有以下几个方面的清理机制:

  • Checkpoint:

    • 在InnoDB中,有一个后台线程称为Checkpoint线程,定期将脏页(被修改的页)写入磁盘。
    • Checkpoint操作会将已经提交的事务对应的undolog文件中的记录清理掉,只保留未提交的事务的undolog记录。
  • 事务提交:

    • 当一个事务成功提交时,其对应的undolog记录也会被清理。
    • 因为已经提交的事务不再需要进行回滚,所以相应的undolog记录可以被清理以释放空间。
  • 重用空间:

    • 当undolog文件中的空间被清理后,这些空间可以被重用以记录新的更新操作。
    • 这样可以使得undolog文件得到更好地利用,减少生成新的undolog文件的频率。

以上是一些常见的undolog文件的大小限制和清理规则。需要注意的是,具体的清理机制可能会根据数据库的配置和版本而有所不同,因此实际操作可能会有一些细微的差异。

7.5 undolog 被占用完会发生什么:

当未提交的事务数据已经将undolog占满时,将会发生以下情况:

  • 无法提交新的事务:
    • 如果undolog已经被占满,那么无法再为新的事务分配undolog的空间。
    • 当新的事务尝试提交时,将会失败并返回错误,指示undolog已满。
  • 数据库性能下降:
    • 当undolog被占满后,数据库的性能可能会受到影响。
    • 由于无法为新的事务分配undolog空间,系统可能会出现阻塞或延迟,导致性能下降。

为了避免undolog被占满的问题,在设计和配置数据库时,应该根据实际需求合理设置undolog文件的大小、频繁提交事务以及及时清理undolog等策略来保证事务能够正常进行而不会占满undolog空间。

7.5 开启事务后一条sql 的执行流程:

在默认的事务隔离级别下(如MySQL的可重复读或串行化隔离级别),事务开启后执行的插入、更新、删除操作在事务提交之前不会立即持久化到磁盘上。相反,它们会先被写入到内存中的缓冲池(buffer pool)中。

缓冲池充当了内存中的数据写缓冲区,用于加速数据库的读写操作。在事务处理过程中,所有的变更都会被写入到缓冲池中,并且在缓冲池得到适当管理和刷新之前,数据不会直接写入到磁盘。

只有当事务提交时,MySQL才会将事务中所做的修改持久化到磁盘上,确保事务的原子性和持久性。此时,缓冲池中的数据会被刷新到磁盘上对应的数据文件中,包括数据页和日志文件。

需要注意的是,如果在事务提交之前发生了异常或数据库崩溃,那么未提交的事务更改将会被回滚,不会被持久化到磁盘。

如果需要立即将事务中的修改持久化到磁盘,可以使用COMMIT命令提交事务,这将会将缓冲池中的更改刷新到磁盘。此外,也可以使用FLUSH LOGS命令强制刷新日志文件到磁盘。

7.5 buffer pool 中的定时刷盘任务 对于尚未提交事务的sql 处理:

在buffer pool中的定时刷盘任务(通常称为checkpoint)执行时,如果遇到还未提交的事务的SQL操作,它们将按照以下方式处理:

  • 写入redo log:未提交的事务的修改操作会写入redo log中,以确保事务的持久性和恢复能力。Redo log是一个事务日志,会在定期checkpoint之前强制同步到磁盘,以防止数据丢失。因此,即使事务尚未提交,相关的修改操作仍会被记录在redo log中。

  • . 不会立即刷盘:在定时刷盘任务中,遇到还未提交的事务的SQL操作时,这些修改操作不会立即被刷写到磁盘。这是因为未提交的事务可能需要进行回滚或者继续提交。

  • 等待事务提交:未提交的事务的修改操作会在内存中等待事务提交。只有当事务提交时,相关的修改操作才会被刷写到磁盘。

  • 完整的事务日志记录:在未提交事务的情况下执行定时刷盘任务时,相关的事务日志记录会被写入到磁盘,确保数据库的一致性和完整性。这个机制可以在数据库崩溃或重启后,通过redo log进行事务恢复。

  • InnoDB使用undolog(回滚日志)来记录数据修改前的原状,这样在事务回滚时,会将undolog中的记录恢复到修改前的状态。另一方面,修改后的数据会在buffer pool(缓冲池)中,但不会立即写入磁盘。当遇到回滚操作时,InnoDB会利用undolog中的记录,恢复数据到修改前的状态,然后将修改后的数据从buffer pool中移除。

7.6 undolog,redolog ,binlog 和buffer pool 的写入顺序:

  • 修改后的数据首先会进入到buffer pool;
  • 如果开启了事务 将修改的数据记录到 undolog 日志进行持久化;
  • 由于buffer pool 是内存,所有要将执行的sql 写入到redolog 日志中;
  • 因为redolog 文件内容是会被定时清除的,所有将修改的数据记录到binlog 一份;
  • 当遇到事务回滚,根据undlog 将数据恢复到数据之前的状态,同事删除buffer pool修改后的数据,
    修改Redolog的状态,如果binlog 有语句记录,则改语句不会被执行;
  • binlog 是ROW模式,只有在事务提交时才会写入binlog,也就是说如果事务回滚,binlog中将不会有这个事务的任何信息;如果是STATEMENT或MIXED模式,记录的是SQL语句,那么每次开始一个新的事务时,会在binlog中写入一个BEGIN,事务提交就写入COMMIT,事务回滚就写入ROLLBACK。当进行数据恢复或复制时,MySQL会读取binlog中的内容,如果遇到BEGIN就开始执行,遇到COMMIT就提交,遇到ROLLBACK就回滚,不执行该事务的SQL语句;

总结

  • 为了提示读写速度,mysql 提供了buffer pool 内存,对于修改和查询操作,mysql 会按页加载数据到buffer pool 内存中;
  • 对于修改的数据,mysql 后端线程定时将buffer pool 的数据刷脏,持久化的磁盘中;
  • 为了防止buffer pool 数据因为mysql 宕机而丢失,通过redolog 将数据进行记录并进行持久化;
  • 因为redolog 日志大小是固定的,redolog 记录的日志数据会被清除,所以使用binlog 来对所有的sql 进行记录;
  • 对于事务中的sql mysql 会使用undlog 进行记录,当事务需要回滚时,使用改日志通过事务id 找到记录的数据进行事务回滚;
举报

相关推荐

0 条评论