vlambda博客
学习文章列表

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。

  1. GO111MODULE=off,禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。
  2. GO111MODULE=on,启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖,将依赖下载至%GOPATH%/pkg/mod/ 目录下。
  3. 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项目的依赖描述文件,该文件主要用来描述两个事情:

  1. 当前项目名(module)是什么。每个项目都应该设置一个名称,当前项目中的包(package)可以使用该名称进行相互调用。
  2. 当前项目依赖的第三方包名称。

看下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

mysql之语句审核工具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





👇 点点下面的小咔片再走吧,谢谢老板!!!