经过init-connect + binlog 实现MySQL审计功能
背景:
假设这么一个状况,你是某公司mysql-DBA,某日忽然公司数据库中的全部被人为删了。
尽管有数据备份,可是因服务中止而形成的损失上千万,如今公司须要查出那个作删除操做的人。
可是拥有数据库操做权限的人不少,如何排查,证据又在哪?
是否是以为无能为力?
mysql自己并无操做审计的功能,那是否是意味着遇到这种状况只能自认倒霉呢?
本文就将讨论一种简单易行的,用于mysql访问审计的思路。mysql
关键字:init—connect,binlog,trigger
概述:
其实mysql自己已经提供了详细的sql执行记录–general log ,可是开启它有如下几个缺点
不管sql有无语法错误,只要执行了就会记录,致使记录大量无用信息,后期的筛选有难度。
sql并发量很大时,log的记录会对io形成必定的印象,是数据库效率下降。
日志文件很容易快速膨胀,不妥善处理会对磁盘空间形成必定影响。
基本原理:
因为审计的关键在于DML语句,而全部的DML语句均可以经过binlog记录。
不过遗憾的是目前MySQL binlog 中只记录,产生这条记录的connection id(随链接数自增,循环使用),这对以后的反查没有任何帮助。
所以考虑经过init-connect,在每次链接的初始化阶段,记录下这个链接的用户,和connection_id信息。
在后期审计进行行为追踪时,根据binlog记录的行为及对应的connection-id 结合 以前链接日志记录 进行分析,得出最后的结论sql
正文:
1. 设置init-connect
1.1建立用于存放链接信息的表
create database AuditDB default charset utf8;
use AuditDB;
create table accesslog (ID int primary key auto_increment,ConnectionID int, ConnUserName varchar(30), PrivMatchName varchar(30), LoginTIme timestamp);数据库
1.2 保证全部的用户对此表有写权限
insert into db (Host,Db,User,Insert_priv) values (‘%’,'AuditDB’,”,’Y');
flush privileges;服务器
1.3 设置init-connect
在my.cnf 中的 [mysqld] 的block 添加如下配置;
init-connect=’insert into AuditDB.accesslog (ConnectionID,ConnUserName,PrivMatchName,LoginTime) values(connection_id(),user(),current_user(),now());’
log-bin并发
1.4 重启数据库生效
service mysqld restartide
2. 记录追踪
2.1 thread_id确认
假设想知道在2009年11月25日,上午9点多的时候,是谁吧test.dummy这个表给删了。能够用如下语句定位
mysqlbinlog –start-datetime=’2009-11-25 09:00:00′ –stop-datetime=’2009-11-25 09:00:00′ binlog.xxxx | grep ‘dummy’ -B 5
会获得以下结果(可见thread_id为5):性能
# at 300777 #091124 16:54:00 server id 10 end_log_pos 301396 Query thread_id=5 exec_time=0 error_code=0 SET TIMESTAMP=1259052840; drop table test.dummy;
2.2 用户确认
thread_id 确认之后,找到元凶就只是一条sql语句的问题了。
select ID,LoginTime,PrivMatchName,ConnUserName fromAuditDB.accesslog where ConnectionID=5 ;rest
就能发现是testuser2@localhost干的了。日志
(root:local_test:)[(none)] 02:23:22> select * from auditdb.accesslog limit 1; +----+--------------+----------------+----------------+---------------------+ | id | connectionid | connusername | privmatchname | logintime | +----+--------------+----------------+----------------+---------------------+ | 1 | 5 | root@localhost | root@localhost | 2013-10-07 14:17:01 | +----+--------------+----------------+----------------+---------------------+
3. Q&A
Q:使用init-connect会影响服务器性能吗?
A:理论上,只会在用户每次链接时往数据库里插入一条记录,不会对数据库产生很大影响。除非链接频率很是高(固然,这个时候须要注意的就是如何进行链接复用和控制,而非是否是要用这种方法的问题了)
Q:access-log表如何维护?
A: 因为是一个log系统,推荐使用archive存储引擎,有利于数据厄压缩存放。若是数据库链接数量很大的话,建议必定时间作一次数据导出,而后清表。
Q:表有其余用途么?
A:有!access-log表固然不仅用于审计,固然也能够用于对于数据库链接的状况进行数据分析,例如每日链接数分布图等等,只有想不到没有作不到。
Q:会有遗漏的记录吗?
A:会的,init-connect 是不会在super用户登陆时执行的。因此access-log里不会有数据库超级用户的记录,这也是为何咱们不主张多个超级用户,而且多人使用的缘由。code