事务
在软件开发中的事务(Transaction)
什么是事务
参看文章
mysql 四种隔离级别
MySQL的四种事务隔离级别
事务具有四个特征:原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持续性( Durability )。这四个特性简称为 ACID 特性。
事务指单元性事件或动作,具有
原子性,不可再细分;
隔离性,事务不被其他事情影响;
一致性,事务的结果是可预见的。
持久性,事务提交后,永久生效。
描述事务最常见的列子使用转账来说明。
通过转账描述事务
A账户有人名币100元
B账户有人名币50元
现在要做一件事,A账户转账给B账户20元,那么这件事中算一个事务
@1 A账户减少20元 100-20 = 80
@2 B账户增加20元 50+20 = 70
事件@1与@2必须是同时发生的或者都不发生。(原子性)
A账户再转账给其他人,和此次转账没有关联(隔离性)
A账户少了20元,B账户多了20元,总值没变(80 + 70 = 100 + 50 = 150)(一致性)
转账确认后,修改是永久生效的,(A减少20) (B增加20) (持久性)
如果 @1发生 @2没发生 那么转账这件事的结果是错误的
A账户少了20元 B账户却没有增加20元(打破了原子性,一致性)
这种错误是不允许发生的,但是在软件开发中@1(支出) @2(收入)是两个方法或者代码段,存在一个方法执行,一个方法未执行的意外情况,所以在软件开发中需要用到事务去处理此类似意外情况,使结果正确;
这里通过事务机制修改错误的方法有两种
1.回滚,@1 事件回滚,A账户转账20撤回,结果接就是转账失败(但不是错误),A账户没有少钱,B账户也有多钱
2.尝试强制执行上次未成功的动作 @2 B账户没有新增20元 再次执行新增20元的动作,如果成功,那么结果是转账成功,否则只能回滚事务
事务
事务主要针对数据库数据操作
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
事务流程
Transaction
像上述所说的转账,是针对数据库的操作
begin
开启事务
commit
提交事务,数据修改生效 (事务结束)
rollback
回滚事务,撤销数据修改(事务结束)
所以,一般执行事务的流程分为三个阶段
1.开启事务 -> 2.执行数据修改操作 -> 3.结束事务(回滚 or 提交)
结束事务分两种情况,如果执行正常,就提交生效数据修改;出现意外,执行出错,就回滚数据修改。
隔离性
事务与数据库数据操作有关,数据在修改时,在高并发情况下,存在数据修改的同时,有可能被其他连接查询,会有查询数据不一致情况,这里就有隔离级别的概念
A转账20 100-20 = 80 在这个事务执行的时候,如果另一个连接查询这条数据,查询的结果是100还是80?
隔离级别有 读未提交 读已提交 可重复读 可串行化
mysql数据库中有四个隔离界别
读未提交 Read Uncommitted
事务中,100元 减少 20, 还剩下80,这个事务还未提交(有可能回滚),这个时候另一个实例查询这条数据,查询到的结果是80,这是读了未提交的数据,如果事务回滚,再次查询,结果又是100
读已提交 Read Committed
同上 100-20=80 在事务中,修改了数据,还没提交,其他人这时候查询这条数据,查询结果是100,如果事务提交了,事务中其他连接查询到的结果才是80
可重复读 Repeatable Read
读已提交虽然读的数据没错误,但是事务中A事务开启,另一个事务B修改数据,并且已提交,但是A事务查询的数据还是A事务开启时的数据,不会查询到B事务修改并且提交的数据,这就是可重复读
幻读
幻读只在可重复读的隔离级别中出现,出现在数据插入操作。
比如,事务A开启,查询数据10条,统计select count(*) from table 结果为10
这时事务B在表中插入了一条数据,那么事务A再次执行select count(*) from table 结果为11
事务A两次执行同一个查询,第一次是10,第二次是11,这是幻读。
解决幻读
解决幻读的办法就是在事务A开启的时候,禁止其它事务在表中插入数据,第一时间想到的是用表锁。
可串行化 Serializable
事务队列化执行,明显影响性能的隔离级别,不常用,就是任何事务必须排队执行,如果服务开启10个事务,那么这10个事务必须排队依次执行,A事务执行完提交或者回滚了,B事务才可以开启执行...