事务特征以及隔离级别

事务是什么?

事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transactionend transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。

举个栗子:假如A转账给B100元,第一步需要将A账户扣除100元,第二步需要将B账户增加100元,这两个操作组成了一个转账操作,假如我们在执行第一步的时候突然断电导致服务器宕机,这样就会造成A账户被扣除100元,B账户并没有相应的加钱操作,这是致命的问题,为了解决这个问题,事务就出现了,他表示第一步与第二步要么同时成功,要么同时失败,不会出现其他情况,这样就保证了转账的一致性。

这里我们设置一个转账的案例:A账户:100元;B账户:100元。

步骤:

1.开启事务

2.第二步:扣除A账户100元;

3.第三步:B账户增加100元;

4.第四步:提交事务。

事务是如何保证的呢?

这就要说到事务的几个特征:原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability),也就是常说的ACID特性。

原子性(atomicity):知道原子是什么吗?原子在化学反应中不可分割,也就是说原子是最小单位,一个事务必须被作为一个不可分割的最小工作单员,在一个事务中,所有操作要么同时成功,要么同时不执行,对于同一个事务,永远不能出现一个操作成功,另一个操作失败的情况,这就是事务的原子性。

一致性(consistency):数据库总是从一个一致性的状态转换到另一个一致性的状态,也就是说从一个状态改编成另一个状态,转账为例,初始状态A账户100元,B账户0元,假设在执行了A账户的扣钱操作之后系统奔溃,导致状态的转换没有完成,因此事务不会提交,所以在数据库中数据也不会做出相应的修改。

隔离性(isolation):这个是比较重要的一点,通常来说,一个事务在提交之前的所有操作是对其他事务不可见的,举个例子:A账户给B账户转账100元,执行了1、2步之后,突然线程被切换了,因为账号这时候账号B给账号A转50元,它查询A账户的结果还是100元,不会看到被扣除的结果,这就是事务的隔离性。

持久性(durability):这个比较好理解,就是说事务提交之后,事务中所作的所有操作都将永久保存到数据库中,就算系统奔溃,修改的数据也不会丢失。

事务的ACID特征保证了转账的准确性,不会导致金钱的丢失,但是,程序中真的要做到不丢失你的金钱是比较复杂的,所以这时候性能可能就不会那么出众了,因为程序、存储引擎会做大量的工作来保证事务的准确性。

就像锁一样,他保证了线程安全,但是降低了可用性,mysql的存储引擎有很多,有支持事务的也有不支持事务的,比如:InnoDB支持事务;MyISAM不支持事务。我们在选型的时候根据项目的需求来判断,对于一些不需要事务的查询类应用,选择MyISAM存储引擎可以获得更高的效率,如果个别操作需要事务,也可以通过lock tables语句来提供保护。

隔离级别

隔离级别:一个事务必须与由其他事务进行的资源或数据更改相隔离的程度。隔离级别从允许的并发副作用(例如,脏读或虚拟读取)的角度进行描述。

下面我来简单的介绍一下四种隔离级别。

read uncommitted(未提交读):一个事务的修改操作对另外一个事务是可见的,即使事务没有提交;事务可以读取到没有提交事务的修改数据,也就是常说的脏读(Dirty Read),这个隔离级别会让系统产生很多问题,项目中一般很少使用。

read committed(读提交):一个事务开始只能看到已经提交事务所作的修改操作,也就是说在事务未提交之前所修改的数据对另一个事务不可见,也就不可重复读,执行两次相同的查询,结果可能会不相同,这是大多数数据库的默认隔离级别(mysql除外)。

repeatable read(可重复读):该级别保证了同一个事物中多次读取相同数据的结果是一致的,但是可重复读还是不能解决另外一个问题,那就是:幻读(Phantom Read),幻读指的是:当某个事物读取某个范围内的记录时,被另外一个事务在该范围内新增了一条记录,当前事务再次读取该范围的记录时,会产生幻行(Phantom Row),InnoDB和XtraBDB存储引擎通过多版本并发控制解决了幻读问题,这种隔离级别时mysql的默认隔离级别。

serializable(可串行化):顾名思义,它要求所有的事务都串行化执行,这避免了可重复读的幻读问题,他是怎么让事务串行化的呢?这是因为serializable会在读取的数据上加锁,保证串行化,但是这就会导致有大量的sql超时和锁竞争的问题。这种隔离级别在项目中也是不常用的,除了特殊情况。

最后,在给出一个各个隔离级别的数据对比:

隔离级别 脏读 不可重复度 幻读 加锁读
read uncommitted(未提交读)
read committed(读提交)
repeatable read(可重复读)
serializable(可串行化)

 

发布了41 篇原创文章 · 获赞 79 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_33220089/article/details/104247472