MySQL源代码:由参数query_response_time_stats想到的
来源:互联网 发布:新闻小偷源码 编辑:程序博客网 时间:2024/06/06 01:31
转载请署名:印风
---------------------------------------------
Percona提供了一个参数query_response_time_stats用于在服务器端观察数据库的响应时间
root@test 02:29:35>show variables like'query_response_time_stats';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| query_response_time_stats | OFF |
+---------------------------+-------+
1 row in set (0.00 sec)
将这个全局变量设置为‘ON’即可观察响应时间
root@test 02:29:47>set globalquery_response_time_stats = 'ON';
Query OK, 0 rows affected (0.00 sec)
响应时间信息被记录在一个内建的I_S 插件中:QUERY_RESPONSE_TIME,其结构如下,包含3个字段:
root@information_schema 02:56:37>desc QUERY_RESPONSE_TIME;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| time | varchar(14) | NO | | | |
| count | int(11) unsigned | NO | | 0 | |
| total | varchar(14) | NO | | | |
+-------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
root@information_schema 04:28:01>select * from QUERY_RESPONSE_TIME;
+----------------+-------+----------------+
| time |count | total |
+----------------+-------+----------------+
| 0.000001| 0 | 0.000000 |
| 0.000010| 0 | 0.000000 |
| 0.000100| 16 | 0.000697 |
| 0.001000| 11 | 0.002144 |
| 0.010000| 0 | 0.000000 |
| 0.100000| 0 | 0.000000 |
| 1.000000| 0 | 0.000000 |
| 10.000000| 0 | 0.000000 |
| 100.000000| 0 | 0.000000 |
| 1000.000000| 0 | 0.000000 |
| 10000.000000| 0 | 0.000000 |
| 100000.000000| 0 | 0.000000 |
| 1000000.000000 | 0 | 0.000000 |
| TOO LONG | 0 | TOO LONG |
+----------------+-------+----------------+
其中time代表RT区间(可以通过参数query_response_time_range_base)来设置,count表示该区间里收集的SQL数,total表示这些SQL的执行总时间
在代码sql/query_response_time.cc里实现了该i_s表。在系统启动时(init_server_components函数)进行初始化(空函数),在sql_show.cc里声明内建i_s表
字段定义:
ST_FIELD_INFO query_response_time_fields_info[]
在i_s表描述数组(ST_SCHEMA_TABLEschema_tables[])中的定义如下:
#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
{"QUERY_RESPONSE_TIME",query_response_time_fields_info, create_schema_table,
query_response_time_fill, make_old_format,0, -1, -1, 0, 0},
#else
{"QUERY_RESPONSE_TIME",query_response_time_fields_info, create_schema_table,
0, make_old_format, 0, -1, -1, 0, 0},
#endif //HAVE_RESPONSE_TIME_DISTRIBUTION
这里有一个有趣的现象,即使用宏HAVE_RESPONSE_TIME_DISTRIBUTION来定义。这取决于具体的Percona Server版本
那么RT到底是如何计算的呢,这里有两个关键函数:
query_response_time_fill
query_response_time_collect
后者用于收集统计信息,我们注意到在函数log_slow_statement函数中调用到了该函数,但注意,如果定义了log_slow_filter选项,可能会导致不收集信息
RT收集函数实际调用为:
query_response_time::g_collector.collect(query_time);
其中query_time代表当前sql的执行时间
计算的方式也很简单,对于query_time属于的那个时间区间,执行:
if(m_utility->bound(i) > time) { my_atomic_rwlock_wrlock(&time_collector_lock); my_atomic_add32((int32*)(&m_count[i]), 1); my_atomic_add64((int64*)(&m_total[i]), time); my_atomic_rwlock_wrunlock(&time_collector_lock); break; }
可以看到其实现还是相当简单的。
query_response_time_fill函数是在每次去select或show QUERY_RESPONSE_TIME的时候被调用,用于向I_S表中填充数据,具体可以参考如何编写I_S插件
话说最后一行显示的字符串看起来有点不爽,这里我们可以做一个简单的修改,使得表中的最后一行显示之前的总和值
当然啦,我们也可以以自己想要的其他方式来对数据进行呈现,开放的源代码赋予了无限的可能。这里的修改只是娱乐一番:)
效果:
root@information_schema 07:50:46>select * fromQUERY_RESPONSE_TIME where time = 'sum';
+------+-------+----------------+
| time | count | total |
+------+-------+----------------+
| sum | 9 | 0.006465 |
+------+-------+----------------+
1 row in set (0.00 sec)
Patch如下:
---Percona-Server-5.5.18.stock/sql/query_response_time.cc 2012-01-07 16:38:37.000000000 +0800+++Percona-Server-5.5.18.rt/sql/query_response_time.cc 2012-01-07 19:28:07.000000000 +0800@@-222,7 +222,9 @@ DBUG_ENTER("fill_schema_query_response_time"); TABLE *table=static_cast<TABLE*>(tables->table); Field **fields= table->field;- for(uint i= 0, count= bound_count() + 1 /*with overflow */; count > i; ++i)+ uint64 sum_total=0;+ uint32 sum_count=0;+ for(uint i= 0, count= bound_count() + 1 /*with overflow */; count > i; ++i) { char time[TIME_STRING_BUFFER_LENGTH]; char total[TOTAL_STRING_BUFFER_LENGTH];@@-230,17 +232,24 @@ { assert(sizeof(TIME_OVERFLOW) <=TIME_STRING_BUFFER_LENGTH); assert(sizeof(TIME_OVERFLOW) <=TOTAL_STRING_BUFFER_LENGTH);- memcpy(time,TIME_OVERFLOW,sizeof(TIME_OVERFLOW));- memcpy(total,TIME_OVERFLOW,sizeof(TIME_OVERFLOW));+ print_time(total, sizeof(total),TOTAL_STRING_FORMAT, sum_total);+ bzero(time, sizeof(time));+ memcpy(time,"sum", 4);+ fields[0]->store(time,strlen(time),system_charset_info);+ fields[1]->store(sum_count);+ fields[2]->store(total,strlen(total),system_charset_info); } else { print_time(time, sizeof(time),TIME_STRING_FORMAT, this->bound(i)); print_time(total, sizeof(total),TOTAL_STRING_FORMAT, this->total(i));- }- fields[0]->store(time,strlen(time),system_charset_info);- fields[1]->store(this->count(i));- fields[2]->store(total,strlen(total),system_charset_info);+ my_atomic_add32((int32*)(&sum_count),this->count(i));+ my_atomic_add64((int64*)(&sum_total),this->total(i));+ + fields[0]->store(time,strlen(time),system_charset_info);+ fields[1]->store(this->count(i));+ fields[2]->store(total,strlen(total),system_charset_info);+ } if (schema_table_store_record(thd,table)) { DBUG_RETURN(1);
- MySQL源代码:由参数query_response_time_stats想到的
- 由percona5.5参数innodb_adaptive_flushing_method想到的....
- 由request.getSession()想到的函数参数设计原则
- 由dg中的db_file_name_convert参数不生效想到的db_file_create
- 由堆栈所能想到的以及ref,out参数
- query_response_time_stats
- 由本子想到的
- 由忧郁想到的
- 由电车男想到的
- 由MBV想到的
- 由“枣子”想到的
- 由 setMeidatime() 想到的
- 由ff想到的
- 由HelloWorld想到的
- 由观察想到的
- 由面试想到的
- 由自行车想到的......
- 由《变形金刚》想到的
- php cookie保存数组
- oracle基本知识
- 设计模式之备忘录模式(三)
- 考试后的反思
- 黑马程序员--反射
- MySQL源代码:由参数query_response_time_stats想到的
- Android2.2快速入门
- C语言变量存储类型auto,static,extern,static extern,register .
- 类的对象和类的指针的区别
- 两个简单的声音引擎
- 经典的字符串hash
- unix入门学习笔记
- adb常用命令
- oracle下system用户解锁和改密码