技術分享 | 是誰刪了表?

做者:王少鵬
愛可生 DBA 團隊成員,負責項目數據庫平常問題處理及公司 DMP 平臺問題處理,對數據庫有強烈的興趣。認爲不會游泳的廚師毫不是一個好數據庫工程師。
本文來源:原創投稿
*愛可生開源社區出品,原創內容未經受權不得隨意使用,轉載請聯繫小編並註明來源。mysql


背景

某日某公司的測試數據庫突發告警!sql

故障初步定位極可能是新來的幾位實習生沒有遵照運維規範,誤操做(沒加 where 條件)刪表致使服務異常,目前還沒確認操做用戶身份。數據庫

DELETE TABLE XXXXX;( 環境 autocommit=1 ,沒有手動開啓事務 )

儘管測試環境不影響線上應用,但影響了新功能開發進度,暴露出運維管理上的漏洞。app

經過以上案例思考,MySQL 自己並無操做審計的功能,又如何根據現有的功能進行行爲分析,避免悲劇再次發生?運維

文章整理了運維時經常使用的定位 MySQL 操做用戶方法,幫你快速查看用戶行爲記錄。測試

1、思路

  1. 設置 init_connect 參數;
  2. 建立用戶鏈接信息表;
  3. 經過 binlog 日誌進行查看執行的危險 SQL 語句;
  4. 經過 thread_id 找到對應的用戶及來源 IP 地址。

init_connect 參數的功能:當用戶在客戶端鏈接 MySQL 時,隱式執行的一條自定義的 SQL 語句(參數值)。線程

注意:3d

  • 開啓 binlog 日誌記錄功能;
  • 對擁有 super_priv 權限的用戶無效。

2、準備工做

2.1 init_connect 參數

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

2.2 鏈接信息表

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 能夠手動刪除他鏈接的信息。

3、誤刪除實驗

3.1 模擬誤刪除

[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)

此時數據已經被刪除了,你的應用程序應該會報錯或開始告警。經過檢查應用日誌,可大體推斷時間範圍。

3.2 導出並分析 binlog 日誌

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

3.3 查看對應時間對應的用戶信息

能夠看到線程 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 地址誰在使用。

完成了經過行爲定位用戶的操做。

相關文章
相關標籤/搜索