本文由葡萄城技术团队于博客园原创并首发
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。
谈起数据库,事务是绕不开的话题。无论你是研发、实施还是运维,都需要理解、使用无数据事务的特性。数据库事务连接各种数据,是处理各种数据的基础。那么数据库事务究竟是什么意思?数据库事务又有什么特性呢?下面大家就跟随本文一起来搞懂数据库事务吧!
举个例子:A(余额1500元)向B(余额500元)银行转账500元,这里面会涉及到两个操作。
1、 A的账户余额减少500,此时余额应为1000元。
2、 B的账户余额增加500,此时余额应为1000元
如果这两个操作中间出现了失误,比如银行系统突然崩溃了,导致A账户余额减少500,但是B账户余额并没有增加,这样的系统明显是有问题的。要么A转账成功(两个操作全部完成),要么A转账失败(两个操作全部不执行),这样AB用户才能接受这样的转账结果。
所以,事务指的就是一个操作,由多个步骤组成,要么全部成功,要么全部失败。
从数据库的角度来理解,事务指的是对数据库操作的序列,是一个不可分割的工作单位,这个序列中的操作要么全部执行,要么全部不执行。
数据库事务具有四个特性,称为 ACID 特性:
1、 原子性
事务是最小的执行单位,不允许分割。事务的原子性保证操作全部执行或全部不执行。
2、 一致性
一致性表示在执行该事务操作前后,从一个正确状态转换为另一个正确状态。以银行转账为例,转账前AB余额共有1500+500合计2000元,转行后AB余额应为1000+1000合计2000元,两种状态的合计余额应是一致的,不会多或者少。
3、 隔离性
隔离性表示多个事务并发执行时,相互之间不会产生影响,各并发事务之间数据库是独立的。
A向B转账过程中,只要事务还未提交,那么此时AB两账户的余额不会有变化。如果A向B转账(执行了一个事务)的同时,C又向B转账(执行了另一个事务),当两个事务都结束时,B账户的余额应为“原余额+B转账金额+C转账金额”。
4、 持久性
一个事务被提交之后,对于数据库中数据的改变是永久的,即使数据库发生了故障修改的数据也不会丢失。
对于两个并发执行的事务,如果涉及到对同一条数据做的操作,可能会出现以下问题:
1、 脏读(Ditry Read / Read Uncommitted)
脏读,是指一个用户读取到了另一个用户没有提交的数据。如:
用户A和用户B提交事务之后,发现最后的库存为1。但是因为A的提交回滚了,所以正确的库存应为5。
如何解决脏读呢?读已提交。控制一个事务只能读取其他事务提交后的数据。
2、 不可重复读(Unrepeatable Read)
不可重复读,是指同一个事务中,两次读取相同数据,返回的结果不一样。
不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的记录加锁,这可能导致锁竞争加剧,影响性能。
3、 幻读(Phantom Read)
前面讲的不可重复读是发生在两次读取之间,数据被更新了的情况。如果两次操作之间,插入了新的数据呢?
上面例子中,用户B的更新结果与预期不符,仿佛产生了幻觉。
不可重复读和幻读,是两个容易混淆的概念,不可重复读是发生在一行数据上的,因此可以通过锁定行来解决。幻读是发生在多行记录中的,因此可以通过锁定表来解决
为了解决上面的并发问题,数据库系统提供了隔离级别的概念。
在数据库中多个SQL语句在同一时刻修改数据,会产生并发控制的问题,如果不加以控制,就会造成事务中的隔离性被破坏,引起不可预知的错误。实现并发访问可以采用两种类型的锁,即读锁/共享锁和写锁/排它锁:
以上就是数据事务库的内容与特性,如果您想进一步了解与学习,欢迎留言评论与我们交流。