技术内幕-innodb
-
1Memory 存储引擎默认使用哈希索引,而不是 B+ Tree索引,不支持 TEXT 和 BLOB 列类型。
-
2MySQL 数据库使用 Memory 存储引擎作为临时表来存放查询的中间结果集。如果中间结果集大于 Memory 存储引擎表的容量设置,又或者中间结果含有 TEXT 或者 BLOB 字段,则 MySQL 数据库会把其转换成 MyISAM 存储引擎表而存在磁盘中。MyISAM 不缓存数据文件,因此这时产生的临时表的性能对于查询会有损失。
-
3Innodb 内存数据对象包括 缓冲池(innodb_buffer_pool)、重做日志缓冲(redo_log_buffer)、额外内存池(innodb_additional_mem_pool_size)。
-
4缓冲池(innodb_buffer_pool)不仅仅包含索引页(index page)、数据页(data page) 还包括 插入缓冲(insert buffer)、锁信息(lock info)、自适应哈希索引、数据字典信息。
-
5在 InnoDB 存储引擎中,缓冲池中页的大小默认为 16 KB,使用 LRU 算法对缓冲池进行管理。
-
6对普通的 LRU 算法进行了改进,加入了 midpoint 位置。把 LRU 列表一分为二,前面 5/8 是 new 列表,后面 3/8 是 old 列表,从磁盘新读入的页放在距离尾部 3/8 的位置(参数innodb_old_blocks_pct 默认值为 37 表示新读取的页插入到LRU列表尾端的37% 的位置差不多 3/8 的位置),可以防止在某个全表扫描的查询把之前的热数据缓存全部剔除。关于何时将数据从 old 列表放到 new 列表中,书上说通过另一个参数 innodb_old_blocks_time,用于表示页读取到 mid 位置需要等待多久才会加入到 new 列表中。在网上看到一个更靠谱的说法,当页在缓存中被第二次引用,即放到 new 列表的头部。大概是不同版本的不同实现,参考链接 https://arpitbhayani.me/blogs/mysql-cache。
-
7数据库更新操作采用 Write Ahead Log 策略,先写 redo log(宕机时用于恢复数据),再更新缓冲池。一条 DML 语句更新了缓冲池中的页数据,导致和磁盘页数据不一致称为脏页。
-
8为避免每次更新都将脏页刷回磁盘带来的性能损耗,使用 Checkpoint(检查点) 技术将脏页刷回磁盘。对于 InnoDB 使用 LSN(Log Sequence Number) 来标记版本。每个页、重做日志、Checkpoint 中都有 LSN, Checkpoint 之前的页都已经刷回磁盘,异常恢复只需要从 Checkpoint 之后恢复。主线程定时触发、LRU 空闲页不够、重做日志不可用、脏页太多都会触发 Checkpoint。
-
9重做日志缓冲刷盘时机:
1)主线程每隔 1s 将重做日志缓冲刷新到重做日志文件,即使事务没有提交,这也是为什么再大的事务提交时间都很短的原因
2)每个事务提交时,由参数 innodb_flush_log_at_trx_commit 控制,为了保证事务的 ACID 中的持久性,必须设置为 1,表示在执行 commit 时将重做日志缓冲同步到磁盘,即伴有 fsync 的调用。
3)重做日志缓冲区空间不足 1/2
4)按 512字节(磁盘一个扇区的大小) 为单位进行写入。因为磁盘扇区是写入的最小单位,可以确保原子性,所以不需要double write -
10插入缓冲(Insert Buffer)
B+ 树实现,主要解决非唯一二级索引插入性能低(非顺序插入)的问题,不直接操作索引页,在 Insert Buffer 中暂存,再通过一定的触发机制合并操作。 -
11两次写(double write)
解决部分写失效(partial page write),比如一页 16k 数据刷盘时只成功了 4k,崩溃时无法通过 redo log 恢复的问题。在对缓冲池脏页刷新时,不直接写磁盘,通过 memcpy 函数复制到 doublewrite buffer 中,然后通过顺序写入共享表空间中,最后再去从 doublewrite buffer 中 fsync 刷到磁盘。如果出现部分写失效恢复数据的时候,会从共享表空间中还原该页再进行恢复。 -
12binlog 三种格式
Statement:sql 的逻辑语句,紧凑占空间小,IO效率高,一些内置函数比如取当前时间在主从之间表现不一致,需要保证 Repeatable Read 及以上隔离级别。参考链接http://mysql.taobao.org/monthly/2018/08/04/
Row:记录下每一行数据修改的细节,修改成什么值,需要更多的空间,确保主从之间数据一致,可以将隔离级别改成 Read Commited,获得更大的并发性。
Mixed:混合上面两种 -
13binlog 刷盘机制
默认是缓冲写,在宕机时可能造成数据丢失,可以通过修改 sync_binlog = 1,表示不使用操作系统的缓冲,直接使用同步写磁盘的方式记录 binlog。事务提交之前 binlog 已经记录了此时发生宕机,重启的时候事务会被回滚,如果 binlog 里记录了日志就会有问题,可以通过 innodb_support_xa 来解决,会用到 二阶段提交。 -
14 innodb是如何存储数据的
reference -
来源群友分享
-
加群请加wx: tutengdihuang