Mysql技术内幕InnoDB存储引擎读书笔记

1、Mysql体系结构

1.1库和实例的定义

数据库是文件的集合
数据库实例是应用程序,用户操作(增删改查数据)数据库要通过数据库实例。
1.2mysql整体架构
在这里插入图片描述1.连接池组件
2.管理服务和工具组件
3.Sql接口组件
4.查询分析器
5.优化器
6.缓存(cache)组件
7.插件式存储引擎
8.物理文件

通过上图可以看出mysql分为四层,分别为连接层、服务层、存储引擎层、存储层。
连接层:连接池组件
服务层:从左向右分别为:管理服务和工具组件、SQL接口组件、查询分析器组件、优化器组件、缓冲组件
存储引擎层:插件式存储引擎
存储层:硬盘、物理文件 图中的NTFS/ext2/3/4等为其硬盘格式

Mysql的存储引擎是插件式的表存储引擎,可以自行开发存储引擎。引擎基于表

1.2存储引擎
最常用的存储引擎
Innodb:支持事务、行锁、外键、聚簇索引,并发性能好 。Mysql5.5之后的默认引擎
MyIsam :不支持事务、表锁、非聚簇索引,查询速度快支持全文检索。Mysql5.5之前的默认引擎

其他需要了解的引擎
MEMORY
它在内存中处理所有数据,访问速度快。它非常适合用于存储临时数据的临时表 用于快速查找引用和其他相同的数据。
ARCHIVE
Archive存储引擎只支持INSERT和SELECT操作,从MySQL5.1开始支持索引。Archive存储引擎索引zlib算法将数据行(row)进行压缩后存储,压缩比一般可达1:10。正如其名字所示,Archive存储引擎非常适合存储归档数据,比如日志信息

MyIsam Innodb应用场景及区别:
MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。
InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。

1.二者的缓存策略不同:
innodb buffer pool(缓存池)大, innodb的数据和索引会都缓存进内存自己管理;不分索引文件数据文件
而myisam只有索引在内存里, 其他字段的缓存靠操作系统本身的cache
2.结构及索引类型不同
MyISAM :在磁盘上存储成三个文件。 .frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。
B+Tree的叶子节点上的data,并不是数据本身,而是数据存放的地址(页编号和偏移量offset)

InnoDB:存成两个文件 .frm文件存储表定义 .ibd存储索引及数据
B+Tree的叶子节点上的data是数据本身(所以他的索引和数据在同一个文件中)

为什么mysql的存储引擎MyISam比InnoDB查询速度快

缓存策略不同
1)数据块,INNODB要缓存,MYISAM只缓存索引块,这中间还有换进换出的减少;

结构及索引类型不同
2)innodb寻址要映射到块,再到行,MYISAM 记录的直接是文件的OFFSET,定位比INNODB要快
INNODB在做SELECT的时候,要维护的东西比MYISAM引擎多很多;

innodb需要支持事务
3)INNODB还需要维护MVCC一致;虽然你的场景没有,但他还是需要去检查和维护
MVCC ( Multi-Version Concurrency Control )多版本并发控制
InnoDB:通过为每一行记录添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。但是InnoDB并不存储这些事件发生时的实际时间,相反它只存储这些事件发生时的系统版本号。这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。让我们来看看当隔离级别是REPEATABLE READ时这种策略是如何应用到特定的操作的:
  SELECT InnoDB必须每行数据来保证它符合两个条件:
  1、InnoDB必须找到一个行的版本,它至少要和事务的版本一样老(也即它的版本号不大于事务的版本号)。这保证了不管是事务开始之前,或者事务创建时,或者修改了这行数据的时候,这行数据是存在的。
  2、这行数据的删除版本必须是未定义的或者比事务版本要大。这可以保证在事务开始之前这行数据没有被删除。

2、sql执行顺序
一、手写SQL顺序
select <select_list>
from <table_name>
<join_type> join <join_table> on <join_condition>
where <where_condition>
group by <group_by_list>
having <having_condition>
order by <order_by_condition>
limit <limt_number>
二、Mysql执行顺序
from
on <on_condition>
<join_type> join <join_table>
where <where_condition>
group by <group_by_list>
<sum()avg()等聚合函数>
having <having_condition>
select <select_list>
distinct
order by <order_by_condition>
limit <limit_number>

