概述

使用过inception的人对sql审核这块获取都比较熟悉,作为DBA,审核SQL是日常工作中的很重要的一块内容,审核好SQL对于后期项目以及数据库维护上起着至关重要的作用。

而goInception是一个集审核、执行、备份及生成回滚语句于一身的MySQL运维工具, 通过对执行SQL的语法解析,返回基于自定义规则的审核结果,并提供执行和备份及生成回滚语句的功能

官网:https://github.com/hanchuanchuan/goInception

相关的详细文档:https://hanchuanchuan.github.io/goInception/


一、简介

goInception基于TiDB的语法解析器,和业内有名的inpcetion审核工具重构。

同时提供Archery 查询支持(MySQL/MsSQL/Redis/PostgreSQL)、MySQL优化(SQLAdvisor|SOAR|SQLTuning)、慢日志管理、表结构对比、会话管理、阿里云RDS管理等。

从架构上来说,goinception简直跟inception一模一样,SQL提交到goinception,goinception连接到线上MySQL进行审核。执行的时候也是连接到线上MySQL进行执行,goinception提供了备份、回滚的功能,意思就是能够监听执行期间的binlog,基于binlog生成反向的回滚SQL。

基于polardb设计和实现小型数据库(基于goinception搭建DBA审核平台)(1)

goInception延用inception的使用方式,在审核的sql开始前添加注释来指定远端服务器,并在sql的前后添加特殊标识以区分待审核语句,示例如下:

