@@ -20,7 +20,7 @@ pin: true
2020
2121组成:段(默认256MB) -> 区(默认1MB) -> 页(默认16KB) -> 行
2222
23- 页:InnoDB的数据按** 页** 为单位读写,默认每个页大小为16KB,意味着一次最少从磁盘读取16KB的内容到内存中 ,一次最少把内存中的16KB内容刷新到磁盘中。表中的记录存储在** 数据页** 中。B+树的每个节点都是一个数据页。
23+ 页:InnoDB的数据按** 页** 为单位读写,默认每个页大小为16KB,意味着一次最少从磁盘读取16KB的内容到内存(Buffer Poll)中 ,一次最少把内存中的16KB内容刷新到磁盘中。表中的记录存储在** 数据页** 中。B+树的每个节点都是一个数据页。
2424
2525区:数据量大的时候,索引分配空间则是按** 区** 为单位分配,每个区的大小为1MB,对于16KB的页来说,连续(物理连续)64个页会被划分到一个区,这样,B+树中节点所构成的链表中相邻页的物理位置也相邻,便能顺序IO。
2626
@@ -269,9 +269,9 @@ Binlog 有三种格式:
2692692 . Statement,记录修改的 sql 语句。缺点是在mysql集群时的一些操作会导致数据不一致(例如 Now() 的时间不同)。
2702703 . Mixed
271271
272- Binlog 写入到磁盘的操作:
272+ 写入到磁盘的操作:
273273
274- 1 . write:从binglog cache写到 page cache。
274+ 1 . write:从 Buffer pool 写到 page cache。
2752752 . fsync:将数据持久化到磁盘。
276276
277277Binlog 的持久化:
@@ -282,13 +282,38 @@ Binlog 的持久化:
282282
283283#### Redolog
284284
285- 刷盘时机:事务进行中
285+ 刷盘时机:
286+ 1 . MySQL 正常关闭
287+ 2 . redo log buffer 的写入量大于 redo log buffer 内存空间的一半时
288+ 3 . 后台线程每隔一秒将 redo log buffer 持久化到磁盘
289+ 4 . innodb_flush_log_at_trx_commit 参数
290+ 1 . 当innodb_flush_log_at_trx_commit=0时,InnoDB会** 每秒钟** 将log buffer的数据** write** 到文件系统缓存中,并调用** fsync** 操作将数据缓存更新至磁盘中,与事务的执行与否无关。因此,在实例崩溃恢复场景中,可能会出现丢失1秒钟的事务。
291+ 2 . 当innodb_flush_log_at_trx_commit=1时,InnoDB将在** 每次事务提交** 时将log buffer的数据** write** 到文件系统缓存中,并调用** fsync** 操作将数据缓存更新至磁盘中。此种方式下,数据库完全遵守ACID特性,安全性较高。
292+ 3 . 当innodb_flush_log_at_trx_commit=2时,InnoDB将在** 每次事务提交** 时将log buffer中的数据** write** 到文件系统缓存中,** 每秒钟** 将文件系统缓存中的数据** fsync** 到磁盘中。不能完全保证每秒更新磁盘一次,没有被更新到磁盘中的事务可能会因宕机而丢失。
286293
287- 1 . 当innodb_flush_log_at_trx_commit=0时,InnoDB会每秒钟将log buffer中的数据更新到磁盘中。但并不能完全保证每秒将数据更新到磁盘一次。因此,在实例崩溃恢复场景中,可能会出现丢失1秒钟的事务。
288- 2 . 当innodb_flush_log_at_trx_commit=1时,InnoDB将在每次事务提交时将log buffer的数据更新到文件系统os buffer中,并调用文件系统的flush操作将数据缓存更新至磁盘中。此种方式下,数据库完全遵守ACID特性,安全性较高。
289- 3 . 当innodb_flush_log_at_trx_commit=2时,InnoDB将在每次事务提交时将log buffer中的数据更新到文件系统缓存中,每秒钟将文件系统缓存中的数据更新到磁盘一次,该操作由操作系统调度。不能完全保证每秒更新磁盘一次,没有被更新到磁盘中的事务可能会因宕机而丢失。
290294
295+ #### Buffer Pool
291296
297+ ![ ] ( https://raw.githubusercontent.com/CompetitiveLin/ImageHostingService/picgo/imgs/202409261455571.png )
298+
299+ 在 MySQL 启动时,向操作系统申请一片连续的空间,大小为 ` 128MB ` 。Buffer Pool中维护的数据结构是缓存页(16 KB 的数据页),而且每个缓存页都有它对应的描述信息。还有存在三个双向链表,分别是FreeList、LRUList以及FlushList。这三个双向链表中维护着缓存页的描述信息。
300+
301+ 读写数据流程:当读取数据时,先读 Buffer Pool 中的数据,再去磁盘中读;写数据时,修改 Buffer Pool 中的页,设置为脏页,最后由后台线程写入到磁盘;
302+
303+ ##### 双向链表
304+ 1 . FreeList,存放空闲的缓存页的描述信息
305+ 2 . LRUList,用于提高缓存命中率
306+ 3 . FlushList,存放脏页的描述信息
307+
308+ 为了解决预读失效(被提前加载进来的数据页并没有被访问)的问题,链表做了冷热数据分离优化,5/8的区域是热数据区域,3/8的区域算是冷数据区域
309+
310+ 为了解决 Buffer Pool 污染(扫描大量数据把热数据淘汰掉)的问题,进入热数据区域设置一个时间判断,如果数据被访问并且在冷数据区域的停留时间超过 1 秒,才会被放入热数据区域,否则仍然被放入冷数据区域。
311+
312+ #### 脏页刷新
313+ 1 . 当 redo log 日志满了的情况下,会主动触发脏页刷新到磁盘;
314+ 2 . Buffer Pool 空间不足时,需要将一部分数据页淘汰掉,如果淘汰的是脏页,需要先将脏页同步到磁盘;
315+ 3 . MySQL 认为空闲时,后台线程会定期将适量的脏页刷入到磁盘;
316+ 4 . MySQL 正常关闭之前,会把所有的脏页刷入到磁盘;
292317
293318### Crash-Safe 能力,两阶段提交
294319前提:innodb_flush_log_at_trx_commit 设置为1,sync_binlog 设置大于0
0 commit comments