3、InoDB体系结构
3.1 InnoDB整体架构
内存池(维护内部数据结构,缓存磁盘数据加速读取,redolog缓冲)

在这里插入图片描述
上图展示了 Innodb存储引擎的体系架构,Innodb存储引擎有多个内存块,可以认为这些内存块组成了一个大的内存池,负责如下工作:
维护所有进程/线程需要访问的多个内部数据结构
缓存磁盘上的数据,方便快速读取,同时在对磁盘文件的数据修改之前在这里缓存
重做日志缓冲

后台线程
后台线程的主要工作是负责刷新内存池中的数据,保证缓冲池中的内容缓存的是最近的数据。此外将已修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常的情况下Innodb能恢复到正常运行状态。

Master Thread
核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲、Undo页的回收等。
IO Thread
在Innodb存储引擎中大量使用了AIO来处理写IO请求,通过这种方式大大保证了数据库的性能。IO thread的工作主要是负责这些IO请求的回调。Innodb 1.0版本之前共有4个IO thread,分别是write、read、insert buffer、log IO thread,并且其数量不能进行调整。从Innodb1.0.x开始,read和write线程分别增大到了4个,并且可以通过innodb_read_io_threads和innodb_write_io_threads进行设置。可以通过show engine innodb status可以查看其IO thread状态。
Purge Thread
当事务被提交后,其所使用的undolog不再需要,因此需要purge Thread来回收已经使用并分配的undo页。InnoDB 1.1版本前在Master thread中进行。1.1版本开始独立出来,但是数量只能设置为1。1.2版本开始,Innodb 支持多个Purge Thread。
Page Cleaner Thread
在innodb 1.2.x版本中引入,其作用是将之前版本中脏页的刷新操作都放入到单独的线程中来完成。进一步减轻Master Thread的工作。
内存
缓冲池
Innodb是基于磁盘存储的,缓冲池简单来说就是一块内存区域,通过内存的速度来弥补磁盘速度较慢对数据库性能的影响。在数据库中进行读取页的操作时,首先将从磁盘读到的页放到缓冲池中,该过程称为将页FIX到缓冲池中,下次读取相同的页时,会判断缓冲池中是否存在,存在则直接命中。
同理,对数据库的页有修改操作时,首先修改缓冲池中的页,然后再以一定的频率刷新到新的磁盘上。要注意的是,并不是每次修改都会刷新到磁盘上,而是根据Checkpoint的机制刷新回磁盘。因此,缓冲池的大小同样影响了数据库的整体性能,可以通过参数innodb_buffer_pool_size来设置。
缓冲池中缓存的数据页类型有:索引页、数据页、undo页、插入缓存、自适应哈希索引、InnoDB存储的锁信息、数据字典信息等。同时从innodb 1.0.x版本开始,允许有多个缓冲池实例,每个页根据哈希值平均分配到不同的缓冲池实例中。可以通过innodb_buffer_pool_instances来进行配置。
在这里插入图片描述
LRU List、Free List、Flush List
缓冲池中存放了很多的页,其是通过LRU(Latest Recent Used最近最少使用)算法来进行管理的。这个算法原理为最频繁使用的页在LRU列表的前端,而最少使用的页在LRU的尾端,当缓冲池中不能读取到新的页时,将首先释放LRU列表中尾端的页。
在innodb存储引擎中,缓冲池中页的大小默认为16kb。在使用LRU算法时进行了一些优化,在LRU列表中加入了midpoint位置。新读取到的页虽然是最新访问的页,但并不是直接放到LRU列表的首部,而是放到midpoint位置。该位置在LRU列表的5/8处,也就是在LRU列表尾端的37%处。midpoint 之后的列表称为old列表,之前的列表称为new列表。可简单的理解为最为活跃的热点数据。
为什么要对LRU进行优化呢?因为有些操作需要访问表中的许多页,甚至为全部的页,这些数据仅仅在本次查询中有用。如果使用原本的LRU算法那么就很有可能将热点数据从LRU列表中全部移除。为了解决此问题,又引入了innodb_old_blocks_time,用于表示页读取到mid位置后需要等待多久才会被加入到LRU列表的热端。通过这两种方式保证了上述问题的解决。还可以通过innodb_old_blocks_pct来调整midpoint的位置。
Innodb存储引擎从1.0.x版本开始支持压缩页的功能,将原本16kb的页变为1kb、2kb、4kb、8kb。对于非16kb的页,通过unzip_LRU进行管理的。对于不同压缩大小的页进行分别管理,那么内存分配是怎么进行的呢?通过伙伴算法进行内存的分配。例如对需要从缓冲池中申请页为4kb的大小,其过程如下:
1.检查4kb的unzip_LRU列表,检查是否有可用的空闲页
2.若有,则直接使用
3.否则,检查8kb的unzip_LRU列表
4.若能够得到空闲页,将页分成2个4kb的页,存放到4kb的unzip_LRU列表
5.若不能得到空闲页,则从LRU列表中申请一个16kb的页,将页分为1个8kb的页,2个4kb的页,分别存放到对应得unzip_LRU列表中。
LRU、Free、Flush列表关系如下:其中flush列表中的页刷新回磁盘使用的checkpoint机制,下篇博客进行说明。
在这里插入图片描述
重做日志缓冲
重做日志信息先进入缓冲区,然后以一定的频率将其刷新到重做日志文件。缓冲区大小可以通过innodb_log_buffer_size控制,默认为8m。
重做日志缓冲刷新到磁盘的情况如下:
Master Thread线程每1秒将重做日志缓冲刷新到重做日志文件
每个事务提交时将重做日志缓冲刷新到重做日志文件
当重做日志缓冲剩余空间小于1/2时,重做日志缓冲刷新到重做日志文件
额外内存池
在innodb存储引擎中,对内存的管理是通过一种称为内存堆的方式进行的。对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当区域的内存不够时,会从缓冲池中进行申请。因此在申请很大的innodb缓冲池时,也应考虑相应的增加这个值。

