MySql InnoDB存储引擎之Buffer Pool运行原理讲解

目录
  • 1. 前言
  • 2. Buffer Pool
    • 2.1 Buffer Pool结构
    • 2.2 Free链表
    • 2.3 缓冲页哈希表
    • 2.4 Flush链表
    • 2.5 LRU链表
    • 2.6 多个实例
    • 2.7 Buffer Pool状态信息
  • 3. 总结

1. 前言

我们已经知道,对于InnoDB存储引擎而言,页是磁盘和内存交互的基本单位。哪怕你要读取一条记录,InnoDB也会将整个索引页加载到内存。哪怕你只改了1个字节的数据,该索引页就是脏页了,整个索引页都要刷新到磁盘。InnoDB是基于磁盘的存储引擎,如果每次操作都去读写磁盘,那么性能将会受到很大的影响。而且绝大多数时候,程序读写的数据在磁盘上并不是连续的,这意味着需要执行大量的随机IO读写,磁盘随机IO读写效率是非常低的,尤其是传统的机械硬盘。

在解决这个问题之前,大家可以先想一想,为什么我们只想读取一条记录,而InnoDB会将整个页的数据都加载到内存?因为根据计算机的局部性原理,程序接下来大概率会访问与它相邻的记录,为了避免频繁发起磁盘IO读操作,InnoDB直接将整个页都加载到内存,下次再访问页中的其它记录时,就可以命中缓存了,减少磁盘IO操作。

问题解决的思路其实是一样的,磁盘的速度虽然很慢,但是内存的速度快啊。这些被加载到内存里的索引页,使用完毕后不要立即释放,而是将它们先缓存下来,下次再访问这些页时,就可以命中缓存了,减少磁盘IO,从而提升性能。理论上,只要内存无限大,那么MySQL几乎可以是基于内存的数据库了。

InnoDB缓存索引页的组件,就是我们今天要聊的「Buffer Pool」。

2. Buffer Pool

MySQL服务器启动时,InnoDB会向操作系统申请一块连续的内存空间用来缓存索引页,这一块连续的内存空间就是Buffer Pool。默认情况下Buffer Pool的大小是128MB,查看命令如下:

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+

理论上,Buffer Pool越大,缓存的索引页就可以更多,缓存的命中率就可以更高,对应的性能提升就越明显。如果你的机器内存够大,完全可以调大 Buffer Pool的大小,在配置文件里进行修改:

[server]
innodb_buffer_pool_size=2147483648
innodb_buffer_pool_instances=2

Buffer Pool最小是5MB,即使你配置的小于5MB,InnoDB也会分配5MB的内存。

innodb_buffer_pool_instances启动项代表Buffer Pool实例的个数。是的,你没看错,Buffer Pool支持配置多个,不同实例之间是隔离的,互不影响。配置多个的主要原因是因为Buffer Pool由多个链表组成,在维护这些链表时需要加锁保证同步,在高并发场景下会影响性能,配置多个实例就可以解决这个问题了。

每个Buffer Pool的大小是innodb_buffer_pool_size/innodb_buffer_pool_instances,InnoDB有规定,单个Buffer Pool实例的大小如果小于1GB,即使配置多个也不会生效。

2.1 Buffer Pool结构

Buffer Pool是用来缓存物理磁盘上的页结构的,那它自然也是由若干个页组成。为了与磁盘上的页区分开,这里我们叫它「缓冲页」。为了更好的管理这些缓冲页,InnoDB为每个缓冲页都创建了一个「控制块」对象与之关联。所以,Buffer Pool其实是由若干对控制块和缓冲页,以及一些碎片空间组成的。

为什么会有碎片空间?如果最后剩余的空间不足以分配一对控制块和缓冲页,就会被浪费掉,也就是碎片空间。除非你把Buffer Pool的大小设置的刚好合适。另外,控制块的大小在正常模式下和DEBUG模式下占用的大小并不一样,DEBUG模式下控制块的大小约为缓冲页的5%。

