共计 7528 个字符,预计需要花费 19 分钟才能阅读完成。
这篇文章主要讲解了“如何理解 SQL 审核利器 goinception”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“如何理解 SQL 审核利器 goinception”吧!
一、goinception 简介
使用过 inception 的人对 SQL 审核这块获取都比较熟悉,作为 DBA,审核 SQL 是日常工作中的很重要的一块内容,审核好 SQL 对于后期项目以及数据库维护上起着至关重要的作用,好比一座大厦没有坚实的地基支撑,也就无法长期屹立不倒。
goInception 是一个集审核、执行、备份及生成回滚语句于一身的 MySQL 运维工具, 通过对执行 SQL 的语法解析,返回基于自定义规则的审核结果,并提供执行和备份及生成回滚语句的功能。
从架构上来说,goinception 简直跟 inception 一模一样,SQL 提交到 goinception,goinception 连接到线上 MySQL 进行审核。执行的时候也是连接到线上 MySQL 进行执行,goinception 提供了备份、回滚的功能,意思就是能够监听执行期间的 binlog,基于 binlog 生成反向的回滚 SQL。
二、安装测试
废话不多说,咱们直接安装测试一把。
下载、安装
官方提供了二进制包,简直安装部署的一大福利。
下载地址:https://github.com/hanchuanchuan/goInception/releases
下载好对应版本的 goinception,直接解压即可,解压完成以后在 config/config.toml.default 有一个默认的配置文件,大概意思也写得比较清楚了,那我修改的部分已经写在下面的配置文件中了,其他部分我都没有修改
# 日志文件 [log.file] filename = /opt/goinception/logs/goinception.log max-days = 7 max-backups = 7 [inc] backup_host = xxxx backup_port = 3306 backup_user = goinception backup_password = goinception sql_safe_updates = 1 lang = zh-CN [osc] osc_min_table_size = 1024 [ghost] ghost_on = true ghost_chunk_size = 10000 ghost_dml_batch_size = 100
那么,我们启动 goinception
./goInception -config=config/config.toml
启动以后,我们可以看到端口 4000 已经启动监听了
[root@VM_0_9_centos ~]# netstat -lntp|grep 4000 tcp6 0 0 :::4000 :::* LISTEN 31404/./goInception
测试
goinception 可以沿用 inception 的调用方法,示例如下:
/*--user=root;--password=root;--host=127.0.0.1;--check=1;--port=3306;*/ inception_magic_start; use test; create table t1(id int primary key); inception_magic_commit;
那么我们构建一个 python 脚本来进行测试:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- import pymysql import prettytable as pt tb = pt.PrettyTable() sql = /*--user=xucl;--password=xuclxucl123;--host=127.0.0.1;--check=1;--port=3308;*/ inception_magic_start; use sbtest; create table t1(id int primary key,c1 int, c2 int); insert into t1(id,c1,c2) values(1,1,1); inception_magic_commit; conn = pymysql.connect(host= 127.0.0.1 , user= , passwd= , db= , port=4000, charset= utf8mb4) cur = conn.cursor() ret = cur.execute(sql) result = cur.fetchall() cur.close() conn.close() tb.field_names = [i[0] for i in cur.description] for row in result: tb.add_row(row) print(tb)
执行后输出如下:
[root@VM_0_9_centos goinception]# python3 test.py +----------+---------+-------------+-----------------+-----------------+----------------------------------------------------+---------------+--------------+---------------+--------------+---------+-------------+ | ------+---------------+--------------+---------------+--------------+---------+-------------+|order_id|stage|error_ | ------+---------------+--------------+---------------+--------------+---------+-------------+|order_id|stage|error_ | ------+---------------+--------------+---------------+--------------+---------+-------------+|order_id|stage|error_level | ------+---------------+--------------+---------------+--------------+---------+-------------+|order_id|stage|error__status | ------+---------------+--------------+---------------+--------------+---------+-------------+|order_id|stage|error_message | sql | affected_rows | sequence | backup_dbname | execute_time | sqlsha1 | backup_time | +----------+---------+-------------+-----------------+-----------------+----------------------------------------------------+---------------+--------------+---------------+--------------+---------+-------------+ | 1 | CHECKED | 0 | Audit Completed | None | use sbtest | 0 | 0_0_00000000 | None | 0 | None | 0 | | 2 | CHECKED | 2 | Audit Completed | 表 t1 已存在. | create table t1(id int primary key,c1 int, c2 int) | 0 | 0_0_00000001 | None | 0 | None | 0 | | 3 | CHECKED | 0 | Audit Completed | None | insert into t1(id,c1,c2) values(1,1,1) | 1 | 0_0_00000002 | None | 0 | None | 0 | +----------+---------+-------------+-----------------+-----------------+----------------------------------------------------+---------------+--------------+---------------+--------------+---------+-------------+
可以看到审核结果还是非常清晰的
那如果需要执行的话怎么做呢?我们只需要修改示例中的头部,将 –check= 1 改成 –execute= 1 即可
/*--user=xucl;--password=xuclxucl123;--host=127.0.0.1;--execute=1;--port=3308;*/
那你如果想备份的话,添加选项 –backup= 1 即可
/*--user=xucl;--password=xuclxucl123;--host=127.0.0.1;--execute=1;--backup=1;--port=3308;*/
三、审核规则
goinception 的审核规则可以见文档:https://hanchuanchuan.github.io/goInception/rules.html
我捡了一些我认为比较重要的审核规则,列成表格如下:
create table
表属性
检查项相关配置项这个表不存在 当前库存在 表名、列名、索引名的长度不大于 64 个字节 对象名允许字符 [a-zA-Z0-9_]check_identifier 字符集限制 enable_set_charset,support_charset 排序规则限制 enable_set_collation,support_collation 存储引擎限制 enable_set_engine,support_engine 不能建立为分区表 enable_partition_table 只能有一个主键 表要有主键 check_primary_key 至少有一个列 表必须包含某些列 must_have_columns 不允许 create table as 语法 禁止使用 Foreign keyenable_foreign_key
列属性
检查项相关配置项 char 长度大于 20 的时候需要改为 varchar(长度可配置)max_char_length 不能有重复的列名 非数值列不能使用自增 不允许无效库名 / 表名前缀 如果是 timestamp 类型的,则要必须指定默认值。check_timestamp_default 如果是 datetime 类型的,则要必须指定默认值。check_datetime_default 不能同时有两个 timestamp 类型的列,如果是 datetime 类型,则不能有两个指定 DEFAULT CURRENT_TIMESTAMP 及 ON UPDATE CURRENT_TIMESTAMP 的列。check_timestamp_count,check_datetime_count 只有 timestamp 或 datatime 才能指定 on update on update 表达式只能为 CURRENT_TIMESTAMP
索引属性检查项
检查项相关配置项索引必须要有名字 enable_null_index_nameUnique 索引必须要以 uniq_为前缀 check_index_prefix 普通索引必须要以 idx_为前缀 check_index_prefix 索引的列数不能超过 5 个 max_key_parts 主键索引列数限制 max_primary_key_parts 主键列必须使用 int 或 bigintenable_pk_columns_only_int 建索引时,指定的列必须存在。 索引中的列,不能重复 BLOB 列不能建做 KEY 索引长度不能超过 767 或 3072, 由实际 mysql 的 innodb_large_prefix 决定 索引名不能是 PRIMARY 索引名不能重复
默认值
检查项相关配置项 BLOB/TEXT 类型的列,不能有非 NULL 的默认值 enable_blob_not_null 如果默认值为 NULL,但列类型为 NOT NULL,或者是主键列,或者定义为自增列,则报错。 JSON 列不能设置默认值。 每个列都需要定义默认值,除了自增列 / 主键 /JSON/ 计算列 / 以及大字段列之外 check_column_default_value
自增列
检查项相关配置项建表时,自增列初始值为 1check_autoincrement_init_value 如果自增列的名字不为 id,说明可能是有意义的,不建议 check_autoincrement_name 自增列类型必须为 int 或 bigintcheck_autoincrement_datatype 自增列需要设置无符号 enable_autoincrement_unsigned
ALTER
检查项相关配置项表是否存在 同一个表的多个 ALTER 建议合并 merge_alter_table 列是否存在 表属性只支持对存储引擎、表注释、自增值及默认字符集的修改操作。 是否允许 change column 操作 enable_change_column 是否允许列顺序变更 check_column_position_change 是否允许列类型变更 check_column_type_change
DML
INSERT
检查项相关配置项表是否存在 列必须存在 不为 null 的列,如果插入的值是 null,报错
INSERT SELECT
检查项相关配置项涉及的所有库 / 表 / 字段必须存在 必须指定插入列表,也就是要写入哪些列,如 insert into t (id,id2) select hellip;check_insert_field 是否允许 select *enable_select_star 必须有 where 条件 check_dml_where 不能有 order by rand 子句 enable_orderby_rand 使用 explain 获取预估行数或 select count 获取真实行数调用选项 real_row_count,explain_rule
UPDATE/DELETE
检查项相关配置项表必须存在 必须有 where 条件 check_dml_where 不能有 order by 语句 check_dml_orderby 影响行数大于 10000 条,则报警(数目可配置)max_update_rows 对 WHERE 条件这个表达式做简单检查,具体包括什么不一一指定 多表更新、删除时,每个表及涉及字段必须要存在 update 多表关联时, 如果 set 未指定表前缀, 自动判断 多表时判断未指明表前缀的列是否有歧义 update 多表关联时, 如果 set 了多个表的字段, 同样支持回滚语句生成 使用 explain 获取预估行数或 select count 获取真实行数调用选项 realRowCount,explain_rulemysql 版本在 5.6 之前时, 自动将语句转换为 select 做 explain 设置数据库 sql_safe_updates 参数 sql_safe_updates 多表关联时, 审核 join 语句是否包含 on 子句 check_dml_where 条件中的列是否存在隐式类型转换 check_implicit_type_conversionupdate set 判断 set 使用了逗号还是 and 分隔
四、使用感受
简单测试了一下 goinception,整体体验下来感觉还是很不错的,相比于之前的 inception 来说,goinception 有如下几个优点:
安装部署非常简单,官方直接提供了二进制包
集成了 gh-ost 无需另外安装,同时也提供 pt-osc 方式执行 DDL
提供了基于表大小的 ALTER 执行选项,并且可配置大小
支持关联更新,inception 本身是不支持的
提供了更加丰富的审核规则选项,并且是基于 MySQL5.7 的,相比于 inception 来说支持度更好
长期稳定更新,从 github 上的 commit 记录看作者还是更新得很勤奋的
更快的备份功能,之前使用 inception 的时候经常会碰到需要备份的 binlog 过大,网络超时的现象(从文档上看 goinception 使用的批量备份,据说速度能快很多)
五、系统集成
到这里,我们已经基本上选择 goinception 作为我们的审核引擎了,那么如何集成到现有的自动化系统中是个问题。
先说一下我们公司的情况,我们公司有流程中心,也就是开发会在上面选择库,提交 SQL,DBA 收到工单以后人工审核,手工执行。
在审核过程中,对于 DBA 来说,肉眼审核也太过于辛酸了,手工执行一不小心就是背黑锅。所以,基于 goinception,我这边提供了几个 restful 的接口,分别如下:
db 信息接口,根据用户权限,返回该用户所能看到的 dbname
SQL 检查接口,用户提交 SQL,调用 goinception 进行审核,审核通过以后到 DBA
SQL 执行接口,DBA 选择执行的实例,调用 goinception 进行 SQL 执行,执行完成以后通知开发工单完成
开发查看工单,可以下载对应的回滚 SQL
感谢各位的阅读,以上就是“如何理解 SQL 审核利器 goinception”的内容了,经过本文的学习后,相信大家对如何理解 SQL 审核利器 goinception 这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!