MySQL 学习心得和知识总结(五)|MySQL的一般查询日志(general log)

本文主要是介绍MySQL 学习心得和知识总结(五)|MySQL的一般查询日志(general log),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下:

1、参考书籍:《PostgreSQL数据库内核分析》
2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》
3、PostgreSQL数据库仓库链接,点击前往
4、日本著名PostgreSQL数据库专家 铃木启修 网站主页,点击前往
5、参考书籍:《PostgreSQL中文手册》
6、参考书籍:《PostgreSQL指南:内幕探索》,点击前往
7、参考书籍:《事务处理 概念与技术》
8、Linux安装odbc连接mysql,点击前往


1、本文内容全部来源于开源社区 GitHub和以上博主的贡献,本文也免费开源(可能会存在问题,评论区等待大佬们的指正)
2、本文目的:开源共享 抛砖引玉 一起学习
3、本文不提供任何资源 不存在任何交易 与任何组织和机构无关
4、大家可以根据需要自行 复制粘贴以及作为其他个人用途,但是不允许转载 不允许商用 (写作不易,还请见谅 💖)


MySQL的一般查询日志 general log

  • 文章快速说明索引
  • 一般查询日志简单介绍
    • 日志简介参数配置
    • 文件生成内容分析
    • odbc连接内容生成
  • 一般查询日志性能影响
    • 系统信息
    • 禁用一般查询日志
    • 启用一般查询日志
    • 输出是文件
    • 输出为表(CSV 表)
    • 输出为表(MYISAM 表)
    • 输出为表(MYISAM 表,结构发生一些变化)
    • 结论



文章快速说明索引

学习目标:

做数据库内核开发久了就会有一种 少年得志,年少轻狂 的错觉,然鹅细细一品觉得自己其实不算特别优秀 远远没有达到自己想要的。也许光鲜的表面掩盖了空洞的内在,每每想到于此,皆有夜半临渊如履薄冰之感。为了睡上几个踏实觉,即日起 暂缓其他基于PostgreSQL数据库的兼容功能开发,近段时间 将着重于学习分享Postgres的基础知识和实践内幕。


学习内容:(详见目录)

1、MySQL的一般查询日志(general log)


学习时间:

2024-04-03 18:06:50 星期三


学习产出:

1、MySQL数据库基础知识回顾 1个
2、CSDN 技术博客 1篇
3、PostgreSQL数据库内核深入学习


注:下面我们所有的学习环境是Centos8+PostgreSQL16.1+Oracle19C+MySQL8.0

postgres=# select version();version                                                   
------------------------------------------------------------------------------------------------------------PostgreSQL 17devel on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-21), 64-bit
(1 row)postgres=##-----------------------------------------------------------------------------#SQL> select * from v$version;          BANNER        Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production	
BANNER_FULL	  Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production Version 19.17.0.0.0	
BANNER_LEGACY Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production	
CON_ID 0#-----------------------------------------------------------------------------#mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.27    |
+-----------+
1 row in set (0.06 sec)mysql>

一般查询日志简单介绍

日志简介参数配置

查询日志分为一般查询日志和慢查询日志。

通过查询是否超出如下变量指定时间的值来判定的,例如:

# 指定慢查询超时时长,超出此时长的属于慢查询,会记录到慢查询日志中[root@127.0.0.1] mysql>show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.01 sec)[root@127.0.0.1] mysql>
# 定义一般查询日志和慢查询日志的输出格式,不指定时默认为file# log_output={TABLE|FILE|NONE}
# TABLE:表示记录日志到表中
# FILE:表示记录日志到文件中
# NONE:表示不记录日志[root@127.0.0.1] mysql>show variables like 'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output    | FILE  |
+---------------+-------+
1 row in set (0.01 sec)[root@127.0.0.1] mysql>

在超时时间内完成的查询是一般查询,可以将其记录到一般查询日志中;而超出时间的查询是慢查询,可以将其记录到慢查询日志中。我们今天学习的重点在于一般查询日志,慢查询日志后面有机会详聊!


一般查询日志general log,记录了服务器接收到的每一个查询或是命令,无论这些查询或是命令是否正确甚至是否包含语法错误,general log 都会将其记录下来。

开启general log,MySQL服务器就会不断地记录日志,会产生一定的系统开销。因此所有都默认关闭一般查询日志。