4、文件
在这里插入图片描述
在这里插入图片描述
日志文件:redo log binlog undolog
一、重做日志(redo log)
作用:
确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。
二、回滚日志(undo log)
作用:
保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读
undo log分为:
insert undo log
update undo log

三、二进制日志(binlog):
作用:
用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。
用于数据库的基于时间点的还原。

redo log和binlog区别
redo log是属于innoDB层面,binlog属于MySQL Server层面的,这样在数据库用别的存储引擎时可以达到一致性的要求。
redo log是物理日志,记录该数据页更新的内容;binlog是逻辑日志,记录的是这个更新语句的原始逻辑
redo log是循环写,日志空间大小固定;binlog是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖。
binlog可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用。
数据库数据存放的文件称为data file;日志文件称为log file;数据库数据是有缓存的,如果没有缓存,每次都写或者读物理disk,那性能就太低下了。数据库数据的缓存称为data buffer,日志(redo)缓存称为log buffer;既然数据库数据有缓存,就很难保证缓存数据(脏数据)与磁盘数据的一致性。比如某次数据库操作:
update driver_info set driver_status = 2 where driver_id = 10001;
更新driver_status字段的数据会存放在缓存中,等待存储引擎将driver_status刷新data_file,并返回给业务方更新成功。如果此时数据库宕机,缓存中的数据就丢失了,业务方却以为更新成功了,数据不一致,也没有持久化存储。
在数据库的世界里,数据从来都不重要,日志才是最重要的,有了日志就有了一切。
因为data buffer中的数据会在合适的时间 由存储引擎写入到data file,如果在写入之前,数据库宕机了,根据落盘的redo日志,完全可以将事务更改的数据恢复。好了,看出日志的重要性了吧。先持久化日志的策略叫做Write Ahead Log,即预写日志。

checkpoint:
checkpoint是为了定期将db buffer的内容刷新到data file。当遇到内存不足、db buffer已满等情况时,需要将db buffer中的内容/部分内容(特别是脏数据)转储到data file中。在转储时,会记录checkpoint发生的”时刻“。在故障回复时候,只需要redo/undo最近的一次checkpoint之后的操作。