缓冲页的结构和物理磁盘上的页一致,也就没什么好说的了。控制块主要记录了缓冲页所属的表空间ID、页号、缓冲页在Buffer Pool中的地址、链表节点信息等等。我们重点关注链表节点,因为Buffer Pool出于不同的目的,将这些缓冲页串联成了多条链表,后面会提到。

总之,Buffer Pool的结构其实很简单,如下图所示:

2.2 Free链表

Buffer Pool是用来缓存磁盘上的页结构的,那么第一个问题就来了。当我们要从磁盘上加载一个页的时候,这个页该放到Buffer Pool的哪个缓冲页里呢?总不能遍历整个Buffer Pool吧,哪个缓冲页是空闲的就直接使用它,这未免也太笨拙了。

InnoDB会通过控制块里的链表节点属性,将所有空闲的缓冲页都串联成一条双向链表,叫作「Free链表」。MySQL服务器刚启动时,所有的缓冲页都会加入到该链表中,因为所有的缓冲页都没有被使用。当我们要把磁盘上的页加载到内存时,就从Free链表申请一个缓冲页,并把它对应的控制块从Free链表中移除,这比遍历整个Buffer Pool可高效多了。

怎么找到Free链表呢?为了更好的管理这些链表,InnoDB为每条链表都创建了一个叫作「链表基节点」的结构,它的属性就三个,分别记录链表的头尾节点指针、以及链表内的节点数量。

2.3 缓冲页哈希表

第二个问题又来了,当我们要使用某个页的时候,怎么知道它有没有被加载到Buffer Pool呢?难道又要再遍历一次所有已使用的缓冲页吗?未免也太笨拙了。

在同一个表空间里,每个页都有唯一的一个页号,所以要定位一个页,只需要知道表空间ID+页号就可以了。也就是说,我们完全可以建立一个哈希表,哈希表的Key就是表空间ID+页号的组合,Value就是缓冲页。这样就可以快速判断某个页是否已经加载到Buffer Pool了。

2.4 Flush链表

在执行增删改操作时,如果InnoDB每次都把受影响的页同步到磁盘,那么必然会导致大量的磁盘随机IO写操作,这个效率是很低的。为了提升性能,InnoDB会先在内存里修改这些受影响的页面,这些被修改过的页面称作「脏页」(Dirty Page),然后由一个额外的线程负责将这些脏页刷新到磁盘。

内存断电数据就丢失了,那些没来得及刷盘的脏页岂不是数据就丢失了?不用担心,后面聊的redo log会帮我们保证数据一致性的,这里先跳过。

第三个问题又来了,InnoDB怎么知道哪些页是脏页呢?再遍历一次Buffer Pool吗?太笨拙了,为了解决这个问题,InnoDB又引入了第二条链表:flush链表。

flush链表和free链表极其相似,也有一个链表基节点,当我们修改了缓冲页里的数据,InnoDB就会把该缓冲页对应的控制块加入到flush链表,等待后续的刷盘。

2.5 LRU链表

那些已经被使用的缓冲页,会从Free链表中移除,然后加入到一个叫作“LRU”的链表中。LRU是Least Recently Used的缩写,译为“最近最少使用”。为啥会需要LRU链表呢?说白了,相较于磁盘上海量的数据,Buffer Pool那点内存实在是杯水车薪,当Buffer Pool中的内存不够时,就不得不释放掉一些页面,来缓存新的页面。

Buffer Pool的本质是为了减少磁盘IO的访问,提高缓存命中率,正是因为它小才显得极其珍贵,InnoDB更应该要用好它。如果是你,你会在Buffer Pool里放访问频率高的页面,还是访问频率低的页面呢?

最简单的LRU链表,每当我们要访问一个页面时,就把它移动到LRU链表的表头,那么链尾的页面自然就是最近最少使用的了,当Free链表没有空闲的缓冲页时,直接把LRU链表的链尾页面释放掉即可。看似没什么问题,但是某些场景下,LRU链表会被破坏:

