1. Gdevops 全球敏捷运维峰会 MySQL大并发量性能优化实战 演讲人:张青林 Gdevops.com 全球敏捷运维峰会 上海站

2. mysql_parse mysql_execute_command 简 单 查 execute_sqlcom_select 询 语 open_normal_and_derived_tables 句 的 open_table_get_mdl_lock 执 行 handle_select 过 程 thr_lock engine operation close_open_tables Gdevops.com 全球敏捷运维峰会 上海站 PS 的 影 响 范 围

3. Agenda  metadata_locks_hash_instances 的作用 & 原理 & 实现  table_open_cache_instances 的作用 & 原理 & 实现  performance_schmea 的作用 & 原理 & 实现  INNODB MVCC 的实现 Gdevops.com 全球敏捷运维峰会 上海站

4. MySQL metadata_locks_hash_instances  什么是 MDL Lock ,其主要作用是什么? MDL Lock (Metadata Lock),即 Server 层的数据字典锁,是为了保护 DB, table, trigger, procedure 等数据对象而设计的,先看一下一个 bug#989: Gdevops.com 全球敏捷运维峰会 上海站

5. MDL Lock 的实现原理 mysql_execute_command THD -> MDL_context -> MDL_tickets -> MDL_lock ... acquire_lock(...mdl_requests...) try_acquire_lock_impl find_or_insert MDL_map_partition::find_or_insert MDL_map MDL_lock::create .... m_partitions.at(part_id) m_partitions.at(part_id) m_partitions.at(part_id) .... mdl_locks m_mutex ... MDL_key {mdl_namespace, dbname, object_name} 问题:MDL Lock 中存在的瓶颈,MDL Lock 瓶颈的缓解方法, MDL Lock 中在各个版本中的实现方法 Gdevops.com 全球敏捷运维峰会 上海站

6. MySQL table_open_cache_instances  什么是 table_cache,为什么需要 table_cache ? table_cache是缓存 table 对象的容器,table 是MySQL中用户线程操作表对象的内存对象,table 中包括了用 户的相关操作记录,对应的 engine 的文件句柄以及内部对象管理的控制信息等;  MySQL 打开表 & 关闭表的过程  MySQL 打开表的流程中存在的性能瓶颈 当 MySQL 的并发链接数较高的时候,会有多个用户线程被分配到同一个 table_cache 中,造成多个线程竟争 table_cache->m_lock 的问题,引起 thread_running 飙升;  解决 table_cache 问题的方法 对参数 table_open_cache_instances 进行调整,1 -> 64  table_open_cache_instances & table_definition_cache 关系 每一个 table 内存对像中会有一个指象表对像的指针,即 table_share, table_share 也有一个缓存大小的设置, 即 table_definition_cache, 同时, table_definition_cache 也是 innodb 层缓存数据字典的设置,如果没有对 table_definition_cache 进行设置,则会根据 table_open_cache的值进行计算;  table cache 相关问题的状态信息 show status like '%table_cache%'; flush tables; Gdevops.com 全球敏捷运维峰会 上海站

7. table 对象的生命周期 open_and_process_table open_table ... tc= table_cache_manager.get_cache(thd) tc->lock() table= tc->get_table() tc->unlock ... close_thread_table release_table link_unused_table ... el->used_tables.remove(table); el->free_tables.push_front(table); link_unused_table(table); free_unused_tables_if_necessary ...  cache_manager & cache_instance 控制的是 thd 使用表的分区信息;  Table_cache_element table_cache 共同管理 table 缓存对象; Gdevops.com 全球敏捷运维峰会 上海站

8. MySQL performance_schema 什么是 performance_schema,和 information_schmea 有什么区别? performance schema 是 MySQL 的内部诊断器,用于记录 MySQL 在运行期间的各种信息,如表锁情况、 mutex 竟争情况、执行语句的情况等,和 Information Schema 类似的是拥用的信息都是内存信息,而不是 存在磁盘上的。和 information_schema 有以下不同点:  information_schema 中的信息都是从 MySQL 的内存对象中读出来的,只有在需要的时候才会读取这 些信息,如 processlist, profile, innodb_trx 等,不需要额外的存储或者函数调用,而 performance schema 则是通过一系列的回调函数来将这些信息额外的存储起来,使用的时候进行显示,因此 performance schema 消耗更多的 CPU & memory 资源;  Information_schema 中的表是没有表定义文件的,表结构是在内存中写死的,而 performation_schema 中的表是有表定义文件的;  实现方式不同,Information_schema 只是对内存的 traverse copy, 而 performance_schema 则使用固 定的接口来进行实现;  作用不同,Information_schema 主要是轻量级的使用,即使在使用的时候也很少会有性能影响, performance_schema 则是 MySQL 的内部监控系统,可以很好的定位性能问题,但也很影响性能; Gdevops.com 全球敏捷运维峰会 上海站

