数据库一般都带慢查询功能,PostgreSQL数据库可以通过加载插件 pg_stat_statements
实现慢日志功能,对应数据库中的一个表pg_stat_statements,可以通过查看该表获取某个SQL
执行的次数,总花费时间等信息;MySQL带慢查询功能,通过参数设置即可打开慢查询功能。
mysql 慢查询参数设置
slow_query_log = 1 – 慢日志开关
long_query_time = 1 – sql阈值,单位为秒
slow_query_log_file = /home/wl/mysqlcluster/app5726/slowlog/mysql-slow.log – 日志文件名
慢查询主要功能如下:设定sql执行阈值,超过该阈值的sql语句需要记录到对应的表或者文件
中,那么需要的内容如下:
(1) 慢日志开关
(2) sql执行时间阈值
(3) 慢日志记录的文件名称
(4) 记录对应的格式:一般需要包括:时刻、用户名、ip、端口号、库名、sql语句、执行总时间、
开始时间、结束时间。
(1) 主要是如何记录开始时间、结束时间。需要在类 class THD中添加2个变量:start_time,
end_time;
(2) 在语句开始处理时(语句解析前,也就是从客户端发送的语句在数据库最开始处理时)用
thd->start_time记录当前时刻,精确到us,使用函数gettimeofday;在语句执行结束时用thd->end_time
记录结束时间,然后将时间差与sql语句阈值进行比较。
(3) 对于日志文件,如慢日志开关打开,则open 打开该日志文件;写日志用write,刷盘 fflush 函数
,close函数关闭文件
slow_query_log
long_query_time
slow_query_log_file
如何添加系统参数见对用文件介绍。
dispatch_command 函数 中调用
thd->enable_slow_log= TRUE;
thd->set_time(); -- 记录时间
set_time 实现如下:
inline void set_time()
{
start_utime= utime_after_lock= my_micro_time();
if (user_time.tv_sec || user_time.tv_usec)
{
start_time= user_time;
}
else
my_micro_time_to_timeval(start_utime, &start_time);
#ifdef HAVE_PSI_THREAD_INTERFACE
PSI_THREAD_CALL(set_thread_start_time)(start_time.tv_sec);
#endif
}
:: start_time 是 class Thd 中的成员变量。
结构体 start_time 能直接赋值?
:: 可以直接赋值,是浅拷贝。
my_micro_time 函数实现如下:
ulonglong my_micro_time()
{
#ifdef _WIN32
ulonglong newtime;
my_get_system_time_as_file_time((FILETIME*)&newtime);
newtime-= OFFSET_TO_EPOCH;
return (newtime/10);
#else
ulonglong newtime;
struct timeval t;
/*
The following loop is here because gettimeofday may fail on some systems
*/
while (gettimeofday(&t, NULL) != 0)
{}
newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec;
return newtime;
#endif
}
需要再仔细看下 class THD 的定义
见函数 void update_server_status()
/**
Update server status after execution of a top level statement.
Currently only checks if a query was slow, and assigns
the status accordingly.
Evaluate the current time, and if it exceeds the long-query-time
setting, mark the query as slow.
*/
void update_server_status()
{
ulonglong end_utime_of_query= current_utime();
if (end_utime_of_query > utime_after_lock + variables.long_query_time)
server_status|= SERVER_QUERY_WAS_SLOW;
}
其中 start_utime= utime_after_lock 见上面的thd->set_time()
log_slow_statement(thd);
bool File_query_log::write_slow(THD *thd, ulonglong current_utime,
ulonglong query_start_arg,
const char *user_host,
size_t user_host_len, ulonglong query_utime,
ulonglong lock_utime, bool is_command,
const char *sql_text, size_t sql_text_len)
...
bool Query_logger::slow_log_write(THD *thd, const char *query,
size_t query_length)
...