有人可以解释一下 innodb 缓冲池的行为吗……?

can some one please explain innodb buffer pool behavior....?

我有我的innodb_buffer_pool_size =1G innodb_old_blocks_time = 5000 innodb_old_blocks_pct = 37

最初是 innodb 引擎的状态

BUFFER POOL AND MEMORY
Total memory allocated 1098907648; in additional pool allocated 0
Dictionary memory allocated 58256
Buffer pool size   65536
Free buffers       64932
Database pages     603
Old database pages 242
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 603, created 0, written 2
6.00 reads/s, 0.00 creates/s, 0.50 writes/s
Buffer pool hit rate 995 / 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: 603, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

之后

select count(*) from tenMillion;


BUFFER POOL AND MEMORY
Total memory allocated 1098907648; in additional pool allocated 0
Dictionary memory allocated 404498
Buffer pool size   65536
Free buffers       873
Database pages     64660
Old database pages 23888
Modified db pages  3
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 64660, created 0, written 20
1085.69 reads/s, 0.00 creates/s, 0.31 writes/s
Buffer pool hit rate 955 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 1081.34/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 64660, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

这是正确的行为吗..? 因为我希望它只占用 37% 的数据库页面,因为整个缓存应该在旧块中

当我的 innodb _old_blocks_time 为 5000 毫秒并且 table 大小超过 37(我的 innodb_old_blocks_pct) 百分比好奇地想知道是否只有 37% 会被填满,或者因为没有年轻人,也不需要驱逐,所以它是否会被填满超过我的 innodb 缓冲池的 37%?

请解释

在 "old_blocks" 和 "37%" 之前,会发生这种情况:

  1. 当你的 co-worker 在 table 的大 table 上做一个无辜的 COUNT(*) 时,你会愉快地徒步旅行,在你的 buffer_pool 中缓存 1GB 的东西几千兆字节。
  2. 噗!您所有的查询现在 运行 变慢了——因为他的查询从 buffer_pool 中清除了所有缓存块。 (他们会慢慢回来的。)

现在,

  1. 你正在愉快地徒步旅行......
  2. 出现了COUNT(*),但他的"table scan"被限制在缓冲池的37%。
  3. (如果有人碰巧触及了其中的一部分table,触及的块将从"old"提升,从而移动到其他63%。)
  4. 您的查询继续 运行 很好,因为您仍然拥有大部分已缓存的内容。
  5. 另一个 COUNT(*) 出现了——好吧,它会在 37% 的范围内乱七八糟,仍然不会(太多)干扰您的 "normal" 查询。

注意:Buffer pool hit rate 995 / 1000 -- 这从 99.5%(非常好)下降到 95.5%(仍然非常好)。

Old database pages 23888(共 65536 个)证实了我所说的被限制在 37%。

以下是 2009 年底发布的 5.1.41 和 5.5.0 的内容:

The InnoDB buffer pool is divided into two sublists: A new sublist containing blocks that are heavily used by queries, and an old sublist containing less-used blocks and from which candidates for eviction are taken. In the default operation of the buffer pool, a block when read in is loaded at the midpoint and then moved immediately to the head of the new sublist as soon as an access occurs. In the case of a table scan (such as performed for a mysqldump operation), each block read by the scan ends up moving to the head of the new sublist because multiple rows are accessed from each block. This occurs even for a one-time scan, where the blocks are not otherwise used by other queries. Blocks may also be loaded by the read-ahead background thread and then moved to the head of the new sublist by a single access. These effects can be disadvantageous because they push blocks that are in heavy use by other queries out of the new sublist to the old sublist where they become subject to eviction.

InnoDB now provides two system variables that enable LRU algorithm tuning:

innodb_old_blocks_pct

Specifies the approximate percentage of the buffer pool used for the old block sublist. The range of values is 5 to 95. The default

value is 37 (that is, 3/8 of the pool).

innodb_old_blocks_time

Specifies how long in milliseconds (ms) a block inserted into the old sublist must stay there after its first access before it can be

moved to the new sublist. The default value is 0: A block inserted into the old sublist moves immediately to the new sublist the first time it is accessed, no matter how soon after insertion the access occurs. If the value is greater than 0, blocks remain in the old sublist until an access occurs at least that many ms after the first access. For example, a value of 1000 causes blocks to stay in the old sublist for 1 second after the first access before they become eligible to move to the new sublist.

See The InnoDB Buffer Pool. (Bug #45015)