5、表
在这里插入图片描述
表空间
表空间可以看做是InnoDB逻辑结构存储的最高层,所有的数据存放在表空间中。在默认情况下Innodb存储引擎有一个共享表空间ibdata1,所有的数据都存放在这个表空间内。如果用户启用了innodb_file_per_table参数,则每张表内的数据可以单独放在一个表空间内。需要注意的是,每张表的表空间只存放数据、索引、插入缓冲Bitmap页。其他的数据,例如回滚信息(undo),插入缓冲索引页、系统事务信息、二次写缓冲等还是存放在由来的共享表空间。

6、索引
B+树索引并不能直接找到数据行,而是定位到数据行所在页,然后把页读入内存再在内存中查找。
页是innodb引擎最小的磁盘单位。
B+树是一种适用于磁盘存储的数据结构,每一个节点对应一块磁盘块也就是innodb的数据页。根节点及内部节点只存储键值,叶子节点存储键值及数据行。插入数据时需要查询index page 及left page是否存在空间,不存在空间需要进行拆分页的操作来保证b+树的平衡。删除数据时需要判断叶子节点和中间节点与填充因子之间的关系,然后相应的进行页合并。

聚集索引
B+树的叶子节点也就是数据页是双向链表,聚集索引顺序与行的物理顺序相同
辅助索引的叶子节点的索引行中包含了一个书签,用于告诉辅助索引在哪里找到它对应的数据行,其实该书签也就是聚集索引的键值,故辅助索引查询时先查询辅助索引找到索引行获取主键索引再查找主键索引获取数据行相当于走了两次索引。

Mysql支持倒排索引

在InnoDB存储引擎中,将(DocumentId,Position)视为一个“ilist”。因此在全文检索的表(辅助表,见下)中,有两个列:
一个是word字段。在word字段上有设有索引
另一个是ilist字段
当前InnoDB的全文索引还存在以下的限制:
每张表只能有一个全文检索的索引
由多列组合而成的全文检索的索引列必须使用相同的字符集与排序规则
不支持没有单词界定符(delimiter)的语言,如中文、日语、韩语等


Lock与latch
latch一般称为闩锁,又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界自资源的正确性,通常没有死锁检测机制。
lock的对象是事务,一般在commit或rollback之后进行释放。其是有死锁机制的。
在这里插入图片描述共享锁与排他锁
行锁分为:共享锁(S Lock)、排他锁(X Lock)。如果一个事务已经获得了行r的共享锁,那么另外的事务可以立即获得r的共享锁,称为锁兼容。如果两个是排他锁,那么后一个事务必须等待前一个事务执行完成释放锁,该情况为锁不兼容
在这里插入图片描述
共享锁(读锁):其他事务可以读,但不能写。
排他锁(写锁) :其他事务不能读取,也不能写。
可以通过以下语句给sql显式的加共享锁和排他锁:
共享锁:select …… lock in share mode;
排他锁:select …… for update;
MySQL 不同的存储引擎支持不同的锁机制
MyISAM 和 MEMORY 存储引擎采用的是表级锁(table-level locking)
BDB 存储引擎采用的是页面锁(page-level locking),但也支持表级锁
InnoDB 存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁: 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
适用:从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。

Record Locks(记录锁)Gap Locks(间隙锁)Next-Key Locks(临键锁)是锁的三种算法
Record Locks(记录锁):在单行索引记录上加锁也就是行锁。
Gap Locks(间隙锁):在索引记录之间加锁,锁定一个范围但是不包含记录本身。
比如目前索引列的字段存在 2349 四条记录
SELECT * FROM table WHERE id BETWEN 1 AND 10 FOR UPDATE;
在数据库参数中, 控制间隙锁的参数是:innodb_locks_unsafe_for_binlog, 这个参数默认值是OFF, 也就是启用间隙锁
Next-Key Locks(临键锁):在索引记录上加锁,并且在索引记录之前的间隙加锁。它相当于是Record Locks与Gap Locks的一个结合。 锁住1-9这个取间的话就是锁住9行 但是是锁住左开右闭的一段取间。临键锁可以解决幻读