开启general log,如下:

# 它是全局变量[root@127.0.0.1] mysql>show variables like 'general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log   | OFF   |
+---------------+-------+
1 row in set (0.00 sec)[root@127.0.0.1] mysql>set global general_log=on;
Query OK, 0 rows affected (0.00 sec)[root@127.0.0.1] mysql>show global variables like 'general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log   | ON    |
+---------------+-------+
1 row in set (0.01 sec)[root@127.0.0.1] mysql>
# 设置日志文件路径,默认是库文件路径下 主机名加上.log[root@127.0.0.1] mysql>show global variables like 'general_log_file';
+------------------+--------------------------------------------+
| Variable_name    | Value                                      |
+------------------+--------------------------------------------+
| general_log_file | /home/mysql/mysql-8.0.27/data/dbserver.log |
+------------------+--------------------------------------------+
1 row in set (0.00 sec)[root@127.0.0.1] mysql>set global general_log_file='/home/mysql/general.log';
Query OK, 0 rows affected (0.00 sec)[root@127.0.0.1] mysql>show variables like 'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output    | FILE  |
+---------------+-------+
1 row in set (0.00 sec)[root@127.0.0.1] mysql>

文件生成内容分析

general logGeneral Query Log,记录了MySQL服务器的操作。当客户端连接、断开连接、接收到客户端的SQL语句等,都会向general log中写入日志。开启general_log会损失一定的性能(性能上的损失 下面详细解释),但是在开发、测试环境下开启日志,可以帮忙我们加快排查出现的问题。如下:

# 我这里开启两个连接 间隔执行SQL 如下:[mysql@dbserver ~]$ cat general.log 
/home/mysql/mysql-8.0.27/bin/mysqld, Version: 8.0.27 (MySQL Community Server - GPL). started with:
Tcp port: 3306  Unix socket: /tmp/mysql.sock
Time                 Id Command    Argument
2024-04-02T06:58:16.355675Z	   10 Query	show variables like 'log_output'
2024-04-02T07:00:20.967875Z	   10 Quit	
2024-04-02T07:00:41.942253Z	   11 Connect	root@localhost on  using SSL/TLS
2024-04-02T07:00:41.944182Z	   11 Query	select @@version_comment limit 1
2024-04-02T07:00:41.945409Z	   11 Query	select USER()
2024-04-02T07:01:11.162705Z	   11 Query	SELECT DATABASE()
2024-04-02T07:01:11.163151Z	   11 Init DB	mysql
2024-04-02T07:01:25.838190Z	   12 Connect	root@localhost on  using SSL/TLS
2024-04-02T07:01:25.838263Z	   12 Connect	Access denied for user 'root'@'localhost' (using password: YES)
2024-04-02T07:01:51.785487Z	   13 Connect	root@localhost on  using SSL/TLS
2024-04-02T07:01:51.785881Z	   13 Query	select @@version_comment limit 1
2024-04-02T07:01:51.786956Z	   13 Query	select USER()
2024-04-02T07:01:57.526667Z	   13 Query	SELECT DATABASE()
2024-04-02T07:01:57.526913Z	   13 Init DB	mysql
2024-04-02T07:02:29.853995Z	   11 Query	show tables
2024-04-02T07:02:52.531882Z	   11 Query	drop table t0401
2024-04-02T07:04:43.538680Z	   11 Query	create table t0402(id int, curtime TIMESTAMP(6))
2024-04-02T07:06:27.948203Z	   11 Query	insert into t0402 values(1, CURRENT_TIMESTAMP(6))
2024-04-02T07:06:37.420331Z	   13 Query	select * from t0402
2024-04-02T07:07:04.077164Z	   13 Query	drop table t0402
2024-04-02T07:08:04.054919Z	   13 Query	create table t0402(id int, curtime_int bigint(15))
2024-04-02T07:09:14.694347Z	   13 Query	insert into t0402 values(1, REPLACE(unix_timestamp(current_timestamp(6)),'.',''))
2024-04-02T07:09:24.407249Z	   11 Query	select * from t0402
2024-04-02T07:10:18.758216Z	   11 Quit	
2024-04-02T07:10:23.518195Z	   13 Quit	
[mysql@dbserver ~]$

