浅谈mysql innodb缓存策略

浅谈mysql innodb缓存策略:

 

 The InnoDB Buffer Pool

   Innodb 持有一个存储区域叫做buffer pool是为了在内存中缓存数据和索引,知道innodb bufferpool怎么工作,和利用它读取频繁访问的数据,是mysql优化重要的方面。

   理想状况下,把bufferpool的大小调整到足够大,留下足够的内存空间给其他该服务器上的进程(使其无缺页即可)。bufferpool越大,innodb 月表现为内存型数据库,从硬盘上一次读取数据,之后并成了从内存中读取数据。buffer pool甚至缓存那些因为insert,update操作而改变的数据(insert buffer),所以随机磁盘写可以聚集在一块得到更好的性能。

   innodb 把缓存池作为链式管理,利用LRU(least recently used)算法,当添加新block到pool中时(无空间),innodb 替换(驱逐)一个最近最少使用的block,然后把新的block添加到链表的中间,"midpoint insertion strategy"策略把链表看出两条子链。

     1:在链表的头部,是由一些“NEW”(or "young")block 组成的最近刚被访问的子链;

     2:在链表的尾部,是由一些'old' block组成的最近没被访问(或者最少被访问的)的子链;

 该算法使大量查询 blocks 保持在  new sublist. old sublist 持有最少使用的 blocks;这些blocks将成为替换或驱逐的候选者。

     1:3/8 的buffer pool 的大小分配给old sublist

     2: 链表的 midpoint (中间插入点) 是new sublist 尾部和 old sublist头部聚合的地方

     3:当 innodb 读取一个block进 buffer pool时,插入到midpoint(old sublist 的头部),block被读取发生在 客户端操作,eg: sql查询,或者innodb特性 readahead(预读);

     4:当访问在old sublist中一个 block时,使其变成'young',把它移动到 buffer pool的头部(new sublist的头部),如果该block 被读取是因为客户端sql查询,则第一次访问立即发生,并且该block变成'young'。如果该block被读取是因为read ahead,第一次呗访问不会发生,并且有可能在该Block被替换之前根本不能发生);

     5:随着数据库操作,在buffer pool 中的没被访问的blocks(年纪大的)被移动到链表的尾部.在old sublist中的blocks 比插入在midpoint上的block老,最终,一个Block一段长时间未被使用会到达old sublist的尾部会被替换。

     默认情况下,被读取的blocks会立即移动到 NEW sublist 的 head,同时意味着他们待着buffer pool中很长一段时间。当扫表时(eg, mysqldump 操作,或者 没有where语句的select操作 )可以使大量的blocks  push into buffer pool中,并且驱逐大量的older 数据,即使那些所谓刚加入的 new blocks 不会再次被访问,相同的,read ahead 后台线程一次载入大量的blocks  ,这些情况使经常被访问的blocks push into 到 old sublist中,然后它们成为被驱逐的候选者。

  一些innodb 系统变量控制着buffer pool的大小和使你调整LRU算法

    1:innodb buffer pool size

       指明Buffer pool的大小,如果你的buffer pool 空间小,并且有充足的空间,使pool大点可以减小磁盘IO的次数来提高性能;

    2: innodb buffer pool instances : 分成多个独立的区域,各个区域相同,来减少在并发内存读写操作的竞争;

    3:innodb old blocks pct:默认3/8;

    4:  innodb old blocks time: 指定多长时间以毫秒为单位(ms),block插入到老子列表必须呆在那里第一次访问后多久,才能搬到新的子列表(解决预读时,缓存污染问题);

  检查查询缓存是否存在于你的MySQL服务器:

mysql> show variables like 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
1 row in set (0.00 sec)

监控查询缓存的性能,使用显示状态查看缓存状态变量:

mysql> show status like 'qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 16768376 |
| Qcache_hits             | 0        |
| Qcache_inserts          | 0        |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 227      |
| Qcache_queries_in_cache | 0        |
| Qcache_total_blocks     | 1        |
+-------------------------+----------+
8 rows in set (0.00 sec)

  

mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        6 |   
+----------+  
1 row in set (0.00 sec)  
 
--Qcache_hits表示sql查询在缓存中命中的累计次数,是累加值。  
mysql> SHOW STATUS LIKE 'Qcache_hits';  
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 0     |  --0次  
+---------------+-------+  
8 rows in set (0.00 sec)  
 
mysql>  select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        6 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql>  SHOW STATUS LIKE 'Qcache%';  
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 1     | --表示sql在缓存中直接得到结果,不需要再去解析  
+---------------+-------+  
8 rows in set (0.00 sec)  
 
mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        6 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        6 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql> SHOW STATUS LIKE 'Qcache_hits';  
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 3     |    --上面的sql也是是从缓存中直接取到结果  
+---------------+-------+  
1 row in set (0.00 sec)  
 
mysql> insert into animals select 9,'testsds' ; --插入数据后,跟这个表所有相关的sql缓存就会被清空掉  
Query OK, 1 row affected (0.00 sec)  
Records: 1  Duplicates: 0  Warnings: 0  
 
mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        7 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql> SHOW STATUS LIKE 'Qcache_hits';  
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 3    |  --还是等于3,说明上一条sql是没有直接从缓存中直接得到的  
+---------------+-------+  
1 row in set (0.00 sec)  
 
mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        7 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql> SHOW STATUS LIKE 'Qcache_hits';   
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 4     |   
+---------------+-------+  
1 row in set (0.00 sec) 

  

原文地址:https://www.cnblogs.com/onlysun/p/4513029.html