1.全表扫描:全表扫描需要加载聚簇索引B+树的所有叶子节点,当表中数据量较大时,可能一次全表扫描就会把之前访问频率很高的缓冲页全部从LRU链表中挤出,下次再访问这些页面时,又得从磁盘上重新加载一遍了。

2.预读:InnoDB内置了一个贴心的预读功能,它会在执行当前读请求时,判断是否还会访问其它页面,然后异步的把这些页面提前加载到Buffer Pool,从而加速读操作。预读细分为两种:

  • 2.1线性预读:系统变量innodb_read_ahead_threshold代表触发线性预读的阈值,如果顺序的访问某个区的页面数量超过该值,InnoDB就会异步的将下一个区的所有页面加载到Buffer Pool,默认值56
  • 2.2随机预读:系统变量innodb_random_read_ahead代表触发随机预读的阈值,如果某个区的13个连续的页面被加载到Buffer Pool,InnoDB就会异步的将本区其它页面全部加载到Buffer Pool,该功能默认关闭。

综上所述,全表扫描和预读可能会破坏LRU链表,本质上就是将大量可能短期不会被访问到的页面加入到LRU链表,反而导致那些访问频率很高的页面被挤掉了,导致Buffer Pool的命中率降低。

为了解决这个问题,InnoDB对LRU链表进行了优化,将LRU链表按照一定的比例分成两部分:存储访问频率很高的Young区、存储访问频率较低的Old区。系统变量innodb_old_blocks_pct控制了Old区所占的比例,默认值是37。也就是说,整个LRU链表的前约5/8部分用来存储访问频率很高的缓冲页,后约3/8部分用来存储访问频率较低的缓冲页。

将LRU链表划分为两截后,InnoDB是这样来维护LRU链表的:首次加载的页面不会直接放到LRU链表的表头,而是Old区的头部,如果该页面后续没有继续访问,会慢慢被释放掉,而不影响Young区的页面。如果后续再次访问了该页面,判断距离上次访问的时间,只有两次访问的时间间隔超过了阈值,才会把它移动到Young区头部。

时间间隔的阈值通过系统变量innodb_old_blocks_time配置,默认是1000ms

LRU链表经过这么一番优化后,我们看看是如何解决上面两个场景的:

  • 全表扫描:全表扫描的页面首次加载只会放在Old区头部,虽然马上又会访问同一个页面,但是时间间隔很短,因此不会移动到Young区。(每一条记录都要访问一次页面)
  • 预读:预读首次加载的页面只会放在Old区头部,只要后续不再继续访问,就会慢慢被释放掉。

对于Young区的缓冲页,如果每访问一次都要把它移动到LRU链表的表头,这个操作未免也太频繁了,因为Young区本来就是访问频率很高的页面,大家互相换来换去意义不大。所以InnoDB再进一步优化,如果访问的缓冲页在Young区的前1/4处,是不需要移动到表头的,只有访问的缓冲页在Young区的后3/4处才会把它移动到表头,这大大降低了链表节点移动的频率。

2.6 多个实例

现在我们知道,Buffer Pool在物理上虽然是一块连续的内存空间,但是逻辑上它由多条链表组成。在维护这些链表时,都需要加锁来保证同步,在高并发场景下,这会带来一些性能上的影响。为了解决这个问题,InnoDB支持多个Buffer Pool实例,每个实例都是独立的,会维护自己的各种链表,多线程并发访问时不会有影响,从而提高并发处理能力。

查看Buffer Pool实例个数的命令,默认是1个。

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| innodb_buffer_pool_instances | 1     |
+------------------------------+-------+

支持在配置文件中进行配置:

[server]
innodb_buffer_pool_size=2147483648
innodb_buffer_pool_instances=2