[mysql@dbserver ~]$ mysql -h 127.0.0.1 -u root -p -A
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 15
Server version: 8.0.27 MySQL Community Server - GPLCopyright (c) 2000, 2021, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.[root@127.0.0.1] (none)>use mysql;
Database changed
[root@127.0.0.1] mysql>select * from t0402;
+------+------------------+
| id   | curtime_int      |
+------+------------------+
|    1 | 1712041754694258 |
+------+------------------+
1 row in set (0.00 sec)[root@127.0.0.1] mysql>prepare p1 as select * from t0402 where id < $1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as select * from t0402 where id < $1' at line 1
[root@127.0.0.1] mysql>
[root@127.0.0.1] mysql>prepare p1 from select * from t0402 where id < $1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select * from t0402 where id < $1' at line 1
[root@127.0.0.1] mysql>
[root@127.0.0.1] mysql>prepare p1 from 'select * from t0402 where id < $1';
ERROR 1054 (42S22): Unknown column '$1' in 'where clause'
[root@127.0.0.1] mysql>
[root@127.0.0.1] mysql>prepare p1 from 'select * from t0402 where id < ?';
Query OK, 0 rows affected (0.00 sec)
Statement prepared[root@127.0.0.1] mysql>SET @a = 3;
Query OK, 0 rows affected (0.00 sec)[root@127.0.0.1] mysql>EXECUTE p1 USING @a;
+------+------------------+
| id   | curtime_int      |
+------+------------------+
|    1 | 1712041754694258 |
+------+------------------+
1 row in set (0.00 sec)[root@127.0.0.1] mysql>prepare p2 from 'select * from t0402 where id = ?';
Query OK, 0 rows affected (0.00 sec)
Statement prepared[root@127.0.0.1] mysql>SET @a = 1;
Query OK, 0 rows affected (0.00 sec)[root@127.0.0.1] mysql>EXECUTE p2 USING @a;
+------+------------------+
| id   | curtime_int      |
+------+------------------+
|    1 | 1712041754694258 |
+------+------------------+
1 row in set (0.00 sec)[root@127.0.0.1] mysql>
...
2024-04-02T07:40:34.865834Z	   15 Connect	root@localhost on  using SSL/TLS
2024-04-02T07:40:34.866145Z	   15 Query	select @@version_comment limit 1
2024-04-02T07:40:34.866744Z	   15 Query	select USER()
2024-04-02T07:40:47.075169Z	   15 Query	SELECT DATABASE()
2024-04-02T07:40:47.075481Z	   15 Init DB	mysql
2024-04-02T07:40:58.135514Z	   15 Query	select * from t0402
2024-04-02T07:42:26.177204Z	   15 Query	PREPARE p1 FROM ...
2024-04-02T07:42:40.265662Z	   15 Query	PREPARE p1 FROM ...
2024-04-02T07:42:40.265822Z	   15 Prepare	select * from t0402 where id < ?
2024-04-02T07:43:18.121465Z	   15 Query	SET @a = 3
2024-04-02T07:43:41.852319Z	   15 Query	EXECUTE p1 USING @a
2024-04-02T07:43:41.852422Z	   15 Execute	select * from t0402 where id < 3
2024-04-02T07:45:07.481268Z	   15 Query	PREPARE p2 FROM ...
2024-04-02T07:45:07.481445Z	   15 Prepare	select * from t0402 where id = ?
2024-04-02T07:45:19.637677Z	   15 Query	SET @a = 1
2024-04-02T07:45:26.939353Z	   15 Query	EXECUTE p2 USING @a
2024-04-02T07:45:26.939432Z	   15 Execute	select * from t0402 where id = 1
[mysql@dbserver ~]$

在这里插入图片描述

如上图所示:

  • 有语法错误的没有记入
  • 有错 但非 语法错误,则仍然记入
  • simple query记入一行 Query
  • 一个prepare/execute 记入两行:Query Prepare/Execute

如上各列说明,如下:

  • Time 日志记录的时间
  • Id 进程ID,可以通过show processlist命令查看
  • Command 执行的命令
  • Argument 命令参数

这里的命令类型,如下:

// sql\sql_parse.ccconst std::string Command_names::m_names[] = {"Sleep","Quit","Init DB", // 使用命令use选择库时的记录"Query","Field List","Create DB","Drop DB","Refresh","Shutdown","Statistics","Processlist","Connect","Kill","Debug","Ping","Time","Delayed insert","Change user","Binlog Dump","Table Dump","Connect Out","Register Replica","Prepare","Execute","Long Data","Close stmt","Reset stmt","Set option","Fetch","Daemon","Binlog Dump GTID","Reset Connection","clone","Group Replication Data Stream subscription","Error"  // Last command number
};
// include\my_command.h/**@enum  enum_server_command@brief A list of all MySQL protocol commands.These are the top level commands the server can receivewhile it listens for a new command in ::dispatch_command@par WarningAdd new commands to the end of this list, otherwise oldservers won't be able to handle them as 'unsupported'.
*/
enum enum_server_command {/**Currently refused by the server. See ::dispatch_command.Also used internally to mark the start of a session.*/COM_SLEEP,COM_QUIT,       /**< See @ref page_protocol_com_quit */COM_INIT_DB,    /**< See @ref page_protocol_com_init_db */COM_QUERY,      /**< See @ref page_protocol_com_query */COM_FIELD_LIST, /**< Deprecated. See @ref page_protocol_com_field_list */COM_CREATE_DB, /**< Currently refused by the server. See ::dispatch_command */COM_DROP_DB,   /**< Currently refused by the server. See ::dispatch_command */COM_REFRESH,   /**< Deprecated. See @ref page_protocol_com_refresh */COM_DEPRECATED_1, /**< Deprecated, used to be COM_SHUTDOWN */COM_STATISTICS,   /**< See @ref page_protocol_com_statistics */COM_PROCESS_INFO, /**< Deprecated. See @ref page_protocol_com_process_info */COM_CONNECT,      /**< Currently refused by the server. */COM_PROCESS_KILL, /**< Deprecated. See @ref page_protocol_com_process_kill */COM_DEBUG,        /**< See @ref page_protocol_com_debug */COM_PING,         /**< See @ref page_protocol_com_ping */COM_TIME,         /**< Currently refused by the server. */COM_DELAYED_INSERT, /**< Functionality removed. */COM_CHANGE_USER,    /**< See @ref page_protocol_com_change_user */COM_BINLOG_DUMP,    /**< See @ref page_protocol_com_binlog_dump */COM_TABLE_DUMP,COM_CONNECT_OUT,COM_REGISTER_SLAVE,COM_STMT_PREPARE, /**< See @ref page_protocol_com_stmt_prepare */COM_STMT_EXECUTE, /**< See @ref page_protocol_com_stmt_execute *//** See  @ref page_protocol_com_stmt_send_long_data */COM_STMT_SEND_LONG_DATA,COM_STMT_CLOSE, /**< See @ref page_protocol_com_stmt_close */COM_STMT_RESET, /**< See @ref page_protocol_com_stmt_reset */COM_SET_OPTION, /**< See @ref page_protocol_com_set_option */COM_STMT_FETCH, /**< See @ref page_protocol_com_stmt_fetch *//**Currently refused by the server. See ::dispatch_command.Also used internally to mark the session as a "daemon",i.e. non-client THD. Currently the scheduler and the GTIDcode does use this state.These threads won't be killed by `KILL`@sa Event_scheduler::start, ::init_thd, ::kill_one_thread,::Find_thd_with_id*/COM_DAEMON,COM_BINLOG_DUMP_GTID,COM_RESET_CONNECTION, /**< See @ref page_protocol_com_reset_connection */COM_CLONE,COM_SUBSCRIBE_GROUP_REPLICATION_STREAM,/* don't forget to update const char *command_name[] in sql_parse.cc *//* Must be last */COM_END /**< Not a real command. Refused. */
};

如上文件中的时间值,转换为微秒的时间戳 如下:

[root@127.0.0.1] (none)>select REPLACE(unix_timestamp('2024-04-02T07:10:18.758216Z'),'.','');
+---------------------------------------------------------------+
| REPLACE(unix_timestamp('2024-04-02T07:10:18.758216Z'),'.','') |
+---------------------------------------------------------------+
| 1712013018758216                                              |
+---------------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)[root@127.0.0.1] (none)>show variables like "%time_zone%";
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)[root@127.0.0.1] (none)>select now();
+---------------------+
| now()               |
+---------------------+
| 2024-04-02 15:29:36 |
+---------------------+
1 row in set (0.00 sec)[root@127.0.0.1] (none)>
[root@127.0.0.1] (none)>select REPLACE(unix_timestamp('2024-04-02 07:10:18.758216'),'.','');
+--------------------------------------------------------------+
| REPLACE(unix_timestamp('2024-04-02 07:10:18.758216'),'.','') |
+--------------------------------------------------------------+
| 1712013018758216                                             |
+--------------------------------------------------------------+
1 row in set (0.00 sec)[root@127.0.0.1] (none)>