当我们使用索引进行范围查询,命中了记录的情况下,就是使用了临键锁,他相当于记录锁+间隙锁。
唯一性索引,等值查询匹配到一条记录的时候,退化成记录锁。
没有匹配到任何记录的时候,退化成间隙锁。

只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。

谈谈对数据库事务的理解:
系统在实际的业务中操作数据库不会是单线程单条sql执行的,而更可能是并发执行并且一次执行操作很可能是多条sql组成的一组sql,数据库事务就是应用于这样的相对复杂的场景,通过mysql提供的各类工具去维护数据库的四性,例如undo log去实现一次执行的操作要么全做要么全不做,过程中出现问题就借助undo log去回滚这样就保证了数据库事务的原子性,通过读写锁和MVCC去隔离事务使并发操作同一份数据的多个事务之间的操作互不影响保障隔离性,通过redo log保证持久性。实现了原子操作、事务间隔离、数据持久化之后也就满足了事务执行前后都是一致状态也就是特性中的一致性,一致性其实就是前面三种特性的总和靠前三性保障。
7、事务

数据库的事务是指一组sql语句组成的数据库逻辑处理单元,在这组的sql操作中,要么全部执行成功,要么全部执行失败。

事务的特性:
ACID
原子性:要么全做要么全不做 通过 undo log 来实现的
隔离性:多个事务之间的操作互不影响 通过 (读写锁+MVCC)来实现的
持久性:事务一旦提交就持久化存储 通过 redo log 来实现的
一致性:事务执行前后都是一致状态 通过原子性,持久性,隔离性来实现的!!

事务的隔离说白了就是事务的并发控制,隔离事务之间的操作,使得各个事务之间的操作不受影响。隔离性靠锁来实现,一般数据库都会提供各种粒度的锁用来提高事务的并发性能。原子性、隔离性、持久性都是为了保障一致性而存在的,一致性也是最终的目的。

Redolog保证持久性,记录的是某行数据修改后的值,redolog分为redolog buffer。事务修改或新增的数据先进入redologbuffer ,事务提交后 后台线程会将buffer刷入磁盘中的redolog中,再之后后台线程会根据redolog向datafile写入数据。
Undolog 保证原子性,记录的是某行数据修改前的值,用于回滚。
mysql 为了提升性能不会把每次的修改都实时同步到磁盘,而是会先存到Boffer Pool(缓冲池)里头,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步。

Mysql中四种事务隔离级别:
读未提交、读已提交、可重复读、串行化
事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted) 是 是 是
不可重复读(read-committed) 否 是 是
可重复读(repeatable-read) 否 否 是
串行化(serializable) 否 否 否

脏读就是事务A可以读到事务b尚未提交的数据,事务B回滚了,则事务A读到了错误数据。
不可重复读,是指事务A在一次事务过程中读取多次同一行数据,事务b在A的两次读取间隙中修改该数据并提交导致事务A两次读取的数据不一致。
幻读
一个事务两次查询同一范围内的行,第二次查询多出新的数据。可以通过加间隙锁解决

事务插入数据的过程

一、从缓存区到磁盘的过程
innodb_flush_log_at_trx_commit参数设置redo log重做日志策略:
0:commit时,redo log写入到redo log buffer中,每隔固定时间,写入OS buffer并刷新到磁盘;(性能最好,高可用最差)
1:commit时,redo log直接写入OS buffer并刷新到磁盘;(线上环境)
2:commit时,redo log写入OS buffer,每隔固定时间刷新到磁盘。(mysql进程宕机不影响)

在这里插入图片描述
快照读和当前读
快照读:读取的是快照版本,也就是历史版本(mvcc)
当前读:读取的是最新版本
普通的SELECT就是快照读,而UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE是当前读。
锁定读
SELECT … LOCK IN SHARE MODE 和 SELECT … FOR UPDATE。
一致性非锁定读
可重复读和读已提交两种事务隔离级别中普通select的方式是一致性非锁定读,它是读取数据库在查询发生时这个时间点的快照,如果事务中后续还存在一致性读操作读到的都是这个快照。

在可重复读隔离级别下,select用的是一致性读不加锁,锁定读及update、delete则需要加锁(加什么锁视情况而定) 如果你对唯一索引进行唯一查询那就是记录锁,若果使用了索引范围扫描就加临键锁或间隙锁。

