mysql之语句审核工具goInception(一)
最近在看mysql的审核工具goInception。该工具通过对执行SQL的语法解析,返回基于自定义规则的审核结果,并提供执行和备份及生成回滚语句的功能。
此篇是对该工具学习过程的一个记录。
goInception是作者基于inception重构的golang版本,因为对golang不是很了解。所以现学现卖,先从golang的基础知识看起,权当学习笔记了。
go module
什么是go module
go module是Go1.11版本之后官方推出的版本管理工具,并且从Go1.13版本开始,go module将是Go语言默认的依赖管理工具。
go module可以将某个项目下的所有依赖整理成一个go.mod文件,里面写入了依赖的版本等。
怎么开启go module
go modules默认是不开启的。要启用go module支持首先要设置环境变量GO111MODULE,通过它可以开启或关闭模块支持,它有三个可选值:off、on、auto,默认值是auto。
-
GO111MODULE=off,禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。 -
GO111MODULE=on,启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖,将依赖下载至%GOPATH%/pkg/mod/ 目录下。 -
GO111MODULE=auto,当项目在$GOPATH/src外且项目根目录有go.mod文件时,开启模块支持。
启用go module,for maxos:
echo "export GO111MODULE=on" >> ~/.bash_profile
echo "export GOPROXY=https://goproxy.cn" >> ~/.bash_profile
source ~/.bash_profile
goproxy: 代理。Go的1.11 版本以后可以设置环境变量GOPROXY,来设置代理,以加速下载。
go.mod文件
go.mod是Go项目的依赖描述文件,该文件主要用来描述两个事情:
-
当前项目名(module)是什么。每个项目都应该设置一个名称,当前项目中的包(package)可以使用该名称进行相互调用。 -
当前项目依赖的第三方包名称。
看下goInception的go.mod文件。
module github.com/hanchuanchuan/goInception
go 1.12
replace gopkg.in/gcfg.v1 => github.com/hanchuanchuan/gcfg.v1 v0.0.0-20190302111942-77c0f3dcc0b3
replace vitess.io/vitess => github.com/vitessio/vitess v3.0.0-rc.3+incompatible
replace github.com/go-sql-driver/mysql => github.com/go-sql-driver/mysql v1.4.1-0.20191022112324-6ea7374bc1b0
// replace github.com/hanchuanchuan/gh-ost => ../gh-ost
require (
github.com/BurntSushi/toml v0.3.1
github.com/CorgiMan/json2 v0.0.0-20150213135156-e72957aba209
...
gopkg.in/natefinch/lumberjack.v2 v2.0.0
vitess.io/vitess v2.1.1+incompatible
)
其中:
-
module用来定义项目名 -
require用来定义依赖包及版本 -
indirect表示间接引用 -
replace: 替换,比如一种情况:在国内访问golang.org/x的各个包都需要翻墙,你可以在go.mod中使用replace替换成github上对应的库。
go modules常用命令
go mod init: 初始化modules
go mod download: 下载依赖的module到本地cache
go mod edit: 编辑go.mod文件,选项有-json、-require和-exclude,可以使用帮助go help mod edit
go mod graph: 以文本模式打印模块需求图
go mod tidy: 检查,删除错误或者不使用的modules,以及添加缺失的模块
go mod vendor: 生成vendor目录,将依赖复制到vendor目录下面
go mod verify: 验证依赖是否正确
go mod why: 解释为什么需要依赖
go list -m: 查看主模块的路径
go list -m -f={{.Dir}}: 查看主模块的根目录
go list -m all: 查看当前的依赖和版本信息
本地运行goInception
使用源码编译执行
# 下载源码
git clone https://github.com/hanchuanchuan/goInception
# 切换到项目根目录。
cd goInception
#该命令会在当前文件夹下生成名为goInception的可执行文件。
go build -o goInception tidb-server/main.go
#执行
./goInception -config=config/config.toml
goLand调试goInception
inception的使用
启动了goInception类似于启动了一个mysql服务,可以连接到服务端口,执行SQL语句。实现了mysql协议驱动的语言均可访问,访问方式和mysql一致。
我可以使用mysql官方提供的客户端访问它,其默认使用的端口是4000。
mysql -h127.0.0.1 -P4000
sql的审核和执行。
/*--user=root;--password=root;--host=127.0.0.1;--check=1;--port=3306;*/
inception_magic_start;
use testdb;
create table t1(id int primary key);
inception_magic_commit;
使用python调用
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymysql
import prettytable as pt
tb = pt.PrettyTable()
sql = '''/*--user=root;--password=root;--host=127.0.0.1;--check=1;--port=3306;*/
inception_magic_start;
use test_inc;
create table t1(id int primary key,c1 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)
执行结果:
+----------+---------+-------------+-----------------+--------------------------------------------------+--------------------------------------------+---------------+--------------+---------------+--------------+---------+-------------+
| order_id | stage | error_level | stage_status | error_message | sql | affected_rows | sequence | backup_dbname | execute_time | sqlsha1 | backup_time |
+----------+---------+-------------+-----------------+--------------------------------------------------+--------------------------------------------+---------------+--------------+---------------+--------------+---------+-------------+
| 1 | CHECKED | 0 | Audit Completed | None | use testdb | 0 | 0_0_00000000 | None | 0 | None | 0 |
| 2 | CHECKED | 0 | Audit Completed | None | create table t1(id int primary key,c1 int) | 0 | 0_0_00000001 | None | 0 | None | 0 |
| 3 | CHECKED | 2 | Audit Completed | Column 't1.c2' not existed. | insert into t1(id,c1,c2) values(1,1,1) | 1 | 0_0_00000002 | None | 0 | None | 0 |
| | | | | Column count doesn't match value count at row 1. | | | | | | | |
+----------+---------+-------------+-----------------+--------------------------------------------------+--------------------------------------------+---------------+--------------+---------------+--------------+---------+-------------+
可以看到有审核失败sql, t1表中没有c2字段,插入语句check失败。
其他
我查了下pg的自动审核工具,貌似没有找到开源的工具(也许是我没找到..如果大家有知道的话,欢迎给我留言告知我下),不过,找到了一篇基于hook来做的SQL规范审核插件的文章,见:https://mp.weixin.qq.com/s/Ow9KKdVKtYmfXIFPkEsSLw,有兴趣的可以看下。
另外,本篇只是简单地介绍了goInception的基础使用,有关它的更多内容,后面有时间再继续。
参考:
https://blog.csdn.net/qq_42403866/article/details/93654421
https://segmentfault.com/a/1190000022868683
https://mp.weixin.qq.com/s/Ow9KKdVKtYmfXIFPkEsSLw
👇 点点下面的小咔片再走吧,谢谢老板!!!