/*--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;

>>>对比原生inception的优势

1) 对开源工具gh-ost的支持,可以不再使用触发器

2) 支持DML和DDL混合提交

3) 批量备份速度远远超过原生inception

4) 因为是go程序,所以不依赖于环境,执行执行即可,原生inception有一些包的问题

5) 支持某些原生incetpion不支持的语法,比如insert select这种带select关键字


二、安装部署

1、下载安装

1.1、二进制安装

下载地址:https://github.com/hanchuanchuan/goInception/releases下载好对应版本的goinception,直接解压即可,解压完成以后在config/config.toml.default有一个默认的配置文件

mkdir -p /usr/local/goinception wget https://github.com/hanchuanchuan/goInception/releases/download/v1.2.3/goInception-linux-amd64-v1.2.3.tar.gz tar -xvf goInception-linux-amd64-v1.2.3.tar.gz -C /usr/local/goinception chown -R root:root /usr/local/goinception && chmod -R 755 /usr/local/goinception

1.2、源码编译

git clone https://gitee.com/hanchuanchuan/goInception.git cd goInception make parser go build -o goInception tidb-server/main.go

1.3、docker部署

docker pull hanchuanchuan/goinception

基于polardb设计和实现小型数据库(基于goinception搭建DBA审核平台)(2)

2、修改配置文件(config.toml)

#· cat /usr/local/goinception/config/config.toml ================================================================================ # IP地址 host = "0.0.0.0" # 端口 port = 8888 # TiDB数据库目录 path = "/tmp/tidb" # 忽略终端连接断开信号 ignore_sighup = true [log] # 日志级别: debug, info, warn, error, fatal. level = "info" # 日志格式, one of json, text, console. format = "text" # 禁用时间戳输出 disable-timestamp = false # 日志文件 [log.file] # 日志文件名 filename = "/usr/local/goinception/goinception.log" # 日志文件的最大上限(MB) max-size = 1000 # Max日志文件的保存天数,默认值 `0`,即不清理 max-days = 7 # 要保留的最大旧日志文件数,默认值 `0`,即不清理 max-backups = 3 # 日志轮询,默认值 `true`,即开启 log-rotate = true [inc] backup_host = "127.0.0.1" backup_port = 3306 backup_user = "root" backup_password = "password" enable_nullable = true enable_drop_table = false enable_set_engine = true enable_change_column = true check_timestamp_count = true check_table_comment = false check_column_comment = false # 审核列类型变更 check_column_type_change = true # 表名/索引名前缀 index_prefix = "idx_" uniq_index_prefix = "uniq_" table_prefix = "" # explain判断受影响行数时使用的规则, 默认值"first" # 可选值: "first", "max" # "first": 使用第一行的explain结果作为受影响行数 # "max": 使用explain结果中的最大值作为受影响行数 explain_rule = "first" # 安全更新是否开启(mysql自身的功能). # -1 表示不做操作,基于远端数据库 [默认值] # 0 表示关闭安全更新 # 1 表示开启安全更新 sql_safe_updates = 1 support_charset = "utf8,utf8mb4" support_engine = "innodb" #lang = "en-US" lang = "zh-CN" # 全量日志 general_log = false [osc] # 用来设置在arkit返回结果集中,对于原来OSC在执行过程的标准输出信息是不是要打印到结果集对应的错误信息列中, # 如果设置为1,就不打印,如果设置为0,就打印。而如果出现了错误,则都会打印。默认值:OFF osc_print_none = false # 对应参数pt-online-schema-change中的参数--print。默认值:OFF osc_print_sql = false # 全局的OSC开关,默认是打开的,如果想要关闭则设置为OFF,这样就会直接修改。默认值:OFF osc_on = false # 这个参数实际上是一个OSC开关,如果设置为0,则全部ALTER语句都使用OSC方式, # 如果设置为非0,则当这个表占用空间大小大于这个值时才使用OSC方式。 # 单位为M,这个表大小的计算方式是通过语句 # select (DATA_LENGTH INDEX_LENGTH)/1024/1024 from information_schema.tables # where table_schema = 'dbname' and table_name = 'tablename' 来实现的。默认值:16 # [0-1048576] osc_min_table_size = 1024 # 对应参数pt-online-schema-change中的参数alter-foreign-keys-method,具体意义可以参考OSC官方手册。默认值:none # [auto | none | rebuild_constraints | drop_swap] osc_alter_foreign_keys_method = "none" # 对应参数pt-online-schema-change中的参数recursion_method,具体意义可以参考OSC官方手册。默认值:processlist # [processlist | hosts | none] osc_recursion_method = "processlist" # 对应参数pt-online-schema-change中的参数--max-lag。默认值:3 osc_max_lag = 3 # 类似--max-lag,检查集群暂停流量控制所花费的平均时间(仅适用于PXC 5.6及以上版本,会自动检测) osc_max_flow_ctl = -1 # 对应参数pt-online-schema-change中的参数 --set-vars lock_wait_timeout=? osc_lock_wait_timeout = 60 # 对应参数pt-online-schema-change中的参数--[no]check-alter。默认值:ON osc_check_alter = true # 对应参数pt-online-schema-change中的参数--[no]check-replication-filters。默认值:ON osc_check_replication_filters = true # 对应参数pt-online-schema-change中的参数--[no]drop-old-table。默认值:ON osc_drop_old_table = true # 对应参数pt-online-schema-change中的参数--[no]drop-new-table。默认值:ON osc_drop_new_table = true # 对应参数pt-online-schema-change中的参数--max-load中的thread_running部分。默认值:80 osc_max_thread_running = 80 # 对应参数pt-online-schema-change中的参数--max-load中的thread_connected部分。默认值:1000 osc_max_thread_connected = 1000 # 对应参数pt-online-schema-change中的参数--critical-load中的thread_running部分。默认值:80 osc_critical_thread_running = 80 # 对应参数pt-online-schema-change中的参数--critical-load中的thread_connected部分。默认值:1000 osc_critical_thread_connected = 1000 # 对应参数pt-online-schema-change中的参数--chunk-time。默认值:1 osc_chunk_time = 1.0 # 对应参数pt-online-schema-change中的参数--chunk-size-limit。默认值:4 osc_chunk_size_limit = 4 # 对应参数pt-online-schema-change中的参数--chunk-size。默认值:1000 osc_chunk_size = 1000 # 对应参数pt-online-schema-change中的参数--check-interval,意义是Sleep time between checks for --max-lag。默认值:5 osc_check_interval = 5 osc_bin_dir = "/usr/local/bin" [ghost] ghost_on = true ghost_allow_on_master = true ghost_assume_rbr = true ghost_chunk_size = 10000 ghost_concurrent_rowcount = true ghost_cut_over = "atomic" ghost_cut_over_lock_timeout_seconds = 3 ghost_default_retries = 60 ghost_heartbeat_interval_millis = 500 ghost_max_lag_millis = 1500 ghost_approve_renamed_columns = true ghost_exponential_backoff_max_interval = 64 ghost_dml_batch_size = 100 ghost_ok_to_drop_table = true ghost_skip_foreign_key_checks = true [inc_level] er_alter_table_once = 1 er_auto_incr_id_warning = 1 er_autoinc_unsigned = 1 er_blob_cant_have_default = 1 er_cant_change_column = 1 er_cant_change_column_position = 1 er_cant_set_charset = 1 er_cant_set_collation = 1 er_cant_set_engine = 1 er_change_column_type = 1 er_change_too_much_rows = 1 er_char_to_varchar_len = 1 er_charset_on_column = 1 er_column_have_no_comment = 1 er_datetime_default = 1 er_foreign_key = 2 er_ident_use_keyword = 1 er_implicit_type_conversion = 1 er_inc_init_err = 1 er_index_name_idx_prefix = 1 er_index_name_uniq_prefix = 1 er_insert_too_much_rows = 1 er_invalid_data_type = 1 er_invalid_ident = 1 er_join_no_on_condition = 1 er_json_type_support = 2 er_must_have_columns = 1 er_columns_must_have_index = 1 er_columns_must_have_index_type_err = 1 er_no_where_condition = 1 er_not_allowed_nullable = 1 er_ordery_by_rand = 1 er_partition_not_allowed = 1 er_pk_cols_not_int = 1 er_pk_too_many_parts = 1 er_select_only_star = 1 er_set_data_type_int_bigint = 2 er_table_charset_must_null = 1 er_table_charset_must_utf8 = 1 er_table_must_have_comment = 1 er_table_must_have_pk = 1 er_table_prefix = 1 er_text_not_nullable_error = 1 er_timestamp_default = 1 er_too_many_key_parts = 1 er_too_many_keys = 1 er_too_much_auto_datetime_cols = 2 er_too_much_auto_timestamp_cols = 2 er_udpate_too_much_rows = 1 er_use_enum = 1 er_use_text_or_blob = 2 er_with_default_add_column = 1 er_with_insert_field = 1 er_with_limit_condition = 1 er_with_orderby_condition = 1 er_wrong_and_expr = 1

3、启动goinception

cd /usr/local/goinception ./goInception -config=config/config.toml &

基于polardb设计和实现小型数据库(基于goinception搭建DBA审核平台)(3)


三、goinception测试

1、安装依赖

pip install pymysql prettytable

2、测试脚本(t_goinception.py)

import pymysql import prettytable as pt tb = pt.PrettyTable() sql = '''/*--user=root;--password=password;--host=127.0.0.1;--check=0;--port=3306;--execute=1;--backup=1;*/ inception_magic_start; use go; 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=8888, 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)