这里的prepare操作,转换如下:

2024-04-02T07:45:07.481268Z	   15 Query	PREPARE p2 FROM ...
2024-04-02T07:45:07.481445Z	   15 Prepare	select * from t0402 where id = ?
2024-04-02T07:45:19.637677Z	   15 Query	SET @a = 1
2024-04-02T07:45:26.939353Z	   15 Query	EXECUTE p2 USING @a
2024-04-02T07:45:26.939432Z	   15 Execute	select * from t0402 where id = 1// sql\sql_rewrite.cc/**Rewrite the query for the PREPARE statement.@param[in,out] rlb     Buffer to return the rewritten query in.@retval        true    the query was rewritten@retval        false   otherwise
*/
bool Rewriter_prepare::rewrite(String &rlb) const {LEX *lex = m_thd->lex;if (lex->prepared_stmt_code_is_varref) return false;rlb.append(STRING_WITH_LEN("PREPARE "));rlb.append(lex->prepared_stmt_name.str, lex->prepared_stmt_name.length);rlb.append(STRING_WITH_LEN(" FROM ..."));return true;
}

odbc连接内容生成

SQL> select version();
+----------+
| version()|
+----------+
| 8.0.27   |
+----------+
SQLRowCount returns 1
1 rows fetched
SQL> 
[mysql@dbserver ~]$ sudo yum install unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel
已加载插件:ulninfo
软件包 unixODBC-2.3.1-14.0.1.el7.x86_64 已安装并且是最新版本
软件包 unixODBC-devel-2.3.1-14.0.1.el7.x86_64 已安装并且是最新版本
软件包 libtool-ltdl-2.4.2-22.el7_3.x86_64 已安装并且是最新版本
软件包 libtool-ltdl-devel-2.4.2-22.el7_3.x86_64 已安装并且是最新版本
无须任何处理
[mysql@dbserver ~]$ ## https://downloads.mysql.com/archives/c-odbc/
[mysql@dbserver odbc_mysql8]$ wget https://cdn.mysql.com/archives/mysql-connector-odbc-8.0/mysql-connector-odbc-8.0.20-1.el7.x86_64.rpm
--2024-04-03 16:09:12--  https://cdn.mysql.com/archives/mysql-connector-odbc-8.0/mysql-connector-odbc-8.0.20-1.el7.x86_64.rpm
正在解析主机 cdn.mysql.com (cdn.mysql.com)... 2402:4f00:4002:19d::1d68, 2402:4f00:4002:190::1d68, 23.7.220.59
正在连接 cdn.mysql.com (cdn.mysql.com)|2402:4f00:4002:19d::1d68|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:4302344 (4.1M) [application/x-redhat-package-manager]
正在保存至: “mysql-connector-odbc-8.0.20-1.el7.x86_64.rpm”100%[=========================================================================================================================================================================>] 4,302,344   3.47MB/s 用时 1.2s   2024-04-03 16:09:16 (3.47 MB/s) - 已保存 “mysql-connector-odbc-8.0.20-1.el7.x86_64.rpm” [4302344/4302344])[mysql@dbserver odbc_mysql8]$ ls
mysql-connector-odbc-8.0.20-1.el7.x86_64.rpm
[mysql@dbserver odbc_mysql8]$ 
[mysql@dbserver odbc_mysql8]$ sudo rpm -ivh mysql-connector-odbc-8.0.20-1.el7.x86_64.rpm 
警告:mysql-connector-odbc-8.0.20-1.el7.x86_64.rpm: 头V3 DSA/SHA1 Signature, 密钥 ID 5072e1f5: NOKEY
准备中...                          ################################# [100%]
正在升级/安装...1:mysql-connector-odbc-8.0.20-1.el7################################# [100%]
Success: Usage count is 1
Success: Usage count is 1
[mysql@dbserver odbc_mysql8]$

