一.數據準備:
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.隔離性:在一個窗口下還沒有提交事務,在另一個窗口下就無法看到最終結果,即使看到了,也不是正在意義上的。隔離性可以通過隔離級別來設置,隔離性越高,事務越安全,但效率越低,所以隔離性很少手動控制。