开发实践|记一次尴尬的MySQL授权导致的问题

2023-11-27 19:53:52 浏览数 (1)

前言

1 背景概述

1.1 授权用户查询不到表?

是这样子,前几日我的一位同事需要创建一个用户并且授权几张业务表提供给伙伴小组同事使用。脚本创建,提供授权。给伙伴使用时,伙伴小组给予的回复是查询不到表,整整给摆了一道乌龙。由于是半道儿上临时受命接的项目,也不知道前任捣鼓了啥,经过排查日志发现,是设置了MySQL的审计。好,那今日就浅浅的聊一下吧,作为一个成长。

1.2 什么是MySQL审计?遵循什么规范?

MySQL Enterprise Edition 包括 MySQL Enterprise Audit,使用服务器插件实现。MySQL Enterprise Audit 使用开放的 MySQL Audit API 来启用标准的、基于策略的监控和记录在特定 MySQL 服务器上执行的连接和查询活动。MySQL Enterprise Audit 旨在满足 Oracle 审计规范,为受内部和外部监管准则约束的应用程序提供了一个开箱即用、易于使用的审计和合规性解决方案。安装后,审计插件使 MySQL 服务器能够生成包含服务器活动审计记录的日志文件。日志内容包括客户端连接和断开连接的时间,以及它们在连接时执行的操作,例如它们访问的数据库和表。

关于Oracle审计的规范,可以参考下官方提供的白皮文档。

审计概述:https://docs.oracle.com/cd/E26926_01/html/E25889/auditov-1.html#scrolltoc

审计白皮书:https://www.oracle.com/cn/a/tech/docs/technical-resources/bwp-security-audit-vault.pdf

1.3 MySQL审计解决什么问题?

// to do

2 本地实验环境

MySQL专业版(MySQL Enterprise Edition)审计请参考官方提供的解决方案和操作执行步骤:MySQL Enterprise Edition审计 ,下面来说说MySQL Community (GPL) 社区版本自建测试环境审计是如何设置的。本文是在 GNU/Linux(CentOS 7 x86_64)环境下实验,后续我又在Mac上面实验了下,都是一致的结果。

MySQL审计这里提供几种方式来讲一下,根据自己实验操作的步骤一一列出来,提供给大家借鉴,欢迎大家提出意见,不胜感激。也希望在MySQL进阶技能树的进阶可以有这个实践。

MySQL审计的三种方式:

  • General Query Log
  • BinLog init_connect
  • 审计插件

下面先讲一下这个 general_log。

2.1 general_log(不推荐)

默认情况下,MySQL不开启General Query Log;开启General Query Log后,MySQL将所有到达MySQL Server的SQL语句记录下来。 关于MySQL的日志,官方给予了明确的解释和说明,从字面的意思理解下,通常有以下几种日志:

日志类型

名称

日志信息

Error log

错误日志

启动、运行或停止 mysqld时遇到的问题

General query log

一般查询日志

已建立的客户端连接和从客户端收到的语句

Binary log

二进制日志

更改数据的语句(也用于复制)

Relay log

中继日志

从复制源服务器接收的数据更改

Slow query log

慢查询日志

执行时间超过 long_query_time几秒钟的查询

DDL log (metadata log)

DDL 日志(元数据日志)

DDL 语句执行的元数据操作

2.2.1 查看general_log设置

执行SQL命令可以看到默认general_logOFF的,SQL关键字语句和属性值是不区分大小写(这个可以设置)。

代码语言:javascript复制
mysql> show variables like 'general_log';

2.2.2 查看日志文件

General Query Log打开后,所有SQL的访问都会记录在general_log_file指向的日志文件。关于全局变量general_log_file值,日志文件位置,可以执行下面命令获取到。

代码语言:javascript复制
mysql> show variables like 'general_log_file';

默认情况下,日志文件会放在你的MySQL文件下,命名规则为机器名称.log,例如我的mysql日志放在了/usr/local/mysql-8.0.18-macos10.14-x86_64/data/(通常情况下,我们称/usr/local/mysql-8.0.18-macos10.14-x86_64/MySQ_HOME)目录,机器名称为Macbook,那么这里的日志文件则是Macbook.log

首先,我们可以看一下这个文件存放了什么内容。

代码语言:javascript复制
Aion.Liu $ tail -200f /usr/local/mysql-8.0.18-macos10.14-x86_64/data/Macbook.log
tail: /usr/local/mysql-8.0.18-macos10.14-x86_64/data/Macbook.log: No such file or directory

No such file or directory这提示我们没有这个文件或目录?事实上,这个也验证了我们第1步骤的准确性,默认是关闭的。

2.2.3 手工打开General Query Log

当执行mysql> set global general_log = on; 后,我们设置了全局变量general_log为打开状态,再次查看general_log是打开的,为ON状态。

