做者:王少鵬
愛可生 DBA 團隊成員,負責項目數據庫平常問題處理及公司 DMP 平臺問題處理,對數據庫有強烈的興趣。認爲不會游泳的廚師毫不是一個好數據庫工程師。
本文來源:原創投稿
*愛可生開源社區出品,原創內容未經受權不得隨意使用,轉載請聯繫小編並註明來源。mysql
某日某公司的測試數據庫突發告警!sql
故障初步定位極可能是新來的幾位實習生沒有遵照運維規範,誤操做(沒加 where 條件)刪表致使服務異常,目前還沒確認操做用戶身份。數據庫
DELETE TABLE XXXXX;( 環境 autocommit=1 ,沒有手動開啓事務 )
儘管測試環境不影響線上應用,但影響了新功能開發進度,暴露出運維管理上的漏洞。app
經過以上案例思考,MySQL 自己並無操做審計的功能,又如何根據現有的功能進行行爲分析,避免悲劇再次發生?運維
文章整理了運維時經常使用的定位 MySQL 操做用戶方法,幫你快速查看用戶行爲記錄。測試
init_connect 參數的功能:當用戶在客戶端鏈接 MySQL 時,隱式執行的一條自定義的 SQL 語句(參數值)。線程
注意:3d
mysql> show variables like 'init_connect'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | init_connect | | +---------------+-------+ 1 row in set (0.00 sec) mysql> set global init_connect='insert into auditdb.accesslog(connectionID,ConnUser,MatchUser,LoginTime) values(connection_id(),user(),current_user(),now());'; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'init_connect'; +---------------+-------------------------------------------------------------------------------------------------------------------------------+ | Variable_name | Value | +---------------+-------------------------------------------------------------------------------------------------------------------------------+ | init_connect | insert into auditd.accesslog(connectionID,ConnUser,MatchUser,LoginTime) values(connection_id(),user(),current_user(),now()); | +---------------+-------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
既然是要 insert 一條數據,那是否是這個普通用戶要對這張表擁有 insert 權限呢?日誌
答案是確定的。code
mysql> create database auditdb charset utf8mb4; Query OK, 1 row affected (0.01 sec) mysql> create table auditdb.accesslog (id int (10) unsigned not null primary key auto_increment, Connectionid int(10) unsigned,ConnUser varchar (30) not null default '', MatchUser varchar (30) not null default '', Logintime datetime); Query OK, 0 rows affected (0.02 sec)
對全部用戶都賦予 insert 權限
mysql> grant insert on auditdb.accesslog to mindoc@'%'; Query OK, 0 rows affected (0.00 sec)
注意:
此方法須要給數據庫全部用戶都對 auditdb.accesslog 授寫權限,不然插入用戶信息會失敗;
不要受權 update 、delete 等權限,不然普通用戶登陸 MySQL 能夠手動刪除他鏈接的信息。
[root@db ~]# mysql -u mindoc -p -h 172.18.1.76 Enter password: mysql> create table temp(id int,name varchar(32)); Query OK, 0 rows affected (0.03 sec) mysql> insert into temp values(1,'aa'); Query OK, 1 row affected (0.01 sec) mysql> insert into temp values(2,'aa'); Query OK, 1 row affected (0.01 sec) mysql> insert into temp values(3,'aa'); Query OK, 1 row affected (0.01 sec) mysql> delete from temp; Query OK, 3 rows affected (0.01 sec)
此時數據已經被刪除了,你的應用程序應該會報錯或開始告警。經過檢查應用日誌,可大體推斷時間範圍。
[root@db ~]# mysqlbinlog -v --base64-output=decode-rows /usr/local/mysql-5.7.20/binlog/mysql-bin.000002 > audit.log
查看危險語句的進程 ID 號( 在解析後的 binlog 文件搜索危險命令關鍵字 )
經過執行的 delete 語句與大概執行時間,肯定是哪一個用戶鏈接( thread_id=130 )
[root@db ~]# tail -35 audit.log # at 49003 #191120 13:02:18 server id 76 end_log_pos 49080 CRC32 0x73dc1dda Query thread_id=130 exec_time=0 error_code=0 SET TIMESTAMP=1574226138/*!*/; BEGIN /*!*/; # at 49080 #191120 13:02:18 server id 76 end_log_pos 49135 CRC32 0x360e7fe4 Table_map: `mindoc_db`.`temp` mapped to number 249 # at 49135 #191120 13:02:18 server id 76 end_log_pos 49194 CRC32 0xbbf0d78f Delete_rows: table id 249 flags: STMT_END_F BINLOG ' 2sjUXRNMAAAANwAAAO+/AAAAAPkAAAAAAAEACW1pbmRvY19kYgAEdGVtcAACAw8CgAAD5H8ONg== 2sjUXSBMAAAAOwAAACrAAAAAAPkAAAAAAAEAAgAC//wBAAAAAmFh/AIAAAACYWH8AwAAAAJhYY/X 8Ls= '/*!*/; ### DELETE FROM `mindoc_db`.`temp` ### WHERE ### @1=1 ### @2='aa' ### DELETE FROM `mindoc_db`.`temp` ### WHERE ### @1=2 ### @2='aa' ### DELETE FROM `mindoc_db`.`temp` ### WHERE ### @1=3 ### @2='aa' # at 49194 #191120 13:02:18 server id 76 end_log_pos 49225 CRC32 0x277ece0b Xid = 23721 COMMIT/*!*/; SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/; DELIMITER ; # End of log file /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
能夠看到線程 threadid=130,而且時間也是 2019-11-20 中午一點左右。能夠肯定就是 mindoc@’%’ 用戶操做的 delete 語句。
經過 ConnUser 字段能夠看到是 172.18.1.99 這個地址使用 mindoc@’%’ 用戶鏈接的 MySQL 數據庫。
mysql> select * from auditdb.accesslog where Connectionid=130; +----+--------------+--------------------+-----------+---------------------+ | id | Connectionid | ConnUser | MatchUser | Logintime | +----+--------------+--------------------+-----------+---------------------+ | 1 | 130 | mindoc@172.18.1.99 | mindoc@% | 2019-11-20 12:59:21 | +----+--------------+--------------------+-----------+---------------------+ 1 row in set (0.00 sec)
而後你就能夠去找誰使用的 mindoc@% 用戶了,還有定位下 172.18.1.99 這個 IP 地址誰在使用。
完成了經過行爲定位用戶的操做。