测试unixODBC安装是否成功,如下:

[mysql@dbserver ~]$ odbcinst -j
unixODBC 2.3.1
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/mysql/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
[mysql@dbserver ~]$ odbcinst -q -d
[PostgreSQL]
[MySQL]
[MySQL ODBC 8.0 Unicode Driver]
[MySQL ODBC 8.0 ANSI Driver]
[mysql@dbserver ~]$

配置 odbc.ini,如下:

[mysql@dbserver ~]$ odbcinst -j
unixODBC 2.3.1
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/mysql/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
[mysql@dbserver ~]$ odbcinst -q -d
[PostgreSQL]
[MySQL]
[MySQL ODBC 8.0 Unicode Driver]
[MySQL ODBC 8.0 ANSI Driver]
[mysql@dbserver ~]$ 
[mysql@dbserver ~]$ sudo vim /etc/odbc.ini
[mysql@dbserver ~]$ 
[mysql@dbserver ~]$ cat /etc/odbc.ini
[mysql]
Description     = Data source sampleMySQL for accessing MySQL database sampleMySQL
Driver          = MySQL ODBC 8.0 Unicode Driver
Server          = 127.0.0.1
Host            = 127.0.0.1
Database        = mysql
Port            = 3306
User            = root
Password        =123456
[mysql@dbserver ~]$ 
[mysql@dbserver ~]$ isql -v mysql
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL>

我这里使用odbc进行操作,日志内容 如下:

[mysql@dbserver ~]$ cat general.log | grep '12 '
2024-04-03T08:26:37.163240Z	   12 Connect	root@localhost on mysql using SSL/TLS
2024-04-03T08:26:37.163849Z	   12 Query	SET NAMES utf8
2024-04-03T08:26:37.164332Z	   12 Query	SET character_set_results = NULL
2024-04-03T08:26:37.164538Z	   12 Query	SET SQL_AUTO_IS_NULL = 0
2024-04-03T08:27:18.292965Z	   12 Query	set @@sql_select_limit=DEFAULT
2024-04-03T08:27:18.293298Z	   12 Query	desc t0402
2024-04-03T08:27:35.010027Z	   12 Query	select * from t0402
2024-04-03T08:28:04.549888Z	   12 Query	PREPARE odbcp1 FROM ...
2024-04-03T08:28:04.550654Z	   12 Prepare	select * from t0402 where id < ?
2024-04-03T08:28:32.707333Z	   12 Query	SET @a = 3
2024-04-03T08:28:58.102807Z	   12 Query	EXECUTE odbcp1 USING @a
2024-04-03T08:28:58.102929Z	   12 Execute	select * from t0402 where id < 3
2024-04-03T08:29:12.346332Z	   12 Quit	
[mysql@dbserver ~]$

可以看出使用odbc的日志记录(格式/内容)上,和上面直接使用client一致!


一般查询日志性能影响

  • IMPACT OF GENERAL QUERY LOG ON MYSQL PERFORMANCE,点击前往

有时,需要启用通用查询日志(默认情况下禁用)。如果启用了通用查询日志,则当客户端连接或断开连接时,以及从客户端接收到的每个 SQL 语句时,服务器都会写入此日志信息。问题是:

  • 启用通用查询日志会影响MySQL性能吗?
  • 另外,可以将该日志的输出记录到mysql数据库(mysql.general_log)中的文件或表中,每种记录对性能有何影响?

让我们针对这些场景做一些简单的基准测试来衡量对 mysql 性能的实际影响。


系统信息

硬件配置:

  • CPU: Intel® Core™ i7-3520M Processor (4M Cache, up to 3.60 GHz).
    • 2 cores, 4 threads, HT enabled.
  • Memory: 8GB RAM (1600).
  • Storage: HDD 1TB/ 5400RPM.

软件配置:

  • OS: Ubuntu 12.04
  • MySQL Server: 5.6.17
  • Sysbench: 0.4.12

测试信息:

  • Sysbench命令:
sysbench --num-threads=1 --max-requests=1000 --db-driver=mysql --test=oltp --mysql-table-engine=InnoDB --mysql-user=root run 
  • sysbench 测试使用的表结构