一致性读保证了可用重复读(mvcc)
临键锁防止了幻读

1、利用MVCC实现一致性非锁定读,这就有保证在同一个事务中多次读取相同的数据返回的结果是一样的,解决了不可重复读的问题
2、利用Gap Locks和Next-Key可以阻止其它事务在锁定区间内插入数据,因此解决了幻读问题
综上所述,默认隔离级别的实现依赖于MVCC和锁,再具体一点是一致性读和锁。

多版本并发控制(MVCC)
读已提交和可重复读两种隔离级别使用了MVCC,MVCC可以被视为一种特殊的行锁,通过给煤航添加隐藏的两列来实现,一列是行创建时的系统版本号(创建时间),一列时行删除时的系统版本号(过期时间)。
系统每创建一个事务,会将当前的系统版本号作为事务的版本号,
SELECT查询数据时只查小于等于当前事务版本号的行。
INSERT 插入数据时,新增一行数据当前事务版本号作为创建版本号。
UPDATE 更新数据时,将旧数据所在行标记删除版本号为事务当前版本号,新增一行数据当前事务版本号作为创建版本号。
DELETE 删除数据时,将数据所在行标记删除版本号为事务当前版本号
索引和行锁表锁的关系。什么情况下使用行锁什么情况下使用表锁
Mysql 脏页是指当内存中的数据页与磁盘上的数据页不一致时,即为脏页。
WAL :Write ahead log 预写式日志,即为先写日志然后再写入磁盘来保证数据的安全性。

在这里插入图片描述
写入过程:

·MySQL服务器收到请求后,进行语法解析,检查查询语句的语法是否合法。然后进行查询优化,优化查询执行计划。
·将查询请求发送给适当的存储引擎进行处理,使用锁来管理并发访问。锁机制保证了数据的一致性和并发控制
·查询Buffer pool中如果没有需要操作的页则先从磁盘加载页到buffer pool中
·在数据写入修改之前,MySQL将先记录Undolog保证原子性。
·在Buffer pool中修改数据行成脏页。同步写内存中的redolog(事务提交后会将Buffer中的记录刷写到磁盘上的redo log文件中)
·后台线程在checkpoint时将Buffer pool脏页刷盘
·刷盘后redolog checkpoint之前的日志就可以按照一定的策略进行删除了

Check point总体上分为运行时刷新和关闭时刷新,关闭时刷新就是在数据库关闭时先将所有脏页刷盘后再关闭数据库。运行时刷新就是按照不同策略在适时的时间点进行刷新
运行时刷新分为以下四种:
当脏页太多时进行刷新
后台线程固定每间隔一段时间进行刷新
检查LRU中是否有足够的页供用户查询使用,若不够用则淘汰LRU末尾的页,如果有脏页则刷盘。
redolog文件写满时需要刷盘然后删除checkpoint前的redolog来腾空间

我们知道InnoDB采用Write Ahead Log策略来防止宕机数据丢失,即事务提交时,先写重做日志,再修改内存数据页,这样就产生了脏页。既然有重做日志保证数据持久性,查询时也可以直接从缓冲池页中取数据,但是,通常会有以下几个问题:
服务器内存有限,缓冲池不够用,无法缓存全部数据
重做日志无限增大成本要求太高
宕机时如果重做全部日志恢复时间过长
事实上,当数据库宕机时,数据库不需要重做所有的日志,只需要执行上次刷入点之后的日志。这个点就叫做Checkpoint,它解决了以上的问题:
缩短数据库恢复时间
缓冲池不够用时,将脏页刷新到磁盘
重做日志不可用时,刷新脏页
重做日志被设计成可循环使用,当日志文件写满时,重做日志中对应数据已经被刷新到磁盘的那部分不再需要的日志可以被覆盖重用。

