02.MySQL事务
# 01.MySQL事务
# 1.1 InnoDB事务原理
- 事务(Transaction)是数据库区别于文件系统的重要特性之一,事务会把数据库从一种一致性状态转换为另一种一致性状态
- 在数据库提交时,可以确保要么所有修改都已保存,要么所有修改都不保存
# 1.2 事务四大特性
- 原子性:整个事物的所有操作要么全部提交成功,要么全部失败回滚(
要么全部执行,要么全部回滚
)- eg:A向B转账100块,从A扣除成功而添加B失败,整个事务将回滚,确保没有部分完成的转账
- 一致性:事务开始之前和事务结束以后,数据不会被破坏(
保持数据库的一致性
)- eg:假如A账户给B账户转10块钱,不管成功与否,A和B的总金额是不变的
- 隔离性:事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的
- 持久性: 事务完成提交后,该事务对数据库所作的操作更改,将持久地保存在数据库之中
原子性和一致性区别
- 原子性并不能保证一致性,在多事务并行情况下,即使保证每个事物原子性,仍然可能数据不一致
- 比如:假如同时开启两个事物A和B都要给tom账号转100元,可能增加两次,但是有一次被另一个事物覆盖
# 1.3 InnoDB与MyISAM
- InnoDB是支持
事物
,MyISAM不支持 - InnoDB支持
行级锁
,MyISAM不支持 - InnoDB支持
外键
,MyISAM不支持 - InnoDB支持
崩溃恢复
,MyISAM数据库崩溃,可能导致表损坏 - InnoDB数据和索引存储在相同表空间,支持缓存机制,MyISAM数据和索引存储在两个不同文件中,不支持缓存机制
- 引擎选择
- MyISAM更适合读多写少的操作
- 需要
事务、行级锁定、崩溃恢复
等高级特性,选择InnoDB更为合适
# 1.4 事务隔离级别
# 1.4.1 未提交读: 脏读
读取到其他事务修改但未提交数据
1)事务2查询到的数据是事务1中修改但未提交的数据,但因为事务1回滚了数据
2)所以事务2查询的数据是不正确的,因此出现了脏读的问题
注:
脏读没有MVCC机制
,select 默认需要加共享锁
# 1.4.2 提交读: 不可重复读
事务1读取到事务2修改前和修改后的数据,两次读取数据不一样
- 1)事务2执行update语句但未提交前,事务1的前两个select操作返回结果是相同的
- 2)但事务2执行commit操作后,事务1的第三个select操作就读取到事务2对数据的改变
- 3)导致与前两次select操作返回不同的数据,因此出现了不可重复读的问题
注:
不可重复读 有MVCC机制
,select 默认不需要加共享锁
# 1.4.3 可重复读: 幻读(MySQL默认)
事务1在自己版本号中,查询到另一个事务插入新的数据行,这就会导致该事物中凭空多出数据行
这是MySQL的默认事务隔离级别
- 1)事务A先查询id大于2的账户记录,得到记录id=2和id=3的两条记录
- 2)这时候,事务B开启,插入一条id=4的记录,并且提交了
- 3)事务A再去执行相同的查询,却得到了id=2,3,4的3条记录了
注:
可重复读 有MVCC机制
,select 默认不需要加锁
# 1.4.4 可串行读
1)这是事务的最高隔离级别,通过强制事务排序,使之不可能相互冲突,就是在
每个读的数据行加上共享锁来实现
2)在该隔离级别下,可以解决前面出现的脏读、不可重复读和幻读问题,但也会
导致大量的超时和锁竞争现象,一般不推荐使用
注:
可串行读没有MVCC机制
,select 默认需要加共享锁
# 02.事务使用举例
事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行
例子:张三账户转账转出 100 元到李四的账户
1、张三账户减去 100 元
2、李四账户增加 100 元
begin;
update user set balance = balance-100 where id=1;
# rollback; # 如果rollback,就不会提交了
update user set balance = balance+100 where id=2;
commit; # 只有commit提交事务,其他事务才能看到结果
1
2
3
4
5
2
3
4
5
上次更新: 2024/10/15 16:27:13