mysql> show create table sbtest.sbtest\GCREATE TABLE `sbtest` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`k` int(10) unsigned NOT NULL DEFAULT '0',`c` char(120) NOT NULL DEFAULT '',`pad` char(60) NOT NULL DEFAULT '',PRIMARY KEY (`id`),KEY `k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=8574 DEFAULT CHARSET=latin1

注意:

该测试针对 1、2、4、8、16 和 32 个线程进行,每个测试用例的每个线程数的每个吞吐量/响应时间值是由十 (10) 次执行的平均值生成的。


禁用一般查询日志

要确保禁用常规查询日志:

mysql> show global variables like'general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log   | OFF   |
+---------------+-------+

测试结果,如下:

在这里插入图片描述

启用一般查询日志

通用查询日志是一个动态变量,这意味着它可以在线启用或禁用,而无需重新启动 MySQL(自 MySQL 5.1 起):

mysql> SET GLOBAL general_log=ON;

我们可以选择将此日志输出到日志文件(默认情况下)或 MySQL 表 (mysql.general_log) 中。如果我们将日志输出存储在表而不是文件中,我们可能会得到什么好处?

  • 我们可以使用普通的 SQL 语句访问日志内容来获取有关特定条件的信息(例如使用 WHERE 条件),这在处理文件时有点困难
  • 如果有人可以连接到 MySQL 服务器,则可以远程访问日志内容
  • 日志条目的标准格式
  • 如果日志表使用 CSV 引擎,则可以轻松将 CSV 文件导入到电子表格中
  • 只需 TRUNCATE 日志表即可轻松使日志过期
  • 通过使用 RENAME TABLE 语句可以进行日志轮转
  • 日志条目不会复制到从属服务器,因为它们不会写入二进制日志
  • 即使使用了 --all-databases 备份选项,mysqldump 也不在备份中包含日志表内容(general_log 或 Slow_log)

那么,让我们检查一下每个日志输出对性能的影响。

输出是文件

要检查通用查询日志的输出目的地,应使用以下命令:

mysql> show global variables like'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output    | FILE  |
+---------------+-------+

测试结果,如下:

在这里插入图片描述

输出为表(CSV 表)

要将通用查询日志的输出目的地从文件更改为表(默认为 CSV),应使用以下命令:

mysql> SET GLOBAL log_output='TABLE';
mysql> show global variables like'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output    | TABLE |
+---------------+-------+

测试结果,如下:

在这里插入图片描述

输出为表(MYISAM 表)

也许由于 CSV 存储引擎的性质,我们在之前的案例中遇到了性能问题。是否可以更改general_log表的表引擎?

答案是肯定的,但不幸的是,我们被限制只能使用 MyISAM 存储引擎,不允许使用 CSV 或 MyISAM 以外的引擎。检查此链接以获取更多信息。

要更改日志表,您必须首先禁用日志记录:

mysql> alter table mysql.general_log engine=MYISAM;
ERROR 1580 (HY000): You cannot 'ALTER' a log table if logging is enabled
mysql> SET GLOBAL general_log=OFF;mysql> alter table mysql.general_log engine=MYISAM;mysql> SET GLOBAL general_log=ON;

测试结果,如下:

在这里插入图片描述

输出为表(MYISAM 表,结构发生一些变化)

一般来说,为了使任何 SQL 查询运行得更快,我们可能需要优化表结构、添加索引、重写查询等。

通用查询日志表结构如下:

mysql> show create table mysql.general_log\GCREATE TABLE `general_log` (`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`user_host` mediumtext NOT NULL,`thread_id` bigint(21) unsigned NOT NULL,`server_id` int(10) unsigned NOT NULL,`command_type` varchar(64) NOT NULL,`argument` mediumtext NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='General log'

我们来看看如何优化general_log表结构(欢迎其他建议):

  • 我们可以在该表上创建分区来提高我们的搜索吗?虽然这是一个普通的 MyISAM 表,但日志表不允许分区(顺便说一句,CSV 表也不允许分区)
  • 我们可以将user_host列的数据类型从mediumtext更改为例如 varchar(100)?(我的机器上该列数据的最大长度不超过50个字符)虽然它在语法方面已被接受,但此后表中不会存储任何日志,并且错误日志文件中将打印以下错误:
