一.数据准备:
1.员工表:
-- 员工管理
create table tb_emp
(id int unsigned primary key auto_increment comment 'ID',username varchar(20) not null unique comment '用户名',password varchar(32) default '123456' comment '密码',name varchar(10) not null comment '姓名',gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',image varchar(300) comment '图像',job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管,5.咨询师',entrydate date comment '入职时间',dept_id int unsigned comment '部门ID', -- 属于外键字段,关联部门表的主键IDcreate_time datetime not null comment '创建时间',update_time datetime not null comment '修改时间'
) comment '员工表';
insert into tb_emp
(id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)
values (1, 'jinyong', '123456', '金庸', 1, '1.jpg', 4, '2000-01-01', 2, now(), now()),(2, 'zhangwuji', '123456', '张无忌', 1, '2.jpg', 2, '2015-01-01', 2, now(), now()),(3, 'yangxiao', '123456', '杨逍', 1, '3.jpg', 2, '2008-05-01', 2, now(), now()),(4, 'weiyixiao', '123456', '韦一笑', 1, '4.jpg', 2, '2007-01-01', 2, now(), now()),(5, 'changyuchun', '123456', '常遇春', 1, '5.jpg', 2, '2012-12-05', 2, now(), now()),(6, 'xiaozhao', '123456', '小昭', 2, '6.jpg', 3, '2013-09-05', 1, now(), now()),(7, 'jixiaofu', '123456', '纪晓芙', 2, '7.jpg', 1, '2005-08-01', 1, now(), now()),(8, 'zhouzhiruo', '123456', '周芷若', 2, '8.jpg', 1, '2014-11-09', 1, now(), now()),(9, 'dingminjun', '123456', '丁敏君', 2, '9.jpg', 1, '2011-03-11', 1, now(), now()),(10, 'zhaomin', '123456', '赵敏', 2, '10.jpg', 1, '2013-09-05', 1, now(), now()),(11, 'luzhangke', '123456', '鹿杖客', 1, '11.jpg', 1, '2007-02-01', 3, now(), now()),(12, 'hebiweng', '123456', '鹤笔翁', 1, '12.jpg', 1, '2008-08-18', 3, now(), now()),(13, 'fangdongbai', '123456', '方东白', 1, '13.jpg', 2, '2012-11-01', 3, now(), now()),(14, 'zhangsanfeng', '123456', '张三丰', 1, '14.jpg', 2, '2002-08-01', 2, now(), now()),(15, 'yulianzhou', '123456', '俞莲舟', 1, '15.jpg', 2, '2011-05-01', 2, now(), now()),(16, 'songyuanqiao', '123456', '宋远桥', 1, '16.jpg', 2, '2010-01-01', 2, now(), now()),(17, 'chenyouliang', '123456', '陈友谅', 1, '17.jpg', NULL, '2015-03-21', NULL, now(), now());
2.部门表:
-- 部门管理
create table tb_dept
(id int unsigned primary key auto_increment comment '主键ID',name varchar(10) not null unique comment '部门名称',create_time datetime not null comment '创建时间',update_time datetime not null comment '修改时间'
) comment '部门表';
insert into tb_dept (id, name, create_time, update_time)
values (1, '学工部', now(), now()),(2, '教研部', now(), now()),(3, '咨询部', now(), now()),(4, '就业部', now(), now()),(5, '人事部', now(), now());
二.实例:
意味着要删除部门表里的学工部和员工表里在学工部的员工。
代码:
-- =============================================事务=============================================
-- 删除部门
delete from tb_dept where id = 1;
-- 删除部门下的员工
delete from tb_emp where dept_id = 1;
运行结果:
1.异常情况:
代码:
-- =============================================事务=============================================
-- 删除部门
delete from tb_dept where id = 3;
-- 删除部门下的员工
delete from tb_emp where dept_id == 3;
运行结果:
出现了异常,只有部门表成功操作,员工表操作失败:
2.问题:可通过事务解决
三.事务:
如果删除一个部门,那么该部门下的员工也就要删除,因此两者应属于一个事务即要么同时成功,要么同时失败,但刚才的例子中删除部门成功,而删除部门对应的员工失败,是因为当执行一条DML语句时,MySQL会立即隐式的提交事务,也就是说,刚才删除部门的SQL语句和删除员工的SQL语句是两个事务。
由此,就需要把删除部门和删除部门下的员工绑定成一个事务。
四.操作:
首先开启事务,所有操作成功之后提交事务,只要有数据操作失败就需要回滚事务,回滚事务就是把所有的数据恢复到操作之前的样子。
注:上图3条语句都属于SQL语句,都需要执行才生效。
如:
五.代码演示事务:
-- =============================================事务=============================================
-- 1.开启事务
start transaction ;/*也可以用begin*/
-- 删除部门
delete from tb_dept where id = 3;
-- 删除部门下的员工
delete from tb_emp where dept_id = 3;
-- 2.提交事务
commit ;
-- 3.回滚事务
rollback ;
select * from tb_dept;
select * from tb_emp;
1.部门表和员工表:
2.开启事务并执行绑定为事务的SQL语句:
运行结果:带绿箭头的语句代表已经执行过
在别的窗口中此时id为3的部门和该部门下的员工并没有被删除,是因为还没有提交事务,两者还是隔离的(尽管刷新后看到的已经删除了,但并没有真正意义上的删除,两个窗口也属于两个事务)。
在开启事务的窗口中查看部门表和员工表:同一个窗口下属于一个事务,可以看到id为3的部门和该部门下的员工被删除
3.提交事务:
此时别的窗口中就可以看到正确的结果了。
4.异常情况:
a.代码:
-- =============================================事务=============================================
-- 1.开启事务
start transaction ;/*也可以用begin*/
-- 删除部门
delete from tb_dept where id = 2;
-- 删除部门下的员工
delete from tb_emp where dept_id == 2;
-- 2.提交事务
commit ;
-- 3.回滚事务
rollback ;
select * from tb_dept;
select * from tb_emp;
b.开启事务:
c.执行SQL语句:
2条SQL语句中只成功操作了部门表,员工表操作失败。
先不提交事务,因为提交事务是所有操作成功后才进行的操作,如果有操作失败,就必须先回滚事务
部门表和员工表的运行结果:部门表操作成功,员工表操作失败
由此就需要回滚事务。
d.回滚事务(只要有操作失败就要回滚事务):
部门表和员工表数据恢复到操作之前的样子:
所以一旦出现异常,就可以通过回滚事务将删除掉的数据恢复,从而保证在操作前后数据的一致性和完整性。
六.事务的四大特性:
1.一致性:无论提交事务还是回滚事务,都算事务完成,所有的数据都必须保持一致性。比如刚才的例子,事务完成后要么部门和该部门下的员工都还在,要么部门和该部门下的员工都没有,不能是部门没有了,而该部门下的员工还在。
2.隔离性:在一个窗口下还没有提交事务,在另一个窗口下就无法看到最终结果,即使看到了,也不是正在意义上的。隔离性可以通过隔离级别来设置,隔离性越高,事务越安全,但效率越低,所以隔离性很少手动控制。