MySQL 源码解读 -- Query Result Cache
Query Result Cache
层级结构
query_cache
query_cache 类是直接给mysql 内核使用, 外界使用接口namespace qc 里面提供的接口
qc::send_result_to_client
sql_cache
sql_cache 是一个plugin, 对外暴露的接口是Query_cache_service_t sql_cache_service, 将这个sql_cache_service 注册到query_cache 当中 (在函数sql_cache_init),在sql_cache 插件内部, 有个全局类global_query_cache 它是Query_cache
sql cache 基础类型
query cache service
1 | typedef uint64 (*resize_func)(uint64 size); |
注册Query_cache_service 到系统中去
**extern **Query_cache_service_t *Query_cache_service;
在query_cache plugin 初始化的时候, 将sql_cache_service 注册进去
**static **Query_cache_service_t sql_cache_service = {
resize, result_size_limit, store_query,
insert, send_result_to_client, end_of_result,
abort, invalidate_table, flush,
pack, reset_status};
query cache 实现类
1 | class Query_cache { |
锁系统
大锁, 平时操作, 都是读锁, 在flush时,进行写锁
some point
以前query cache是固定memory size。一启动就分配了。
现在的query cache用通过通用的malloc接口,背后实际jemalloc,是使用的时候才会分配。
内存用满了再申请的时候,就会主动释放链表(lru链表)上的old query.
同时原生的query cache, query block释放除了申请不到的情况,就是有dml语句的时候,invalidate释放。
我们现在query cache, 当有dml语句的时候,不会立即释放,除了内存不够的时候释放old query,还有就是匹配到对应query发现失效释放和prune线程回收释放。
prune线程目前是对性能不影响的,不会提升性能。 这个等后面做更多performance tunning后再去看。
prune线程是定位用来回收内存的。会主动释放无效query/table,还有比较老的query,不断释放内存。但这个对sysbench压测没有什么影响。因为sysbench压测,内存一直在高水位运行。
Query_cache_block_lists m_queries_lru;
Query_cache_block_lists m_tables;
LF_HASH queries, tables;
这个Lists是有16个List,然后每个query上,和每个table也有读写锁和原子状态(标记是否有人在做释放呢)。 (原来的query cache query上就单独有锁,但是没有被充分利用)
然后两个无锁hash。无锁hash实际也有自己的保护位。每次查找后需要调用lf_hash_search_unpin,另外的线程才可以释放对应对象。
恩,这个主要是由之前query cache串行运行,改为并发安全。
内部结构,去掉关联一个表所有query的链表,原来的这个链表涉及表和query。
剩余的链表结构变成了简单加减节点操作,这个锁时间很短,而且query和table的链表都是分拆成16个,锁冲突很少。
hash结构全部变成无锁hash。 利用query table上的锁还有原子状态变量保证并发并发安全。
恩,这个主要是由之前query cache串行运行,改为并发安全。
内部结构,去掉关联一个表所有query的链表,原来的这个链表涉及表和query。
剩余的链表结构变成了简单加减节点操作,这个锁时间很短,而且query和table的链表都是分拆成16个,锁冲突很少。
hash结构全部变成无锁hash。 利用query table上的锁还有原子状态变量保证并发并发安全。