0. 数据源
/*
Navicat Premium Data Transfer
Source Server : localhost_3306
Source Server Type : MySQL
Source Server Version : 80016
Source Host : localhost:3306
Source Schema : tempdb
Target Server Type : MySQL
Target Server Version : 80016
File Encoding : 65001
Date: 23/05/2023 22:01:41
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`num` int(11) NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`age` int(11) NULL DEFAULT NULL,
`tel` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`c_id` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`num`) USING BTREE,
INDEX `f_std_cls`(`c_id`) USING BTREE,
INDEX `index_test2`(`age`) USING BTREE,
INDEX `index_test3`(`name`, `age`) USING BTREE,
CONSTRAINT `f_std_cls` FOREIGN KEY (`c_id`) REFERENCES `class` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (102, '王五', 34, '4334', 2);
INSERT INTO `student` VALUES (104, '赵无极', 23, '4234', 1);
INSERT INTO `student` VALUES (105, '韩夫子', 34, '23', 2);
INSERT INTO `student` VALUES (106, '高俅', 25, '42543', 4);
INSERT INTO `student` VALUES (107, '范瑶', 26, '2345', NULL);
INSERT INTO `student` VALUES (108, '斯巴达克斯', 27, '422156 ', NULL);
SET FOREIGN_KEY_CHECKS = 1;
1. 概念
把完成特定业务的多个数据库DML操作步骤称之为⼀个事务,事务就是完成同⼀个业务的多个DML操作。
-- 借书业务
-- 操作1:在借书记录表中添加记录
-- 操作2:修改图书库存
-- 转账业务:张三给李四转账1000
-- 操作1:李四的帐号+1000
-- 操作2:张三的账户-1000
2. 特性
原⼦性
(Atomicity):⼀个事务中的多个DML操作,要么全部执⾏成功,要么全部执⾏失败;
⼀致性
(Consistency):事务执⾏之前和事务执⾏之后,数据库中的数据是⼀致的,完整性和⼀致性不能被破坏;
隔离性
(Isolation):数据库允许多个事务同时执⾏(张三借Java书的同时允许李四借Java书),多个加粗样式并行的事务之间不能相互影响;
持久性
(Durability):事务完成之后,对数据库的操作是永久的。
3. 事务管理
3.1
⾃动提交
在MySQL中,默认DML指令执⾏时⾃动提交的
,当我们执⾏⼀个DML指令之后,⾃动同步到数据库中。
3.2
事务流程
(1)开启事务,就是关闭⾃动提交。在开始事务之前,执⾏ start transaction;
开启事务;
(2)依次执⾏事务中的每个DML操作;
(3)如果在执⾏过程中的任何位置发生异常,则执⾏ rollback;
回滚事务;
(4)如果事务中所有的DML操作都执⾏成功,则在最后执⾏ commit;
提交事务;
-- 开启事务
start TRANSACTION;
-- DML相关操作
update student set name='王五五' where name='王五';
delete from student where num=103;
-- 如果发生错误,则回滚
rollback;
-- 否则,提交事务,将数据同步到数据库中
commit;
4. 事务隔离级别
数据库允许多个事务并⾏,多个事务之间是隔离的、相互独⽴的;如果事务之间不相互隔离并且操作同⼀数据时,可能会导致数据的⼀致性被破坏。
4.1
读未提交
T2可以读取T1执⾏但未提交的数据;可能会导致出现脏读。
脏读
,⼀个事务读取到了另⼀个事务中未提交的数据。
4.2
读已提交
T2只能读取T1已经提交的数据;避免了脏读,但可能会导致不可重复读(虚读)。
不可重复读(虚读)
: 在同⼀个事务中,两次查询操作读取到数据不⼀致。
例如: T2进⾏第⼀次查询之后在第⼆次查询之前, T1修改并提交了数据, T2进⾏第⼆次
查询时读取到的数据和第⼀次查询读取到数据不⼀致。
4.3
可重复读
T2执⾏第⼀次查询之后,在事务结束之前其他事务不能修改对应的数据;避免了不可重复读(虚读),但可能会导致幻读。
幻读
, T2对数据表中的数据进⾏修改然后查询,在查询之前T1向数据表中新增了⼀条数据,就导致T2以为修改了所有数据,但却查询出了与修改不⼀致的数据(T1事务新增的数据)。
4.4
串行化
同时只允许⼀个事务对数据表进⾏操作;避免了脏读、虚读、幻读问题。
我们可以通过设置数据库默认的事务隔离级别来控制事务之间的隔离性;
也可以通过客户端与数据库连接设置来设置事务间的隔离性(在应⽤程序中设置–Spring);
MySQL数据库默认的隔离级别为 可重复读。
(1)查看MySQL数据库默认的隔离级别
-- 在MySQL8.0.3 之前
select @@tx_isolation;
-- 在MySQL8.0.3 之后
select @@transaction_isolation;
(2)设置MySQL默认隔离级别
set session transaction isolation level <read committed>;