MySQL事务
Mysql事务
概念:如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败
操作:
- 开启事务:
start transaction;
- 回滚:
ROLLBACK
- 提交:
COMMIT
- 开启事务:
例如:王给张转500元钱
- 判断王有没有500
- 王-500
- 张+500
- 转账完成,中间出现差错会从头回滚
1
2
3
4
5
6
7
8
9
10START TRANSACTION;# 开启事务
# 王给张转500
# 判断是否大于五百元
# 王账户减去五百
UPDATE deliver SET bank = bank -500 WHERE `NAME` = '王' && bank>500;
# 张账户加五百
#这里出错
UPDATE deliver SET bank = bank +500 WHERE `NAME` = '张';
#这里出错 ROLLBACK; 出错就添加ROllBACK 回到开启事务的地方
COMMIT;# 成功就会完成这项事务 - MySQL数据库中事务默认自动提交(Oracle默认是手动提交的)
- 手动打开事务才是自动提交
- 修改事务的默认提交方式
1
2
3
4
5# 查看默认提交方式
SELECT @@autocommit
# 1代表自动提交,0代表手动提交
SET @@autocommit = 0;
# 更改为手动提交,只有COMMIT才会
事务ACID原则
- 原子性A:同时成功,要么同时失败
- 一致性C:在事务开始之前和事务结束以后,数据库的完整性没有被破坏
- 隔离性I:多个事务之间,相互独立
- 持久性D:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
隐式提交
mysql中事务提交后,才会改变数据的值,但是如果在事务执行时执行了如下的操作,mysql就会隐式的替我们提交:
- 执行了DDL语句(create、drop、alter)
- 开启了一个新的事务
- 使用了锁
- 使用了加载语句操作
事务引发的问题
多个事务操作同一批数据,存在问题:
脏读:一个事务读取到另一个事务中没有提交的数据
比如A、B、C三个人,A有500元,B有100、C有1000
1 | A向B转100元——正常流程: |
不可重复读:在同一个事务中两次读取到的数据不一样(不一定是错误,但是某些场合不对)
比如总支出计算,第一次读出开支100元,准备生成报表,结果读出为200元(在那一瞬间别的事务又花了100)
幻读:一个事务(同一个read view)在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行(一般指数据行记录变多了或者少了)
比如给员工都涨薪,update set salary= salary + 100
,但是此时又来一个新人,最后发现,命名给所有人涨薪100的操作,缺疏忽了一个人
事务的隔离级别
多个事务之间是隔离的,相互独立的。
但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题
隔离级别:
read uncommited
读未提交:所有事务都可以看到没有提交事务的数据产生的问题:脏读、不可重复度、幻读
read commited
读已提交(Oracle默认):事务成功提交后才可以被查询到产生的问题:不可重复度、幻读
repeatable read
可重复读(MySQL默认):同一个事务内多次查询却返回了不同的数据值产生的问题:幻读
serializable
串行化:写加写锁,读加读锁
可以解决所有的问题
注意:隔离级别从小到大安全性越来越大,但是效率越来越低
查询隔离级别
1 | select @@tx_isolation # 老版MySQL |
设置隔离级别
1 | set global transaction isolation level 级别字符串;# 老版 |
区别
脏读与不可重复读的区别:
- 脏读:读了另一事务未提交的数据
- 不可重复读:读了另一事务提交的数据