MySQL---脏页机制

flush和脏页

InnoDB在处理更新语句的时候,磁盘操作仅写了redo log日志,同时并更新内存,之后当系统空闲时会把操作记录更新到磁盘里,MySQL把内存里的数据写入磁盘的过程我们称为flush

当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容一致,称为“干净页”。

flush触发条件

  1. InnoDB redo log日志写满。此时系统会停止所有更新操作,把checkpoint往前推进,为redo log留出空间。 MySQL日志—redo log和binlog
  2. 系统内存不足。当需要新的内存页,而内存不够用的时候,就要淘汰一些数据页,空出内存给别的数据页使用。如果淘汰的是“脏页”,就要先将脏页写到磁盘。
  3. MySQL空闲
  4. MySQL正常关闭。MySQL正常关闭前会把内存的脏页都flush到磁盘上,这样下次MySQL启动的时候,就可以直接从磁盘上读数据,启动速度会很快。

第一种情况InnoDB要尽量避免,因为出现这种情况整个系统就不能再接受更新了,所有的更新都必须堵住,这时候的更新数会跌为0。

第二种是“内存不够用了,要先将脏页写到磁盘”,这种情况很常见。但是出现以下这两种情况,都是会明显影响性能的:

  1. 一个查询要淘汰的脏页个数太多,会导致查询的响应时间明显变长。
  2. 日志写满,更新全部堵住,写性能跌为0,对于某些业务无法接受。

InnoDB刷脏页的控制策略

首先需要正确地告诉InnoDB所在主机的IO能力,这样InnoDB才能知道需要全力刷脏页的时候可以刷多快。

MySQL5.5版本里,innodb_io_capacity参数可以动态调整刷新脏页的数量,innodb_io_capacity参数默认是200,单位是页。该参数设置的大小取决于硬盘的IOPS,即每秒的输入输出量(或读写次数)。

刷脏页的速度该如何设置呢?

InnoDB的刷盘速度需要参考两个因素:一个是脏页比例,另一个是redo log写盘速度。InnoDB会根据这两个因素先单独算出两个数字。

参数innodb_max_dirty_pages_pct是脏页比例上限,默认值是75%。InnoDB会根据当前的脏页比例(假设为M),算出一个范围在0到100之间的数字,这个计算公式可以记为F1(M)。

InnoDB每次写入的日志都有一个序号,当前写入的序号跟checkpoint对应的序号之间的差值,我们假设为N。InnoDB会根据这个N算出一个范围在0到100之间的数字,这个计算公式可以记为F2(N)(N越大,算出来的值越大)。

取F1(M)和F2(N)最大值R,按照R%的速度刷脏页。

在使用数据库开发实际项目时,经常会遇到多个事务并发执行的情况。事务一方面可以保障数据的一致性,但另一方面也可能因为并发带来一些“隐藏的问题”。为了保障数据的正确性,MySQL 提供了不同的事务隔离级别来应对这些问题 [^2]。 事务是为了保证 SQL 之间不产生数据。在 innodb 中,默认没有被包裹在事务中的一个单条 SQL 就是一个事务。事务具有 ACID 四个特征 [^4]: - 原子性 (Atomicity):一个事务是一个不可分割的工作单元,事务中的所有操作要么全部成功执行,要么全部不执行。如果事务中的任何部分失败,则整个事务将被回滚到事务开始前的状态 [^4]。 - 一致性 (Consistency):在事务开始和结束时,数据库都必须处于一致状态。这意味着事务的执行不会违反任何数据库约束或规则,并且会保持业务逻辑上的一致性。一旦事务完成,它应该使数据库从一个有效状态变为另一个有效状态 [^4]。 - 隔离性 (Isolation):并发执行的多个事务之间互不干扰,如同它们是按顺序独立执行一样。这防止了读(读取未提交的数据)、不可重复读(在同一事务内多次读取同一数据时结果不同)和幻读(在事务中多次执行相同的询时,由于其他已提交事务的插入或删除操作导致结果集发生变化)等现象 [^4]。 - 持久性 (Durability):当事务成功提交后,其对数据库所做的修改将会永久保存,即使系统发生故障(如崩溃、重启等)也不会丢失这些修改。持久性通常是通过日志记录和恢复机制来保证的 [^4]。 事务的隔离性指的是,当并发产生多个事务时,各个事务相互之间相互隔离、互不影响。对于隔离性来说,数据库可以设置不同的隔离级别,隔离级别越高,事务之间的相互影响程度就越低,但是并发程度也会随之下降 [^1]。 数据库系统提供了四种事务隔离级别供用户选择 [^5]: - Serializable(串行化):一个事务在执行过程中完全看不到其他事务对数据库所做的更新,事务执行的时候不允许别的事务并发执行,事务串行化执行,只能一个接着一个地执行,而不能并发执行。 - Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他事务对已有记录的更新。 - Read Committed(读已提交数据):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新。 - Read Uncommitted(读未提交数据):一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新。 以下是设置事务隔离级别的示例代码: ```sql -- 请不要在本代码文件中添加空行!!! use testdb1; -- 设置事务的隔离级别为 read uncommitted set session transaction isolation level read uncommitted; -- 开启事务 start transaction; insert into dept(name) values('运维部'); -- 回滚事务 rollback; /* 结束 */ ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值