MySQL-LRU_List Free_List Flush_List

本文介绍了InnoDB存储引擎中缓存池的管理机制,包括LRU算法的应用、Freelist的作用及Flushlist的工作原理。详细解释了如何通过调整参数防止热点数据被误刷,以及InnoDB如何处理压缩页。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于 LRU_List ,Free_List,Flush_List的介绍:
 
LRU算法:(Latest Recent Used)最近最少使用
     数据库的缓冲池通过LRU算法来进行管理。
     即,最频繁使用的页在LRU列表的前端,最少使用的页在LRU列表的尾端。当缓冲不能存放新读取到的页时,首先释放LRU列表尾端的页。
 
InnoDB存储引擎中,缓冲池中页默认大小16KB,也通过LRU列表对缓冲池进行管理,并对传统的LRU算法做了优化。在LRU列表中加入了midpoint位置。
     
 
midpoint位置设置:innodb_old_block_pct 默认:37 也就是3/8位置
midpoint之前的称为:new列表,之后的称为:old列表。
 
问题 1:为什么不将读取的页放入到LRU列表的首部?
      答:LRU列表,当不能存放新读取的页时,会释放尾部的页。若直接插入首部位置,某些SQL操作会使缓冲池中的页被刷新出去,尤其是读取大量的新页,直接插入首部,会使活跃的页逐渐被刷新出去。比如:索引或数据的全表扫描。这些页可能只在这次中用,但是活跃的页被刷新出去,下次读取该页,需要再次访问磁盘。
 
问题 2:解决类似全表扫描操作时,LRU列表中热点数据不被刷出
      答:设置参数:innodb_old_block_time:表示页读取到mid位置后需要等待多久才会被加入到LRU列表的热端。
          设置参数:innodb_old_block_pct :通过预估热点数据百分比。37-->20,降低mid位置,增加热点范围。
 
Free list:
 
LRU管理已经读取的页,数据库启动时,LRU列表是空的,没有页。此时的页都放在Free list。当需要从缓冲池中分页时,先查看Free list是否有空闲的页,若有,则从Free list中删除该页,放入到LRU列表。
若没有,则根据LRU算法,释放LRU列表尾端的页,将该内存分给新页。
 
page made young :当页从LRU列表的old部分加入到new部分时,此时的操作称为:page made young
page not made young:因为innodb_old_block_time设置,导致页没有从old部分移动到new部分的操作称为:page not made young。
 
如图:
mysql>SHOW ENGINE INNODB STATUS\G
 
---BUFFER POOL 3
Buffer pool size        204799     # *16KB
Buffer pool size, bytes 3355426816
Free buffers            1024
Database pages          193488
Old database pages      145096
Modified db pages       414
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 12977471, not young 326415366
 
Database pages :表示LRU列表中页的个数
 
Database pages + Free buffers <Buffer pool size
 
缓冲池中的页 可能分配给:自适应哈希索引,lock信息,insert buffer等页,这些页不需要LRU算法运行维护,因此不在LRU列表中。
 
缓冲池的运行状态:
1.
SELECT POOL_ID,HIT_RATE,PAGES_MADE_YOUNG,PAGES_NOT_MADE_YOUNG FROM `information_schema`.`INNODB_BUFFER_POOL_STATS`;
 
mysql>SHOW ENGINE INNODB STATUS\G
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 12977554, not young 326416098
0.00 youngs/s, 0.00 non-youngs/s
Pages read 3489114, created 521364, written 31146169
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 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: 193491, unzip_LRU len: 0
I/O sum[1]:cur[0], unzip sum[0]:cur[0]
 
2.通过INNODB_BUFFER_PAGE_LRU表查看LRU中每个页的状态
 
LRU中对于页的处理:
InnoDB存储引擎1.0.x版本开始支持压缩页的功能,即将16KB的页压缩成:1KB,2KB,4KB,8KB.
页的大小发生变化,LRU的管理页变。
非16KB的页,用unzip_LRU列表进行管理。
 
mysql>SHOW ENGINE INNODB STATUS\G
LRU len: 193491, unzip_LRU len: 0
I/O sum[1]:cur[0], unzip sum[0]:cur[0]
 
