做者:黃超python
杏仁運維工程師,關注容器技術和自動化運維。mysql
最近打算作一個 MySQL 的數據庫運維平臺。這裏面有一個很是重要的功能就是 SQL 的審覈,若是徹底靠人工去實現就不必作成一個平臺了。正沒頭緒如何去實現的時候,google 了一下,看下有沒有現成的開源方案。果不其然,github 上發現一個『去哪兒網』開源的一個數據庫運維工具 Inception, 它是一個集審覈、執行、備份及生成回滾語句於一身的 MySQL 自動化運維工具。linux
Inception 的架構圖以下圖所示,簡單來講,Inception 就是一個 MySQL 的代理,可以幫助你審覈 SQL,執行 SQL,備份 SQL 影響的記錄。Inception 是一個 C/S 的軟件架構。咱們能夠經過原生的 MySQL 客戶端 去鏈接,也能夠經過遠程的接口去鏈接,目前執行只支持經過C/C++接口、Python接口來對Inception訪問。git
我安裝的環境github
OS: Ubuntu 16.04.2 LTSweb
下載 bison: 版本最好是2.6以前的(Ubuntu 16.04.2 LTS 版本下安裝的是 bison-2.5.1),最新的可能會有問題,下載以後,須要本身編譯源碼來安裝,具體安裝方法,能夠參數網上的一些說明。sql
cmake 安裝:``apt-get install cmake`數據庫
ncurses 安裝:apt-get install libncurses5-dev
bash
安裝openssl:apt-get install libssl-dev
服務器
安裝 g++:sudo apt-get install g++
安裝 m4: apt-get install m4
git clone https://github.com/mysql-inception/inception.git
sh inception_build.sh debug [linux] (若是不指定就是linux平臺,而若是要指定是Xcode,就後面指定Xcode)
複製代碼
可執行文件在 debug/sql/Debug/
目錄下面(不一樣平臺有可能不相同)。
建立一個配置文件 inc.cnf, 裏面主要是配置 Inception 啓動的端口,SQL 審覈的策略,備份數據庫的配置等等,更多可參考官方文檔。
[inception]
general_log=1
general_log_file=inception.log
port=6669 # Inception 的監聽的端口
socket=/tmp/inc.socket
character-set-client-handshake=0
character-set-server=utf8
inception_remote_system_password=root # 備份數據庫密碼
inception_remote_system_user=wzf1 # 備份數據庫用戶名
inception_remote_backup_port=3306 # 備份數據庫端口
inception_remote_backup_host=127.0.0.1 # 備份數據庫地址
inception_support_charset=utf8mb4
inception_enable_nullable=0
inception_check_primary_key=1
inception_check_column_comment=1
inception_check_table_comment=1
inception_osc_min_table_size=1
inception_osc_bin_dir=/data/temp
inception_osc_chunk_time=0.1
inception_enable_blob_type=1
inception_check_column_default_value=1
複製代碼
啓動
./Inception --defaults-file=inc.cnf
複製代碼
訪問
mysql -uroot -h127.0.0.1 -P6669
複製代碼
#!/usr/bin/python
#-\*-coding: utf-8-\*-
import MySQLdb
sql='/*--user=username;--password=password;--host=127.0.0.1;--execute=1;--port=3306;*/\ inception_magic_start;\ use mysql;\ CREATE TABLE adaptive_office(id int);\ inception_magic_commit;'
try:
conn=MySQLdb.connect(host='127.0.0.1',user='',passwd='',db='',port=9998)
cur=conn.cursor()
ret=cur.execute(sql)
result=cur.fetchall()
num_fields = len(cur.description)
field_names = [i[0] for i in cur.description]
print field_names
for row in result:
print row[0], "|",row[1],"|",row[2],"|",row[3],"|",row[4],"|",
row[5],"|",row[6],"|",row[7],"|",row[8],"|",row[9],"|",row[10]
cur.close()
conn.close()
except MySQLdb.Error,e:
print "Mysql Error %d: %s" % (e.args[0], e.args[1])
複製代碼
經過 Inception 對語句進行審覈時,必需要告訴 Inception 這些語句對應的數據庫地址、數據庫端口以及
Inception 鏈接數據庫時使用的用戶名、密碼等信息,而不能簡單的只是執行一條 sql 語句,因此必需要經過某種方式將這些信息傳達給 Inception。
鏈接信息放在 /* ... */ 的註釋中,真正的 SQL 語句則包括在 inception_magic_start
與 inception_magic_commit
:
審覈的規範見官方文檔,有些規範是可配置的,可根據本身公司的規範在 Inception 的配置文件中配置。
注意下,官方說是支持 DDL,DML 語句的,可是並不支持 SELECT 查詢。
...
inception_magic_start;
use mysql;
CREATE TABLE adaptive_office(id int);
inception_magic_commit;
...
複製代碼
返回結果, 可見是每一條 SQL 就會返回一個可執行的結果,errlevel 非 0 時表示執行失敗,下面所示中的第二條 SQL 語句 Audit completed(審覈完成) 可是不符合建表的規範,更多關於返回結果的說明可見官方文檔:
'ID', 'stage', 'errlevel', 'stagestatus', 'errormessage', 'SQL', 'Affected_rows', 'sequence', 'backup_dbname', 'execute_time', 'sqlsha1'
1 | CHECKED | 0 | Audit completed | None | use inception_test | 0 | '0_0_0' | None | 0 |
2 | CHECKED | 1 | Audit completed | Set engine to innodb for table 'adaptive_office'.
Set charset to one of 'utf8mb4' for table 'adaptive_office'.
Set comments for table 'adaptive_office'.
Column 'id' in table 'adaptive_office' have no comments.
Column 'id' in table 'adaptive_office' is not allowed to been nullable.
Set Default value for column 'id' in table 'adaptive_office'
Set a primary key for table 'adaptive_office'. | CREATE TABLE adaptive_office(id int) | 0 | '0_0_1' | 10_10_1_67_1028_inception_test | 0 |
複製代碼
線上服務器必需要打開 binlog,否則不會備份及生成回滾語句。
參數 binlog_format
必需要設置爲 mixed 或者 row 模式,經過語句:set global binlog_format=mixed/row
來設置,若是是 statement 模式,則不作備份及回滾語句的生成。
被影響的行中必須存在主鍵,由於回滾語句的 WHERE 條件就是主鍵。好比,我插入一條數據並返回主鍵 id=1, 那麼相應的它就會反向生成一個刪除語句 (WHERE 的條件就是主鍵) DELETE FROM xx WHERE id = 1
。
Inception 在作 DML 操做時具備備份功能(默認開啓,可經過在執行 SQL 中註釋文件中指定 --disable-remote-backup
),它會將全部當前語句修改的行備份下來,存儲到一個指定的備份庫中, 備份庫經過配置 Inception 參數來指定。
關於備份數據庫的命名方式,備份機器的庫名組成是由線上機器的 IP 地址的點換成下劃線,再加上端口號,再加上庫名三部分,這三部分也是經過下劃線鏈接起來的。例如:我執行 DML 操做的數據庫地址是 192.168.1.1, 端口是 3306, 庫名是 inceptiondb, 則在備份數據庫中表名爲:192_168_1_1_3306_inceptiondb
。
好比,我有一個 inception_test 庫,其中有一張 userinfo 表,就兩個字段:
/*--user=root;--password=xxx;--host=1.1.1.1;--execute=1;--port=3306;--sleep=0;--enable-remote-backup;*/\
inception_magic_start;\
use inception_test; \
insert into userinfo(`username`) values("test");\
inception_magic_commit;
複製代碼
返回的結果以下, 能夠看到已經執行成功而且備份成功了:
2 | EXECUTED | 0 | Execute Successfully
Backup successfully | None | insert into userinfo(`username`) values("test") | 1 | '1533716166_25519001_1' | 1_1_1_1_3306_inception_test | 0.060 |
複製代碼
查看下備份數據庫中的 1_1_1_1_3306_inception_test
庫 userinfo 表的結果, 根據 INSERT 的語句相應地生成了一條 DELETE 語句:
DELETE FROM `inception_test`.`userinfo` WHERE id=4;
複製代碼
那麼,我須要若是正確地找到回滾的語句呢? 能夠查看下備份庫 1_1_1_1_3306_inception_test
中 userinfo 的表結構:
主要有兩個字段:
rollback_statement text: 生成修改的回滾語句。
opid_time varchar(50): 這個列存儲的是的被執行的 SQL 語句在執行時的一個序列號,這個序列號由三部分組成:timestamp(int 值,是語句被執行的時間點) + 線上服務器執行時所產生的 thread_id + 當前這條語句在全部被執行的語句塊中的一個序號組成。可見上面的結果:1533716166_25519001_1 , 這個序列號同時也會出如今執行返回的結果中,全部須要回滾就是根據這個序列號去備份表中查詢回滾的 SQL 語句。
更多說明,請參考官方文檔中的備份功能說明。
有了這麼好用的工具,基於這個爲基礎,咱們經過一個 WEB 應用作一個權限審批管理等功能,一個數據庫運維平臺就能夠實現了,真的須要本身去寫嗎?我有發現了一個基於 Inception 實現的一個數據庫運維平臺 Yearning。
數據庫自動化運維平臺--自助 DML(blog.csdn.net/liuhanran/a…)
去哪網數據庫自動化運維工具 inception(mysql-inception.github.io/inception-d…)
DEVOPS 運維開發系列三:在 MySQL DML 自助服務中集成使用 Inception 提供 SQL 的語法檢查和錯誤信息提示(blog.csdn.net/watermelonb…)
基於 Inception 的可視化 web 端 sql 審覈平臺(github.com/cookieY/Yea…)