在MySQL5.7.5之前,InnoDB是不支持运行时动态调整Buffer Pool大小的,主要是因为每次调整大小,都需要向操作系统重新申请一个Buffer Pool,然后将数据拷贝一次,这个开销太大了。在之后的版本中,InnoDB引入了chunk的概念来支持运行时修改Buffer Pool大小。一个Buffer Pool实例由若干个chunk组成,里面包含了若干个控制块和缓冲页。在调整Buffer Pool大小时,InnoDB以chunk为单位来申请内存空间和数据的拷贝。

chunk的大小由系统变量innodb_buffer_pool_chunk_size控制,默认是128MB,chunk本身的大小不支持运行时修改。

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_chunk_size';
+-------------------------------+-----------+
| Variable_name                 | Value     |
+-------------------------------+-----------+
| innodb_buffer_pool_chunk_size | 134217728 |
+-------------------------------+-----------+

innodb_buffer_pool_size必须是innodb_buffer_pool_chunk_size*innodb_buffer_pool_instances的整数倍大小,目的是保证没个Buffer Pool实例的chunk数量一致。

2.7 Buffer Pool状态信息

说了这么多,耳听为虚,眼见为实。如何查看MySQL运行时的Buffer Pool相关的状态信息呢?命令是SHOW ENGINE INNODB STATUS,输出的是InnoDB引擎的状态信息,其中就包含Buffer Pool的状态信息,如下:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 268616
Buffer pool size   8191
Free buffers       7238
Database pages     953
Old database pages 371
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 919, created 34, written 36
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 740 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 959, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

  • Total large memory allocated:Buffer Pool向操作系统申请的总内存大小,包括控制块大小。
  • Dictionary memory allocated:给数据字典分配的内存大小,不包含在Buffer Pool总内存大小中。
  • Buffer pool size:Buffer Pool可以容纳多少缓冲页。
  • Free buffers:Free链表的页面数。
  • Database pages:LRU链表的页面数。
  • Old database pages:LRU链表Old区域的页面数。
  • Modified db pages:脏页数量,即Flush链表的页面数。
  • Pending reads:等待从磁盘加载到Buffer Pool的页面数。
  • Pending writes.LRU:等待从LRU链表中刷新到磁盘的页面数。
  • Pending writes.flush list:等待从Flush链表中刷新到磁盘的页面数。
  • Pending writes.single page:等待以单个页面的形式刷新到磁盘的页面数。
  • Pages made young:LRU链表曾经从Old区移动到Young区的节点数。
  • Pages made not young:再次访问Old区的节点因为时间问题不能移动到Young区的节点数。
  • youngs/s:每秒从Old移动到Young区的节点数。
  • non-youngs/s:每秒由于时间限制不能从Old移动到Young区的节点数。
  • Pages read/created/written:读取/创建/写入了多少页面,下一行是对应的速率。
  • Buffer pool hit rate:过去平均每访问一千次页面,有多少次页面已经被缓存到Buffer Pool。
  • young-making rate:过去平均每访问一千次页面,有多少次使页面移动到Young区头部。
  • not young-making rate:过去平均每访问一千次页面,有多少次没有使页面移动到Young区头部。
  • LRU len:LRU链表的节点数。
  • I/O sum:最近50秒,读取磁盘的总页数。
  • I/O cur:现在正在读取磁盘页的数量。
  • I/O unzip sum:最近50秒解压的页面数。
  • I/O unzip cur:正在解压的页面数。

3. 总结

磁盘速度太慢了,如果每次读取页面都从磁盘加载,会导致大量的磁盘IO随机读,MySQL的性能势必会受到严重影响。为了解决这个问题,InnoDB引入了Buffer Pool,它会在MySQL服务器启动时申请一块连续的内存空间,用来缓存对应的磁盘里的页结构。每个缓冲页都有一个与之关联的控制块,InnoDB为了不同的目的,将这些控制块串联成多条双向链表,例如:Free链表、LRU链表、Flush链表等等。为了提高Buffer Pool的命中率,防止一些特殊的操作破坏LRU链表,InnoDB将LRU链表按照一定的比例划分成两截,分别是存放访问频率很高的页的Young区,和访问频率较低的页的Old区。Buffer Pool逻辑上由这些链表组成,维护这些链表都需要加锁保证同步,高并发下会影响性能,所以InnoDB支持配置多个Buffer Pool实例。为了在运行时支持调整Buffer Pool的大小,InnoDB又引入了chunk的概念,最后通过命令我们可以查看Buffer Pool的状态信息。

