目录
1. 事务的特性
有四个,总结起来叫做ACID(与一些标准的解释可能不太一致):
A (atomicity)原子性 :一个事务的执行操作序列是一个整体,要们全部全部执行成功,要么都都执行失败,不存在部分执行成功部分失败的情况
C(consistency)一致性 :数据库会有增删改的操作,在这个操作前后保持业务逻辑一致
I (Isolation) 隔离性:并发事务中有的概念,单个事务不会出问题,但多个事务并发执行就会出现各种数据问题,事务隔离级别解决了各种问题
D (Durability)持久性:对数据操作完成后,效果是持久的,不回因为断电等原因而消失,就是存储到了磁盘上了,不是存在内存中就完事了
最终的目标是为了保证数据库数据的一致性
2. 事务的隔离级别
如果不考虑事务的隔离级别,会有什么问题?会有脏读、不可重复度、幻读的问题,不同事务的隔离级别解决对应的问题。
脏读
不可重复读
幻读
事务的隔离级别如表格所示
注意:对于幻读,一般数据库在可重读的级别是有幻读的问题,在MySQL中通过Gap锁实现了在可重复度的幻读问题。
3. 隔离级别验证
前提条件:
- 针对的数据库为MySQL,版本为5.7.x
- MySQL查看事务隔离级别命令:
-- 查看当前会话的隔离级别 select @@tx_isolation; -- 查看全局的隔离级别 select @@global.tx_isolation;
- MySQL数据库的隔离级别会话级设置命令:
-- 设置读取未提交 set session transaction isolation level READ UNCOMMITTED; -- 设置读取已经提交 set session transaction isolation level READ COMMITTED; -- 设置可重复读 set session transaction isolation level REPEATABLE READ; -- 设置串行化 set session transaction isolation level SERIALIZABLE;
- MySQL事务常用操作:
-- 设置事务提交模式,0表示禁止自动提交 1表示自动提交 SET AUTOCOMMIT=0|1 -- 开始事务 BEGIN; -- 提交事务 COMMIT -- 回滚事务 ROLLBACK;
5.准备一张表和数据
CREATE TABLE IF NOT EXISTS `t_user`( `id` INT UNSIGNED AUTO_INCREMENT, `name` VARCHAR(100) NOT NULL comment '名字', `money` INT comment '账户金额', PRIMARY KEY ( `id` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8; BEGIN; INSERT INTO `t_user` VALUES (1, '张三', 100); INSERT INTO `t_user` VALUES (2, '李四', 100); INSERT INTO `t_user` VALUES (3, '王五', 100); COMMIT;
3.1 读取未提交
控制台打开两个界面开启两个会话,设置会话的隔离级别为“读取未提交”,确认两点,是否禁止自动提交,是否为“读取未提交”隔离级别:
两个控制台的执行流程如下:
分析:
- (3)中第一次查询到money的数据为100,(4)步骤更新没有提交,但是再次查询得到money的结果为150,这里查到数据为脏数据
- (3)(5)数据不一致出现不可重读
3.2 读取已提交
控制台打开两个界面开启两个会话,设置会话的隔离级别为“读取已提交”,确认两点,是否禁止自动提交,是否为“读取已提交”隔离级别:
两个控制台的执行流程如下:
分析:
- (3)第一次查询money为100,(4)更新操作,(5)再次查询到结果仍然为100,所以没有脏读的问题
- (6)对修改进行提交,(7)再次读取到的结果为150,还是有不可重复读问题
3.3 可重复读
控制台打开两个界面开启两个会话,设置会话的隔离级别为“可重复读”,确认两点,是否禁止自动提交,是否为“可重复读”隔离级别:
两个控制台的执行流程如下:
分析:
- (3)第一次查询money为100,(4)更新操作,(5)再次查询到结果仍然为100,所以没有脏读的问题
- (6)对修改进行提交,(7)再次读取到的结果为100,解决了不可重复读问题
- (8)提交掉当前事务,新事务查询出的结果为150
3.4 串行化
控制台打开两个界面开启两个会话,设置会话的隔离级别为“串行化”,确认两点,是否禁止自动提交,是否为“串行化”隔离级别:
两个控制台的执行流程如下:
分析:
- (3)事务执行的时候,另一个事务执行修改语句,就必须排队等待执行了,并且有超时机制,超过时间直接放弃修改
- (3)执行查询,其他事务也可以执行查询