Posts 事务
Post
Cancel

事务

事务

在软件开发中的事务(Transaction)

什么是事务

事务具有四个特征:原子性( 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事务才可以开启执行…

This post is licensed under CC BY 4.0 by the author.