innodb buffer pool 过小引起查询更新缓慢症状分析
场景: 业务(读写分离)的流量增大,使得MySQL Server压力增大很多, 表现为iostat显示频繁的写操作, master(只写)中show processlist出现大量的update线程, slave出现大量的select 线程; 表设计和索引相对正常(尽管整体的设计显得不合理,不过对于sql语句及表而言,尽管存在冗余的索引等信息,不过对于业务而言显得可以胜任);
分析: 1. master(只写说明): master说明:
merged operations:
insert 5417064, delete mark 9998418, delete 3935427
Total memory allocated 5494538240; in additional pool allocated 0
Dictionary memory allocated 710216
Buffer pool size 327680
Free buffers 88
Database pages 324937
Old database pages 119928
Modified db pages 182550
LRU len: 324937, unzip_LRU len: 0
可以看到 Old database pages + Modified db pages =~ Database pages; 更新频繁会引起LRU链表的频繁更新,再加上buffer pool过小,尽管有insert buffer的缓冲,频繁的更新还是会引起频繁的flush disk操作, insert buffer 溢出一次,就会刷新一次,引起磁盘io增长; 同样的,buffer pool不够用 update操作会花较长时间处于updating状态(搜索匹配的记录),匹配后再转为updated状态; 这种情况引起出现大量的更新语句:
UPDATE `search` SET `record`='xxxxxxxxxx' WHERE n='nnnn' AND s='sssss';
profiling分析,时间集中在updating状态:
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000776 |
| checking permissions | 0.000424 |
| Opening tables | 0.000523 |
| System lock | 0.000388 |
| init | 0.000723 |
| Updating | 4.498569 |
| end | 0.000903 |
| query end | 0.000797 |
| closing tables | 0.000672 |
| freeing items | 0.000690 |
| logging slow query | 0.000720 |
| logging slow query | 0.000767 |
| cleaning up | 0.000662 |
+----------------------+----------+
加大buffer size 后, 存在更多的free buffer页, update操作更新变快(show processlist 显示很少的update线程(time时间大于1的)), io使用降低,主机负载降低;
2.slave说明: show processlist中出现大量的select语句:
SELECT record,n,s FROM `search` WHERE n = 'nnnnnnn' AND s = 'sssss';
大量的这种语句,profiling中的Sending data占用较多时间, 在buffer pool不够的时候,尽管记录很小,如果没有cache到内存里,还是会走磁盘扫描(也是手工操作会出现一条特别快,一条特别慢的状况的原因)解决同上加大buffer pool size;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000245 |
| Waiting for query cache lock | 0.000048 |
| checking query cache for query | 0.000069 |
| checking permissions | 0.000045 |
| Opening tables | 0.000105 |
| System lock | 0.000047 |
| Waiting for query cache lock | 0.000062 |
| init | 0.000052 |
| optimizing | 0.000048 |
| statistics | 0.000192 |
| preparing | 0.000051 |
| executing | 0.000042 |
| Sending data | 1.988487 |
| end | 0.000438 |
| query end | 0.000341 |
| closing tables | 0.000967 |
| freeing items | 0.000313 |
| logging slow query | 0.000082 |
| logging slow query | 0.000129 |
| cleaning up | 0.000091 |
+--------------------------------+----------+
从engine innodb status来看:
Pages made young 56281937, not young 0
764.74 youngs/s, 0.00 non-youngs/s
Pages read 47532991, created 94762, written 20074767
这种情况下LRU链表不停更新(made young),buffer缓存在这种情况下没多少意义,没有起到缓存的作用;可通过加大buffer pool size大小来缓解;
结论: 描述相对粗糙,没有列出详细的症状和出现问题搜集的信息,这里只是表明buffer pool size过小会引起查询和更新缓慢,加大buffer pool size会缓解这个症状, 加多少视应用和主机环境而定;