December 2013

MySQL5.7新增Performance Schema表

在前面有几篇博客我们已经介绍过MySQL5.6的Performance Schema,详细可点击博客1,博客2,博客3。在MySQL5.6里这些PS表已经包含了足够丰富的信息,帮助我们来分析MySQL的内部运行状态;另外由MySQL官方开发人员写的ps_helper是一组相当好用的ps配套工具,就算对Performance Schema不熟悉的同学,也能读懂其中的信息,感兴趣的同学可以自行谷歌下载。 当然本文的重点不在Performance Schema的使用上,主要是记录下MySQL5.7里新增的一些PS表,也是做个备忘,便于以后翻阅  . . 1.内存监控(MySQL5.7.2) MySQL5.7.2开始支持内存监控的Performance Schema,包括分配内存所属的模块,操作的次数等等;通过这些信息我们可以看到内存究竟消耗在哪些地方; 与其他的类似,都可以通过配置表来动态打开/关闭 root@performance_schema 07:33:59>select count(*) from setup_instruments where name like ‘%memory%’; +———-+ | count(*) | +———-+ |      211 | +———-+ 1 row in set (0.00 sec) 总共增加了211个监控事件项,分为SQL/performance_schema/client/vio/mysys/sql/myisam/csv/memory/myisammrg/archive/blackhole/这几个模块,主要模块是SQL模块,用于监控Server层(共143个) 数据汇总结果表包含: root@performance_schema 07:46:39>show tables like ‘%memory%’; +—————————————–+ | Tables_in_performance_schema (%memory%) | +—————————————–+ | memory_summary_by_account_by_event_name | | memory_summary_by_host_by_event_name    | | […]

Innodb read only事务、MySQL5.7和Percona的事务改进

前言 只读事务在MySQL5.6中引入,改进了创建视图快照的开销,减少了持有trx_sys->mutex的时间,这有利于提升只读性能;这一点已经广为人知;   本文的内容基本按照读代码的顺序来的,先了解了下Oracle MySQL5.6.15的只读事务部分代码,再看了Percona5.6对于事务部分的相关改进;随后大概过了下Oracle MySQL5.7对事务部分的优化;   总的来说,Percona移植了其在5.5上所做的优化,而Oracle MySQL5.7优化的更彻底,很多代码都重构了。   本文不涉及到性能测试,只是代码阅读过程的笔记,记录的目的是方便以后查阅方便,因此同时也附带上了一些新版本修改的Rev号。   1.如何使用只读事务   a.设置变量tx_read_only,当全局设置为true时,涉及到的SQL只能是只读的。这个参数可以是session 级别,也可以是全局级别; 开启该参数后,就默认所有查询走只读的逻辑;   b.开启事务时指明: START TRANSACTION READ ONLY;   c.autocommit状态下的查询操作也会被当做只读事务   如果事务中混合了DML操作,就会报如下错误: root@test 09:57:58>delete from t1; ERROR 1792 (25006): Cannot execute statement in a READ ONLY transaction.  2.只读事务涉及的代码逻辑(MySQL5.6)   Innodb将所有的事务对象维护在链表上,通过trx_sys来管理,在5.6中,最明显的变化就是事务链表被拆分成了两个链表: 一个是只读事务链表:ro_trx_list,其他非标记为只读的事务对象放在链表rw_trx_list上;   这种分离,使得读写事务链表足够小,创建readview 的MVCC快照的速度更快;   a.开始一个事务 入口函数trx_start_low  1)判断事务是否是只读的;     […]

[MySQL5.6] Percona Server 5.6.14的线程池浅析

  Percona的线程池 基本上是从Mariadb中引入,其实现思路也比较简单,就是在线程调度器那增加了一组新的回调函数。线程池可以有效改善在大并发下的性能; Thread pool的原理在Percona的这篇博客描述的很生动;其实就是限制同时运行的线程数,让大家不要一起挤进来,有序运行负载。线程池的目的不是为了提高性能,而是为了保持性能的稳定。 在使用线程池的场景下,就不是通常的一个连接一个线程(one-thread-per-connection),你可以创建几千甚至上万个Socket连接,MySQL只会创建有限个线程来 以下从不同的点来介绍下相关的代码,这里没有太多的深入,也没有性能测试数据,只是阅读时带着疑问做的一些笔记;   Q:如何控制同时运行的并发线程数   参数thread_pool_size的命令可能会让大家产生误解,它不是指的线程池的大小,而是线程组的大小。类似所有创建的线程都在某一个group里,group的编号从1~thread_pool_size,每个group里的线程数可以通过参数thread_pool_oversubscribe来控制(默认为3),如果把thread_pool_oversubscribe设置为1,那么thread_pool_size就被严格限制为能够同时活跃的最大线程数。 thread_pool_size默认值为CPU核心数,最大为128(MAX_THREAD_GROUPS),在启动时,就会把128个Group对应的结构体(all_groups)初始化好。每个group(编号小于等于thread_pool_size)会创建一个epoll对象;   Q:如何处理新连接   当客户端发起一个连接请求时,会被main线程捕捉到(handle_connections_sockets),然后调用tp_add_connection将新的连接加入到某个线程池的group中(根据thread_id%thread_pool_size),每个连接创建一个connection_t结构体对象(这个connection结构体里包含了连接的相关信息,例如是否登录,thd,是否正在等待,tickets等等), 创建好的connection被加入到其所属group的队列中(thread_group->queue),如果当前该group没有active的线程(thread_group->active_thread_count == 0)尝试去唤醒一个工作线程或者新建一个线程(wake_or_create_thread):a.首先尝试唤醒当前空闲的线程(空闲的线程对象在thread_group->waiting_threads中),如果有的话,则将其从waiting_threads中移除,并发送信号 ; b.否则表示现在该group内还没有线程, 需要创建一个新的worker线程(create_worker); 在创建worker线程时,一个比较有趣的代码段: if (tp_stats.num_worker_threads >= (int)threadpool_max_threads && thread_group->thread_count >= 2) { err= 1; max_threads_reached= true; goto end; } 实际上thread_pool_max_threads不是完全严格的限制总共的线程数,只有当当前线程数大于该max值,且当前group已有2个及以上worker线程时才拒绝新建线程 从上一步可以保证有一个活跃线程被唤醒来处理新连接的登录请求,worker线程的回调函数为worker_main,也就是处理socket请求的真正函数逻辑。   Q:如何处理新请求     worker线程调用worker_main,在一个循环内干两件事儿: #get_event 顾名思义,该函数的目的就是为了获取一个事件,大约有如下的流程: a.如果当前活跃线程数大于thread_pool_oversubscribe,并且该group的stall状态为false(何时设置?),暗示这时候该group的活跃线程数太多了(oversubscribed)。 b.如果oversubscribed为false,则取从队列中取connection_t对象(queue_get),先从高优先级队列(thread_group->high_prio_queue)取,如果没有的话,再从普通队列(thread_group->queue)取。如果存在的话,取得该对象返回 c.如果当前group里没有正在监听的线程(这时候没有任何请求),则把当前worker线程设置为监听线程,进入epoll监听socket请求 对于监听到的新请求,如果当前group里的没有event,,则由监听线程自己来处理监听到的第一个任务,剩下的任务放到队列中,否则把任务加入到队列中,由其他worker线程来处理。 加入队列的规则: 1.当该连接的ticket没用完(初始值为thread_pool_high_prio_tickets, Percona引入) […]