到此这篇关于MySql InnoDB存储引擎之Buffer Pool运行原理讲解的文章就介绍到这了,更多相关MySql InnoDB Buffer Pool内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mysql InnoDB多版本并发控制MVCC详解

    目录 一丶为什么需要事务隔离级别 1.实现事务隔离的方式:串行执行 2.实现事务隔离的方式:可串行执行 二丶并发事务执行的问题:脏写,脏读,不可重复读,幻读 1.脏写 2.脏读 3.不可重复读 4.幻读 三丶隔离级别 1.Read UnCommitted 读未提交 2.Read Committed 读已提交 3.Repeatable Read 可重复读 4.Serializable 可串行化 四丶Mysql设置隔离级别 1.设置全局隔离级别 2.设置会话隔离级别 3.设置下一个事务的隔离级别 4

  • 深入理解MySQL中MVCC与BufferPool缓存机制

    目录 一.MVCC机制 undo日志版本链与read-view机制 版本链比对规则 二.BufferPool机制 三.总结 一.MVCC机制 MVCC(Multi Version Concurrency Control),MySQL(默认)RR隔离级别就是通过该机制来保证的,对一行数据的读与写两个操作默认是不会通过加锁互斥来保证隔离性的 串行化隔离级别是为了保证较高的隔离性,是通过将所有操作加锁互斥来实现的 MySQL在RC隔离级别和RR隔离级别下都实现了MVCC机制 RC每次查询都会创建一个r

  • MySQL InnoDB 存储引擎的底层逻辑架构

    目录 正文 内存架构 1. 自适应哈希索引 2. Buffer pool 3. Change buffer 4. Log Buffer 磁盘架构 1. 系统表空间 2. 独立表空间 3. 普通表空间 4. Undo 表空间 5. 临时表空间 总结 正文 我们都知道 MySQL 数据库有很多个存储引擎,其中另我们印象深刻的应该是 InnoDB 存储引擎,它从 MySQL 5.5 之后就是默认的存储引擎,它有支持事务.行级锁.MVCC 以及外键等优点. 那么你知道InnoDB存储引擎的底层逻辑架构吗

  • MySQL InnoDB引擎的缓存特性详解

    目录 1. 背景 2. 存储器性能差异 3. Buffer Pool 4. Free链表 5. Flush链表 6. LRU链表 7. 其它 1. 背景 对于各种用户数据.索引数据等各种数据都是需要持久化存储到磁盘,然后以“页”为单位进行读写. 相对于直接读写缓存,磁盘IO的成本相当高昂. 对于读取的页面数据,并不是使用完就释放掉,而是放到缓冲区,因为下一次操作有可能还需要读区该页面. 对于修改过的页面数据,也不是马上同步到磁盘,也是放到缓冲区,因为下一次有可能还会修改该页面的数据. 但是缓存的

  • MySQL InnoDB锁类型及锁原理实例解析

    目录 锁 共享锁 排他锁 意向锁 记录锁 间隙锁 临键锁 死锁 死锁产生条件 行锁发生死锁 表锁发生死锁 锁的释放 事务阻塞 死锁的避免 锁的日志 行锁的原理 不带任何索引的表 带主键索引的表 带唯一索引的表 结论 1.表必定有索引 2.唯一索引数据行加锁,主键索引同样被锁 锁 锁是用来解决事务对数据的并发访问的问题的.MyISAM支持表锁,InnoDB同时支持表锁和行锁. 表加锁语法: lock tables xxx read; lock tables xxx write; unlock ta

  • MySQL中读页缓冲区buffer pool详解

    目录 Buffer pool buffer pool组成 free链表 缓存页的哈希处理 flush链表的管理 LRU链表 刷新脏页 多个buffer pool实例 动态调整buffer pool大小 查看buffer pool具体的信息 Buffer pool 我们都知道我们读取页面是需要将其从磁盘中读到内存中,然后等待CPU对数据进行处理.我们直到从磁盘中读取数据到内存的过程是十分慢的,所以我们读取的页面需要将其缓存起来,所以MySQL有这个buffer pool对页面进行缓存. 首先MyS

  • MySQL存储引擎InnoDB与Myisam的区别分析

    目录 MyISAM介绍 InnoDB介绍 MySQL 存储引擎 MyISAM 与 InnoDB 如何选择? 总结 MySQL有多种存储引擎:MyISAM.InnoDB.MERGE.MEMORY(HEAP).BDB(BerkeleyDB).EXAMPLE.FEDERATED.ARCHIVE.CSV.BLACKHOLE.比较常用的是 MyISAM 和 InnoBD.在MySQL 5.1之前的版本中,默认的搜索引擎是MyISAM,从MySQL 5.5之后的版本中,默认的搜索引擎变更为InnoDB. 两

  • MySQL中Buffer Pool内存结构详情

    目录 1.回顾一下Buffer Pool是个什么东西? 1.1 增删改直接操作的是内存还是磁盘? 1.2 数据库崩溃了,内存中数据丢了怎么办? 1.3 Buffer Pool的一句话总结 2.Buffer Pool这个内存数据结构到底长个什么样子? 2.1 如何配置MySQL的Buffer Pool的大小? 2.2 数据页 2.3 磁盘上的数据页和Buffer Pool中的数据页是如何对应起来的? 2.4 缓存页描述信息 1.回顾一下Buffer Pool是个什么东西? 1.1 增删改直接操作的

  • MySql InnoDB存储引擎之Buffer Pool运行原理讲解

    目录 1. 前言 2. Buffer Pool 2.1 Buffer Pool结构 2.2 Free链表 2.3 缓冲页哈希表 2.4 Flush链表 2.5 LRU链表 2.6 多个实例 2.7 Buffer Pool状态信息 3. 总结 1. 前言 我们已经知道,对于InnoDB存储引擎而言,页是磁盘和内存交互的基本单位.哪怕你要读取一条记录,InnoDB也会将整个索引页加载到内存.哪怕你只改了1个字节的数据,该索引页就是脏页了,整个索引页都要刷新到磁盘.InnoDB是基于磁盘的存储引擎,如

  • 详解MySQL InnoDB存储引擎的内存管理

    存储引擎之内存管理 在InnoDB存储引擎中,数据库中的缓冲池是通过LRU(Latest Recent Used,最近最少使用)算法来进行管理的,即最频繁使用的页在LRU列表的最前段,而最少使用的页在LRU列表的尾端,当缓冲池不能存放新读取到的页时,首先释放LRU列表尾端的页. 上面的图中,我使用8个数据页来表示队列,具体作用,先卖个关子.在InnoDB存储引擎中,缓冲池中页的默认大小是16KB,LRU列表中有一个midpoint的位置,新读取到的数据页并不是直接放入到LRU列表的首部,而是放入

  • 简述MySQL InnoDB存储引擎

    前言: 存储引擎是数据库的核心,对于 MySQL 来说,存储引擎是以插件的形式运行的.虽然 MySQL 支持种类繁多的存储引擎,但最常用的当属 InnoDB 了,本篇文章将主要介绍 InnoDB 存储引擎相关知识. 1. InnoDB 简介 MySQL 5.5 版本以后,默认存储引擎就是 InnoDB 了.InnoDB 是一种兼顾了高可靠性和高性能的通用存储引擎.在 MySQL 5.7 中,除非你配置了其他默认存储引擎,否则执行 CREATE TABLE 不指定 ENGINE 的语句将创建一个

  • Mysql Innodb存储引擎之索引与算法

    目录 一.概述 二.数据结构与算法 1.二分查找 2.二叉查找树和平衡二叉树 1)二叉查找树 2)平衡二叉树 三.B+树 1.B+树完整定义 2.关于 M 和 L的选定案例 四.B+树索引 1.聚集索引 2.辅助索引 五.关于 Cardinality 值 1.Cardinality定义 2.Cardinality的更新 六.B+树索引的使用 1.联合索引 2.覆盖索引 3.优化器选择不使用索引的情况 4.索引提示 5.Multi-Range Read 优化 (MRR) 6.Index Condi

  • MySQL InnoDB存储引擎的深入探秘

    前言 在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库中.从MySQL5.5.8开始,InnoDB成为其默认的存储引擎.InnoDB存储引擎支持事务.其设计目标主要是面向OLTP的应用,主要特点有:支持事务.行锁设计支持高并发.外键支持.自动崩溃恢复.聚簇索引的方式组织表结构等. 体系架构 InnoDB存储引擎是由内存池.后台线程.磁盘存储三大部分组成. 线程 InnoDB 使用的是多线程模型, 其后台有多个不同的线程负责处理不同的任务 Master Thread Maste

  • MySQL 学习总结 之 初步了解 InnoDB 存储引擎的架构设计

    一.存储引擎 上节我们最后说到,SQL 的执行计划是执行器组件调用存储引擎的接口来完成的. 那我们可以理解为:MySQL 这个数据库管理系统是依靠存储引擎与存放数据的磁盘文件进行交互的. 那么 MySQL 有哪些存储引擎呢? 主要有 MyISAM.InnoDB.Memory等等.而现在互联网中,基本都是使用 InnoDB 存储引擎,所以接下来我将简单总结自己关于 InnoDB 存储引擎的学习,比较简单的介绍 InnoDB 存储引擎里面的组件. 二.缓冲池 我们现在都知道了,数据库的数据是存放在磁

  • MySQL中InnoDB存储引擎的锁的基本使用教程

    MyISAM和MEMORY采用表级锁(table-level locking) BDB采用页面锁(page-leve locking)或表级锁,默认为页面锁 InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁 各种锁特点 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生冲突的概率最高,并发度最低 行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也最高 页面锁:开销和加锁时间介于表锁和行锁之间:会出现死锁:锁定粒度介于表锁和行锁之

  • MySQL学习(七):Innodb存储引擎索引的实现原理详解

    概述 在数据库当中,索引就跟树的目录一样用来加快数据的查找速度,对于一个SQL查询操作,根据索引快速过滤掉不符合要求的数据并定位到符合要求的数据,从而不需要扫描整个表来获取所需的数据. 在innodb存储引擎中,主要是基于B+树来实现索引,在非叶子节点存放索引关键字,在叶子节点存放数据记录或者主键索引(或者说是聚簇索引)中的主键值,所有的数据记录都在同一层,叶子节点,即数据记录直接之间通过指针相连,构成一个双向链表,从而可以方便地遍历到所有的或者某一范围的数据记录. B树,B+树 B树和B+树都

  • 详解MySql中InnoDB存储引擎中的各种锁

    目录 什么是锁 InnoDB存储引擎中的锁 锁的算法 行锁的3种算法 幻像问题 锁的问题 脏读 不可重复读 丢失更新 死锁 什么是锁 现实生活中的锁是为了保护你的私有物品,在数据库中锁是为了解决资源争抢的问题,锁是数据库系统区别于文件系统的一个关键特性.锁机制用于管理对共享资源的并发访. 数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性 InnoDB存储引擎区别于MyISAM的两个重要特征就是:InnoDB存储引擎支持事务和行级别的锁,MyISAM只支持表级别的锁 In

随机推荐