2014-03-06 18:44:21 6987 [ERROR] Failed to write to mysql.general_log:
2014-03-06 18:44:23 6987 [ERROR] Incorrect definition of table mysql.general_log: expected column 'user_host' at position 1 to have type mediumtext, found type varchar(100).
  • 在我们将用于大多数搜索的列(event_timeargument)上创建索引怎么样?

    • event_time 列上添加索引
mysql> SET GLOBAL general_log=OFF;mysql> alter table mysql.general_log add index ev_tm_idx(`event_time`);mysql> show create table mysql.general_log\GCREATE TABLE `general_log` (`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`user_host` mediumtext NOT NULL,`thread_id` bigint(21) unsigned NOT NULL,`server_id` int(10) unsigned NOT NULL,`command_type` varchar(64) NOT NULL,`argument` mediumtext NOT NULL,KEY `ev_tm_idx` (`event_time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='General log'mysql> SET GLOBAL general_log=ON;

测试结果,如下:

在这里插入图片描述

    • argument列上添加全文索引
mysql> SET GLOBAL general_log=OFF;mysql> alter table mysql.general_log add fulltext index (`argument`);mysql> show create table mysql.general_log\GCREATE TABLE `general_log` (`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`user_host` mediumtext NOT NULL,`thread_id` bigint(21) unsigned NOT NULL,`server_id` int(10) unsigned NOT NULL,`command_type` varchar(64) NOT NULL,`argument` mediumtext NOT NULL,KEY `ev_tm_idx` (`event_time`),FULLTEXT KEY `argument` (`argument`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='General log'mysql> SET GLOBAL general_log=ON;

测试结果,如下:

在这里插入图片描述
为了更清楚地说明,以下是将所有结果组合在一张图表中,然后进行响应时间比较:

在这里插入图片描述
在这里插入图片描述
每秒事务数的原始结果可能有用:

Threads12481632
General Query Log disabled383.996814.7591421.2881674.7331414.9851071.189
General Query Log enabled (File)281.642521.391230.7431406.1271095.896923.986
General Query Log enabled (CSV Table)231.659447.173787.578507.846426.324439.992
General Query Log enabled (MyISAM Table)249.47536.379933.304532.912476.454454.015
General Query Log enabled (MyISAM Table + index)238.508430.05875.209465.464465.464395.063
General Query Log enabled (MyISAM Table + Fulltext index)157.436236.156210.968212.273218.617220.701

结论

  • 在上述所有测试用例中,最好的MySQL性能可以通过禁用常规查询日志来实现,例如,如果我们比较上述4并发线程情况的结果(大多数情况下的最高值),我们会发现:

    • 使用启用的通用查询日志 (general_log = ON) 且日志目标为文件 (log_output = FILE) 可使吞吐量降低 13.4%,并使响应时间增加 17.5%
    • 使用启用的通用查询日志并且日志目标是 CSV 表,吞吐量降低了 44.6%,响应时间增加了 90%
    • 使用启用的通用查询日志并且日志目标是 MyISAM 表,吞吐量降低了 34.3%,响应时间增加了 59%
    • 使用启用的通用查询日志并且日志目标是 MyISAM,并在event_time列上添加索引,吞吐量降低了 38.4%,响应时间增加了 73%
    • 使用启用的通用查询日志并且日志目标是 MyISAM,在event_time列上添加索引并在argument列上添加 FULLTEXT 索引,吞吐量降低了 85%,响应时间增加了 542%
  • 虽然使用表作为日志输出目的地有很多好处(如上所述),但与日志文件相比,它对 MySQL 性能的负面影响更大

  • 增加并发运行的线程数(在 log_output=TABLE 的情况下)将增加general_log 表争用,该争用由MyISAM 或CSV ENGINES 的表锁定级别控制

  • 与任何其他 MySQL 表一样 - 日志表中插入的行数越多,负面性能影响越大

  • 虽然 mysqldump 不包括备份中的日志表内容,但使用 Xtrabackup 或任何其他基于物理备份的工具进行完整物理备份时,情况并非如此

  • 最后,最好只在真正需要时才启用通用查询日志,不建议在生产系统中启用它。它可以(动态)启用一段时间,然后在我们获得要搜索的内容后再次禁用

这篇关于MySQL 学习心得和知识总结(五)|MySQL的一般查询日志(general log)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/874610

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来