今天要讲的是mysql数据库的事务处理:
菜鸟新手一枚,先来事务的定义:
- 在mysql中只有使用了Innodb数据库引擎的数据库或表才支持事务;
- 事务处理可以用来维护数据库的完整性,保证成批的sql语句要么全部执行,要么全部不执行;
- 事务用来管理insert,update,delete语句。
一般来说事务必须满足四个条件,也叫作事务的四大特性(ACID):
-
- 原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败。比如在同一个事务中的SQL语句,要么全部执行成功,要么全部执行失败。
- 一致性(Consistency):事务必须是数据库从一个一致性状态换到另外一个一致性状态。例如:转账的时候,A向B转账,假设转账之前这两个用户的钱加起来总共是2000元,那么A向B转账后,不管怎么转,A和B的钱加起来还是2000元,这就是事务的一致性。
- 隔离性(Isolation):事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
- 持久性(Durability):在软件或硬件运行崩溃时,Innodb数据表会利用日志文件重构修改。
原子性很好理解,就不多解释了,下面对隔离性重点理解:
隔离性分为还几个级别:
- 脏读(Read uncommitted):级别最低,脏读是指一个事务读取了另一个事务未提交的数据。这是非常危险的,假设A和B之间转账,如下语句:
1.update account set money=money+100 where name='B';
2.update account set money=money-100 where name='A';
当第一条sql执行完,第二条还没执行(A未提交),如果此时B查询自己的账户,就会发现自己多了100元钱。如果A等B走后(查询过)再回滚(代码都失效了),B就会损失100元,B再查询钱还是原来的钱。
- 不可重复读(Read committed):不可重复读指在一个事务内读取表中的某一行数据,多次读取结果不同。
我是这样理解的:也就是结果提交后才能查询到修改过的数据,未提交时查询的是未操作的数据;
比如事务T1读取某一数据,事务T2读取并修改了该数据,T1(该事务不能结束)为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
- 虚读(幻读)(Repeatable read):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
例如:丙存款100元未提交,这时银行做报表统计account表中所有用户的总额为500元,然后丙提交了,这时银行再统计(对所有数据进行更新,对某个数据更新时可能发现不了)时发现账户为600元,造成了虚读,怎么出现了幻觉,他就不敢提交了。
流程为:
事务A开启->事务A读取所有行数据->事务B开始在数据库中加入一行数据
并提交->事务对所有数据进行了更新操作(注意这里一定要是全表)———>
然后事务A再次查询表的所有数据,想看看自己的劳动成果,结果发现多出了一条数据还被改了,我只想要我刚才看到的数据啊,我是不是出现幻觉了,这样搞的事务A不敢提交了。
不可重复读和幻读的区别是:
不可重复读是指读的时候,别的事务修改了数据update;
幻读是指读的时候,别的事务插入或删除了数据 insert delete;
- 串行化(Serializable)
一个事务获取的数据别的事务无法更改。。。会有死锁问题,效率问题。
MySQL数据库共定义了四种隔离级别:
1 Serializable(串行化):可避免脏读、不可重复读、虚读情况的发生
2 Repeatable read(可重复读):可避免脏读、不可重复读情况的发生。
3 Read committed(读已提交):可避免脏读情况发生
4 Read uncommitted(读未提交):最低级别,以上情况均无法保证
select @@tx_isolation 读取当前隔离级别
设置读取隔离级别
set session transaction isolation level read uncommitted;
set session transaction isolation level read committed;
mysql 默认
set session transaction isolation level repeatable read;
rollback;使用一次,相当于撤回前面操作,需要重新开启事务操作。