智能2112杨阳
一、目的与要求:
1.了解MySQL审计功能及实现方式
2.掌握触发器的工作原理、定义及操作方法
二、内容:
注:
- 在同一个触发器内编写多行代码,需要用结构begin ……end
- 函数current_user()获得当前登录用户名
1.自动保存对所有表(至少fruits表和orderitems表)的插入、更新、删除操作到opertaion表中。
①增加opertaion表
表1 opertaion表结构
字段名 | 字段说明 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 |
id | ID号 | int (11) | Y | N | Y | Y | Y |
tablename | 表名 | varchar (50) | N | N | Y | N | N |
opname | 操作类型 | varchar (50) | N | N | Y | N | N |
optime | 操作时间 | datetime | N | N | Y | N | N |
ConnUser | 用户名 | varchar(30) | N | N | Y | N | N |
源码:
create table operation(
id int(11) not null unique auto_increment,
tablename varchar(50) not null,
opname varchar(50) not null,
-optime datetime not null,
ConnUser varchar(30) not null,
primary key(id));
②创建基于fruits表和orderitems表的插入、更新、删除触发器,该类触发器的功能是在执行相关操作时把操作相关信息写入opertaion表中。例如在fruits表中成功插入一项新的元组后,在opertaion表中自动增加一个元组,该元组描述了是对fruits表进行了插入操作。
源码:
create trigger insert_f after insert on fruits for each row
insert into operation(tablename,opname,optime,ConnUser) values('fruits','insert',now(),current_user());
create trigger update_f after update on fruits for each row
insert into operation(tablename,opname,optime,ConnUser) values('fruits','insert',now(),current_user());
create trigger delete_f after delete on fruits for each row
insert into operation(tablename,opname,optime,ConnUser) values('fruits','insert',now(),current_user());
create trigger insert_oi after insert on orderitems for each row
insert into operation(tablename,opname,optime,ConnUser) values('fruits','insert',now(),current_user());
create trigger update_oi after update on orderitems for each row
insert into operation(tablename,opname,optime,ConnUser) values('fruits','update',now(),current_user());
create trigger delete_oi after delete on orderitems for each row
insert into operation(tablename,opname,optime,ConnUser) values('fruits','delete',now(),current_user());
③测试:用B001帐号(即销售人员帐号)登录,在fruits表中插入一条水果信息,再查看opertaion表是否实现自动添加更新记录。
运行测试结果截图:
insert into fruits values('o1',103,'cantaloupe',7.80,1000);
2. 实现自动更新fruits表中商品数量
①在fruits表中增加一个属性quantity(库存商品数量) ,数据类型int(5),默认值为1000
源码:
alter table fruits add quantity int(5) default(1000);
运行测试结果截图:
②创建触发器实现当客户下订单后,fruits表对应此商品的数量自动的发生变化(减少或增加):
具体要求:
(1)在orderitems表中修改某个订单的商品数量后时, fruits表对应此商品的数量发生相应的改变。
(2)在orderitems表中增加一个购买详单(增加一个元组)时, fruits表对应此商品的数量发生相应的改变。
源码:
(1)
create trigger update_q after update on orderitems for each row
update fruits set quantity=quantity+old.quantity-new.quantity where f_id=new.f_id;
update orderitems set quantity=30 where f_id='a1';
(2)
create trigger insert_q after insert on orderitems for each row
update fruits set quantity=quantity-new.quantity where f_id=new.f_id;
insert into orderitems values(30002,2,'b3',60,6.70);
运行测试结果截图:
(1)修改前:
修改后:
(2)
修改前:
修改后:
3.用Mysql8审计功能实现保存非root用户的更新操作( binlog + init-connect ):
- 创建审计数据库auditdb及表accesslog;
源码:
create database auditdb;
use auditdb;
create table accesslog(
ID int(11) not null auto_increment,
ServerID int(11) default null,
ConnectionID int(11) default null,
ConnUser varchar(30) default null,
MatchUser varchar(30) default null,
LoginTime datetime default null,
primary key(ID)
)ENGINE=InnoDB auto_increment=1 default charset=utf8mb4;
- 为普通用户赋予写入表'accesslog'权限(每个非Root用户都要先授权,否则无法与数据库建立连接);
源码:
grant insert on `auditdb`.`accesslog` to `B001`@`%`;
flush privileges;
- 配置init-connect,用于当普通用户对目标数据库进行操作时自动写入审记表中,在my.ini(Linux系统下是my.cnf)中配置;
源码:
set global init_connect='insert auditdb.accesslog(ServerID,ConnectionID,ConnUser,MatchUser,LoginTime) values(@@server_id,connection_id(),user(),current_user(),now());';
- 开启mysql-binlog日志记录,在my.ini中配置:
# 二进制日志
log-bin=mysql-bin
# binlog-do-db=db #仅作用的库
expire_logs_days = 20
max_binlog_size = 300m
- 重启mysql
源码:
net stop mysql
net start mysql
测试效果截图:
三、小结
1.遇到的问题及解决过程
问题:开始没理解触发器最后一题的题意,增加一个购买详单时没有选择插入一整个元组,而是单纯改变了一个数值,导致结果跟上一小题的做法没有区别。
解决过程:重新理解了题意,改为在表中添加元组。
2.产生的错误及原因分析
错误:插入数据时失败
原因分析:忘了o_num为orders主键,必然唯一。
3.体会和收获。
本次博客通过对数据库进行一些列操作,学习和了解了触发器的工作原理、定义及操作方法。同时在实验中通过解决出现的问题与错误,在解决问题的过程中学到了更多的Mysql数据库相关的其他内容。通过后台的操控了解了更多可视化数据库管理系统的功能多样与数据库的用处之广,总的来说收获满满。
附:
1.解密mysql-bin查看内容(日志文件)
注意进入日志文件路径后再操作
C:\ProgramData\MySQL\MySQL Server 8.0\Data>mysqlbinlog --base64-output=decode-row -vv mysql-bin.000002 > ./mysql-bin.000002--vv.log
2.查看日志文件内容
C:\ProgramData\MySQL\MySQL Server 8.0\Data>more mysql-bin.000002--vv.log
3.根据thread_id号去找init-connect记录表的登录用户和源ip
mysql -u root -p123456 -e "select * from auditdb.accesslog where connectionID=8 ;"
4.下载并安装MySQL Binlog Digger可视化分析日志
模拟插入或删除表中的一行,再用MySQL Binlog Digger显示