9. Performance schema 的作用  对各种资源监控开关进行设置  监控mutex, rw_lock, conds等资源的使用情况  监控内存使用的情况 (5.7)  监控SQL语句的使用情况并对相关的语句进行统计  监控内部运行的线程  监控文件资源的使用情况并对相关的资源进行统计 Gdevops.com 全球敏捷运维峰会 上海站

10. Performance schema 实现过程及问题  创建对应的监控表  实现 performance_schema 引擎的相关接口;  在相应的地方设置回调函数,在相应的操作中添加或减少对应的监控信息;  查询的时候调用相应的接口访问已经额外存储的数据;  由于需要存储一份额外的数据在内存中,所以会有额外的内存消耗;  Perfornamce schema 会加重计算代价,对性能也有一定的影响; Gdevops.com 全球敏捷运维峰会 上海站

11. MySQL MVCC 的实现  MySQL Innodb record 物理结构  MySQL Innodb MVCC 实现原理  MySQL Innodb MVCC 实现过程中存在的问题  MySQL Innodb MVCC 对于问题的解决过程  TDB5.6 Innodb MVCC 解决问题的方案设计 Gdevops.com 全球敏捷运维峰会 上海站

12. MySQL Innodb record 物理结构 Record 格式: 记录头 主键 TRX_ID ROLL_PTR extra_column 变长记录长度数组 NULLABLE_COLUMNS extra info REC_NEW_INFO_BITS REC_NEW_N_OWNED REC_NEW_HEAP_NO REC_NEW_STATUS REC_NEXT Gdevops.com 全球敏捷运维峰会 上海站

13. MySQL Innodb MVCC 实现原理 MVCC 部分调用栈: row_search_for_mysql row_vers_build_for_consistent_read ROLL_PTR  read view 的创建在 RC & RR 隔离级别下的区别 ?  purge 线程 read_view 的创建需要注意的问题 ?  活跃事务的更改对 read_view 创建的影响 ? trx_undo_prev_version_build low_limit_no, used for purge read_view_sees_trx_id low_limit_id, trx whose trx_id >= low_limit_id is unvisible high_limit_id, trx whose trx_id < high_limit_id is visible Gdevops.com 全球敏捷运维峰会 上海站

14. MySQL Innodb MVCC 存在的问题 参考视图创建函数 read_view_open_now_low,可以看到:  整个创建过程一直持有 trx_sys->mutex 锁;  需要遍历 trx_sys->trx_list (5.5) 或 trx_sys->rw_list (5.6);  read_view 的内存在每次创建中被分配,事务提交后被释放;  并发较大,活跃事务链表过长时,会在 trx_sys->mutex 上有较大的消耗; 详情见:https://bugs.mysql.com/bug.php?id=49169 Gdevops.com 全球敏捷运维峰会 上海站

15. MySQL Innodb MVCC 对于问题的解决过程 解决过程比较区折,但主要是从几个方面来进行优化,从5.6 ->5.7 的 release note & work log 也可以清晰的 看到,简单介绍如下:  减少 read_view 创建时的事务链表的长度(语法上支持或设置 session 变量)  减少 read_view 创建时的不必要的内存分配  减少遍历 rw_trx_list 链表的次数  减少 read_view 的分配 & 释放 Gdevops.com 全球敏捷运维峰会 上海站

17. CDB 5.6 Innodb MVCC 解决问题的方案设计 结合 percona & MySQL 5.7 两种方案进行实现,主要思想如下:  backport percona 5.6 中对 bug#49169 的修复;  实现 MySQL 5.7 中移除只读链表的想法;  其它在编码 & 测试过程中待改近的地方 经过以上的优化,对于只读性能应该可以有比较大的提升,目前进度在移除只读链表中 Gdevops.com 全球敏捷运维峰会 上海站

18. Gdevops 全球敏捷运维峰会 THANK YOU! Gdevops.com 全球敏捷运维峰会 上海站