当我们打开之后,我们再次按照2.2.2的步骤查看下日志文件的内容,惊喜来了,里面有文本内容了(下面我截取了部分)。

代码语言:javascript复制
Aion.Liu $ tail -200f /usr/local/mysql-8.0.18-macos10.14-x86_64/data/Macbook.log
										alert_notification.is_default,
										alert_notification.disable_resolve_message,
										alert_notification.send_reminder,
										alert_notification.frequency
										FROM alert_notification
	  							 WHERE alert_notification.org_id = 1 AND ((alert_notification.is_default = '1'))
2022-08-30T14:19:49.933094Z	 3678 Prepare	SELECT
										alert_notification.id,
										alert_notification.uid,
										alert_notification.uid
										FROM alert_notification
	  							 WHERE alert_notification.org_id = 1 AND alert_notification.id = 1
2022-08-30T14:20:35.933719Z	 3608 Close stmt
2022-08-30T14:20:35.933977Z	 3678 Prepare	SELECT `id`, `org_id`, `version`, `name`, `type`, `access`, `url`, `password`, `user`, `database`, `basic_auth`, `basic_auth_user`, `basic_auth_password`, `with_credentials`, `is_default`, `json_data`, `secure_json_data`, `read_only`, `uid`, `created`, `updated` FROM `data_source` WHERE `id`=? AND `org_id`=? LIMIT 1
2022-08-30T14:20:35.934139Z	 3678 Execute	SELECT `id`, `org_id`, `version`, `name`, `type`, `access`, `url`, `password`, `user`, `database`, `basic_auth`, `basic_auth_user`, `basic_auth_password`, `with_credentials`, `is_default`, `json_data`, `secure_json_data`, `read_only`, `uid`, `created`, `updated` FROM `data_source` WHERE `id`=4 AND `org_id`=1 LIMIT 1
2022-08-30T14:20:35.934361Z	 3678 Close stmt
2022-08-30T14:20:35.935332Z	 3608 Prepare	SELECT
										alert_notification.id,
										alert_notification.uid,
										alert_notification.org_id,
										alert_notification.name,
										alert_notification.type,
										alert_notification.created,
										alert_notification.updated,
										alert_notification.settings,
										alert_notification.secure_settings,
										alert_notification.is_default,
										alert_notification.disable_resolve_message,
										alert_notification.send_reminder,
										alert_notification.frequency
										FROM alert_notification
	  							 WHERE alert_notification.org_id = ? AND ((alert_notification.is_default = ?))
2022-08-30T14:20:35.935422Z	 3608 Execute	SELECT
										alert_notification.id,
										alert_notification.uid,
										alert_notification.org_id,
										alert_notification.name,
										alert_notification.type,
										alert_notification.created,
										alert_notification.updated,
										alert_notification.settings,
										alert_notification.secure_settings,
										alert_notification.is_default,
										alert_notification.disable_resolve_message,
										alert_notification.send_reminder,
										alert_notification.frequency										
										……

查看下当前日志文件的大小324K,这里我们打开日志后,日志就会实时写入到日志文件中。

代码语言:javascript复制
Aion.Liu $ du -h /usr/local/mysql-8.0.18-macos10.14-x86_64/data/Macbook.log
324K	/usr/local/mysql-8.0.18-macos10.14-x86_64/data/Macbook.log

2.2.4 实验

1)我们在命令行工具窗口任意执行一些语句,我这里就查询下table1的表记录数有多少。

2)这个时候,我们看下日志文件的内容是如何记录的

很好理解了吧,查询类型以及执行语句的内容已经被记录到了日志中。

3)使用客户端工具执行SQL命令,在我本地实验数据库study中,查询abc这张表的两个列数据。

4)这个时候,我们在过去日志文件查询下。

是不是很好理解了,这个时候在服务器执行的操作会被记录到设置的日志文件Macbook.log中。

5)我们关闭全局日志设置试试 执行命令如下命令

代码语言:javascript复制
mysql> set global general_log = off;
Query OK, 0 rows affected (0.00 sec)

查看日志文件内容

代码语言:javascript复制
tail -200f /usr/local/mysql-8.0.18-macos10.14-x86_64/data/Macbook.log

由于我这里开启了调度事件和一些触发器,导致一直在执行SQL语句,所以会打印出来很多日志信息。当我们再次关闭时,日志将不在打印,并且在最后一行告知我们已经关闭了日志。那是不是所有的操作都会被记录到日志中呢,你如果有兴趣可以在本地试试。写到这里,前面遗留的一个 // to do 就无需我再多言了。

3 总结

开启General Query Log只要用户执行了操作,无论对错,MySQL就会记录日志,这样的话日志量会非常庞大,对数据库效率有影响。所以我们一般不建议开启开功能,个别情况下可能会临时的开一段时间以供排查故障等使用。


我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