Double write 用于保证innodb的可靠性。
当脏页刷盘的时候如果页只写入磁盘一半时数据库宕机了。那么会造成数据丢失,redolog解决不了这一问题,因为redolog是记录了修改添加等动作是针对于某一行的操作。使用redolog能实现的只是对磁盘上数据页中的数据重新进行一遍之前因意外导致的未执行操作。刷盘时down机会导致页数据丢失。
此时就需要使用dobouleweite来进行可靠性的保障了 ,doublewrite相当于是在刷盘时在磁盘上拓展出一块区域来先写入副本中再从副本中刷入磁盘的数据页中
doublewrite会先将脏页复制到doublewriteBuffer中 然后由buffer分两次每次一MB写入共享表空间的副本中最后刷到磁盘数据页。

插入缓冲是指对于非聚集索引进行插入时,为了提高插入效率并非每次写入磁盘,而是先检查该索引页是否在缓冲池中,若在则直接插入,若不在现将插入数据写入insert Buffer中,等待后台线程进行合并写入,因为非聚集索引一般是在磁盘上是非顺序,后台线程会将临近的操作进行顺序执行以提高执行效率

自适应哈希,如果对一个数据页的访问次数达到一定频率访问方式相同 则会对该页进行哈希 再次查询的时候就会走哈希找到页然后再从页中读取数据以达到效率提升。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《MySQL 技术内幕 InnoDB 存储引擎》是一本探讨 MySQLInnoDB 存储引擎技术书籍,该书主要讲解了 InnoDB 存储引擎的原理、架构和实现细节。 InnoDBMySQL 数据库的默认存储引擎,具有事务处理和行级锁定等特性,广泛应用于企业级数据库系统。因此,了解 InnoDB 存储引擎的内部工作原理和性能优化技巧对于 MySQL 数据库的使用和优化非常重要。 这本书首先介绍了数据库系统和存储引擎的基本概念,然后详细讲解了 InnoDB 存储引擎的体系结构和核心组件。读者可以了解到 InnoDB 存储引擎是如何将数据存储在磁盘上,以及如何通过索引加快查询速度。 在介绍完基础知识之后,书中继续深入讲解了 InnoDB 存储引擎的事务处理机制、并发控制和崩溃恢复等关键技术。读者可以学习到如何正确使用事务,并了解到 InnoDB 是如何通过行级锁定来实现并发访问的。 此外,书中还涵盖了 InnoDB 存储引擎的性能优化技巧和调试方法。读者可以学习到如何通过合理的配置和索引设计来提升查询性能,以及如何通过监控和分析工具来定位和解决性能问题。 总之,《MySQL 技术内幕 InnoDB 存储引擎》是一本深入剖析 InnoDB 存储引擎的权威技术书籍,对于想要深入理解和优化 MySQL 数据库的开发人员和数据库管理员来说是一本非常有价值的参考资料。 ### 回答2: 《MySQL技术内幕InnoDB存储引擎》是一本深入讲解MySQL InnoDB存储引擎技术书籍。InnoDBMySQL中的一种存储引擎,相比其他存储引擎,如MyISAM,它拥有更好的事务支持和并发控制能力,可以提供更高的数据一致性和可靠性。 这本书主要从架构、存储、索引、事务、锁定等方面对InnoDB存储引擎进行了详细的介绍和分析。首先,作者介绍了InnoDB的整体架构,包括缓冲池、日志系统、刷新机制等,帮助读者理解InnoDB的内部工作原理。 然后,书中详细解释了InnoDB的物理存储机制,包括页结构、数据页、索引页等。通过了解这些概念,读者可以更好地理解数据在磁盘上的存储方式,进而优化查询性能和空间利用。 接着,书中介绍了InnoDB的索引机制,包括B+树索引和自适应哈希索引。通过学习这些索引类型的原理和使用方法,读者可以更好地选择和创建适合自己业务需求的索引,提高查询效率。 此外,该书还详细说明了InnoDB的事务处理机制,包括事务的隔离级别、锁定机制、行锁和表锁等。通过学习这些内容,读者可以更好地理解和掌握InnoDB的并发控制技术,避免数据冲突和锁定问题。 总而言之,《MySQL技术内幕InnoDB存储引擎》通过深入讲解InnoDB的各个方面,帮助读者更好地理解和应用该存储引擎。无论是MySQL开发人员还是DBA,都可以从这本书中获得对InnoDB的深入了解,提高数据库性能和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值