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 或任何其他基于物理备份的工具进行完整物理备份时,情况并非如此

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/589769.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LLM:检索增强生成(RAG)

1 Embedding技术 简单地说&#xff0c;嵌入(Embedding)思想可以视为一种尝试通过用向量来表示所有东西的“本质”的方法&#xff0c;其特性是“相近的事物”由相近的数表示。 1.1 文本向量(Text Embedding) 在GPT中&#xff0c;文本嵌入(Text Embedding)是通过将输入文本中的每…

搭建跨境电商电商独立站如何接入1688平台API接口|通过1688API接口采集商品通过链接搜索商品下单

接口设计|接口接入 对于mall项目中商品模块的接口设计&#xff0c;大家可以参考项目的Swagger接口文档&#xff0c;以Pms开头的接口就是商品模块对应的接口。 参数说明 通用参数说明 参数不要乱传&#xff0c;否则不管成功失败都会扣费url说明……d.cn/平台/API类型/ 平台&…

WEB 工程路径

WEB 工程路径 相对路径 使用相对路径来解决&#xff0c; 一个非常重要的规则&#xff1a;页面所有的相对路径&#xff0c;在默认情况下&#xff0c;都会参考当前浏览器地址栏的路径 http://ip:port/工程名/ 资源来进行跳转。 相对路径带来的问题 如上图&#xff0c;若在a.h…

黄锈水过滤器 卫生热水工业循环水色度水处理器厂家工作原理动画

​ 1&#xff1a;黄锈水处理器介绍 黄锈水处理器是一种专门用于处理“黄锈水”的设备&#xff0c;它采用机电一体化设计&#xff0c;安装方便&#xff0c;操作简单&#xff0c;且运行费用极低。这种处理器主要由数码射频发生器、射频换能器、活性过滤体三部分组成&#xff0c;…

MySQL的基本操作(超详细)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 &#x1f4d4;&#xff08;零基础&#xff09;专栏&#xff1a;MSQL数据库 欢迎&#x1f64f;点赞&…

execl产品排行分析

产品排行分析 1.原数据 2.透视表 选择日期--数据--组合 效果如下&#xff1a; 修改透视表排版&#xff1a; 3.提取数据 将需要分析的数据拷贝至新的表中&#xff1a; 4.排序 1996年度进行排序 效果 添加名次 效果 同理处理1997年度数据和排行 新增一列&#xff1a; 名次变…

源聚达科技:抖音开网店步骤难吗

在数字化浪潮的推动下&#xff0c;抖音平台不仅成为了人们娱乐休闲的好去处&#xff0c;更是许多创业者眼中的“金矿”。然而&#xff0c;对于初次尝试在抖音开设网店的朋友来说&#xff0c;难免会对开店流程感到疑惑。究竟开设一个抖音网店的难度如何呢?让我们一探究竟。 要明…

04 Python进阶:MySQL-PyMySQL

什么是 PyMySQL&#xff1f; PyMySQL 是一个用于 Python 的纯 Python MySQL 客户端库&#xff0c;提供了与 MySQL 数据库进行交互的功能。PyMySQL 允许 Python 开发人员连接到 MySQL 数据库服务器&#xff0c;并执行诸如查询、插入、更新和删除等数据库操作。 以下是 PyMySQL …

SSL证书有哪些种类?有免费的吗?

SSL证书主要有以下几种类型&#xff1a; 1. 域名验证型SSL证书 (DV SSL)&#xff1a; - 仅对申请者的域名所有权进行验证&#xff0c;无需人工验证申请单位的真实身份。 - 审核快速&#xff0c;通常适用于个人网站、小型组织或各类加密应用。 2. 组织验证型SSL证书 (OV…

9.动态规划——4.最长公共子序列(动态规划类的算法题该如何解决?)

例题——最长公共子序列(一) 分析 设最长公共子序列 d p [ i ] [ j ] dp[i][j] dp[i][j]是 S 1 S_1 S1​的前 i i i个元素&#xff0c;是 S 2 S_2 S2​的前 j j j个元素&#xff0c;那么有&#xff1a; 若 S 1 [ i − 1 ] S 2 [ i − 1 ] S_1[i-1]S_2[i-1] S1​[i−1]S2​[…

E-魔法猫咪(遇到过的题,做个笔记)

题解&#xff1a; 来自学长们思路&#xff1a; 其中一种正解是写单调队列。限制队列内的数单调递增&#xff0c;方法为每当新来的数据比当前队尾数据小时队 尾出列&#xff0c;直到能够插入当前值&#xff0c;这保证了队头永远是最小值。因此总体思路是队尾不断插入新值的同时 …

ABAP Restful接口

文章目录 ABAP Restful接口代码 ABAP Restful接口 代码 METHOD if_http_extension~handle_request.TYPES: BEGIN OF parameter,name TYPE string,value TYPE string,END OF parameter.TYPES : BEGIN OF ty_material,werks TYPE marc-werks, "工厂matnr TYPE mara-matnr, …