3、测试结果

基于polardb设计和实现小型数据库(基于goinception搭建DBA审核平台)(4)


五、goInception的三个阶段

goInception内部会进行三个阶段的操作,分别是审核阶段,执行阶段和备份阶段。

1、审核阶段

1)goInception在收到sql语句后,先会解析注释中的远程数据库配置,并建立连接

2)如果开启了备份功能,则会检查binlog日志是否开启(log_bin=ON)

3)判断语法开始位置,必须以 inception_magic_start 语法开始

4)开始逐行解析,并进行语法树解析,失败时返回

5)解析到use dbtest,会通过show databases判断数据库是否存在

6)解析到create table table1...,接下来进行建表的校验

7)解析到insert into table1 ...,接下来进行insert的校验

8)解析到inception_magic_commit,判断所有的审核是否成功,如果有错误时,直接返回,而有警告时会判断是否开启了忽略警告的参数,以判断是否进行下一步

2、执行阶段

接下来继续说明执行阶段:

1)在执行阶段,DDL语句和DML语句走不同的逻辑,其中DML通过binlog解析实现回滚,而DDL语句根据语法树规则直接生成逆向SQL即可

2)DML:在开始执行和执行完成时,记录binlog位置

3)DDL和DML:开始执行,并在执行失败时记录失败原因并结束执行操作,成功时记录受影响行数

4)执行中可能想要执行KILL以中止执行

3、备份阶段

1)到达备份阶段有两种情况,可能执行成功也可能部分成功了,此时会进行判断,只备份执行成功的语句

2)DDL的备份是保存自动生成的逆向SQL语句

3)DML的备份是根据执行前后记录的binlog位置和线程号,模拟从库的形式获取binlog信息,并做事件解析

4)解析binlog日志要求binlog格式必须为ROW模式,该模式也会有备份前检查和自动设置,因此可能需要SUPER权限

5)在解析过binlog后,会生成逆向的SQL语句,并异步批量写入备份库

6)在回滚语句写入完成后,所有操作执行完成,并返回结果给客户端。


后面会分享更多devops和DBA方面内容,感兴趣的朋友可以关注下!

基于polardb设计和实现小型数据库(基于goinception搭建DBA审核平台)(5)

,