---LRU len:所有的页,包括压缩页。
---LRU len = unzip_LRU len + 非压缩页
 
表页的压缩比例不同,unzip_LRU是怎么从缓冲池中分配内存的?
     答:unzip_LRU也是有自己的分类的,根据1,2,4,8分类。
     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中。
 
Flush list
在LRU列表中的页被修改后,称该页为脏页(dirty page),即缓冲池中的页和磁盘上的页数据不一致。这时会通过checkpoint机制将脏页刷新回磁盘,而Flush list中的页即为脏页列表。
注:脏页既存在于LRU列表,也存在于Flush列表中。
LRU:用来管理缓冲池中页的可用性
Flush:用来管理将页刷新回磁盘。
 
mysql>SHOW ENGINE INNODB STATUS\G
 
---BUFFER POOL 3
Buffer pool size        204799     # *16KB
Buffer pool size, bytes 3355426816
Free buffers            1024
Database pages          193488
Old database pages      145096
Modified db pages       414      #显示脏页的数量
 
 --ok

转载于:https://www.cnblogs.com/cuisi/p/6586400.html

<think>好的,用户想知道如何使用redis-cli的debug object命令来检查big_list_key的内存使用情况和编码方式。首先,我需要确认debug object命令的具体用法。根据引用[1],用户可以使用debug object ${key}来获取键值的信息。所以具体命令应该是DEBUG OBJECT big_list_key。 接下来,用户需要了解输出中的各个字段含义。比如,serializedlength表示序列化后的长度,但要注意这可能和实际内存占用不完全一致。另外,编码方式encoding也是关键,比如列表可能使用ziplist或linkedlist编码,不同的编码会影响内存使用和性能。 然后,我需要考虑用户可能遇到的常见问题。比如,如果返回错误,可能是因为键不存在或者类型不对。这时候需要先用TYPE命令确认键的类型,如TYPE big_list_key,确保它是一个列表。 另外,用户提到的是大列表键,可能需要拆分。根据引用[3],拆分大的数据结构为多个小的是有效的优化方法。所以在回答中可以建议用户如果发现列表过大,考虑使用拆分策略。 还要注意引用[4]中提到删除bigkey的时间问题,虽然用户现在关注的是检查,但后续处理时删除可能会阻塞Redis,这也是需要注意的点。 最后,确保命令的正确性和步骤清晰,先运行DEBUG OBJECT,再解释输出结果,可能还需要结合其他命令如MEMORY USAGE来获取更准确的内存使用情况。同时提醒用户权限问题,需要连接到正确的Redis实例并有足够的权限执行命令。</think>### 使用 `redis-cli debug object` 检查大列表键 1. **执行 `DEBUG OBJECT` 命令** 通过以下命令检查 `big_list_key` 的详细信息(需确保已连接到 Redis 实例): ```bash redis-cli DEBUG OBJECT big_list_key ``` 2. **解析输出内容** 输出示例: ``` Value at:0x7f6e5c3b6700 refcount:1 encoding:linkedlist serializedlength:2048 lru:21565456 lru_seconds_idle:30 ``` - **`encoding`**:表示键的编码方式。列表可能为 `ziplist`(压缩列表)或 `linkedlist`(普通链表)。当元素数量或大小超过阈值时,Redis 会自动将 `ziplist` 转换为 `linkedlist`[^3]。 - **`serializedlength`**:序列化后的近似长度(单位:字节)。注意此值可能与实际内存占用不完全一致,但可用于相对大小判断[^1]。 - **`lru`** 和 **`lru_seconds_idle`**:记录键的最近访问时间和空闲时间。 3. **补充内存分析** 若需更精确的内存占用数据,可使用 `MEMORY USAGE` 命令: ```bash redis-cli MEMORY USAGE big_list_key ``` 此命令返回键的实际内存消耗(单位:字节)[^2]。 4. **操作注意事项** - 若键不存在或类型错误,命令会返回对应错误提示。可通过 `TYPE big_list_key` 预先验证键类型。 - 对于大列表键(如元素过多或单元素过大),建议按引用[3]拆分数据以优化性能。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值