在数据库中新建一个字段并且设置为索引列,还有删除整张表的数据,类似这些操作都是一系列操作的组合,执行后不能出现中间状态,也就是不会出现新建了字段却不是索引的情况,也不会出现只有一部分数据被删除的情况。这种保证是事务在发挥作用,虽然我们没有使用begin-transaction-commit来执行命令。

既然事务是一系列操作的组合,那两个事务的多个操作如何正确顺序执行和如何高效执行就是关键了。这就要说说事务的ACID原则了,ACID指的是原子性、一致性、隔离性、持久性。

假设有这么一个场景,用户A的初始余额是100元,用户B的初始余额是0元,用户A需要向用户B转账100元。这个场景事实上是分二步执行的,第一步是扣除用户A账号上的100元,第二步是给用户B账号的余额增加100元。最终状态是用户A余额为0元,用户B的余额为100元。

不过,在执行扣除和增加这两步时随时可能发生错误。比如业务属性不匹配,用户B的账号有敏感操作被冻结了,无法更新,所以要恢复到初始状态。又比如系统崩溃了,所以系统重启时要首先进入安全模式,已提交的事务要继续完成,未提交的事务要取消掉。这样才能保证事务操作要么全部成功,要么全部失败。

那如何恢复到初始状态或者取消未提交的事务呢?

执行操作前把之前的值备份下来,不就可以借助备份进行递向操作了嘛?没错,在数据库的体现就是Undo log回滚段。

前面描述的事务场景可能过于简单,我们考虑这么一件事,用户C在刚才的事务执行过程中给用户B成功转入了300元,也就是说同时有多个事务在执行。不幸的是,刚才的事务被回滚了,用户B的余额最终被更新成了0元。后果就是用户C的转入操作好像没发生过一样,成了一笔坏账。

这个问题的原因是原子性不能保证可见性,当前事务看不到其它事务提交的结果,这才导致了数据的不一致。事实上可以使用排它锁来保证一致性。对账号A和账号B这两个资源进行加锁,事务获得锁才能执行,执行完才释放锁。这样事务是串行化执行的,当前事务肯定是能看到前一个事务提交结果的,数据一定是强一致性的。

使用到锁就要考虑死锁问题了,死锁问题说的是两个进程在不同方向抢占相同的共享资源。我们可以通过碰撞检测来发现系统中是否存在死锁,每个进程都记录已拥有和等待中的锁,如果出现了回环,说明有死锁。解决死锁的一般办法是锁等待超时。

使用锁时除了死锁还要考虑性能问题,排它锁是简单粗暴的方法,但是性能有点不忍直视。这时就得考虑一些优化策略了,比如减少锁的覆盖范围、减少锁的持有时间、使用并行代替串行。

数据库的设计大师正是考虑到这些,才引入了事务隔离性。

第一种事务隔离性是序列化读写。所有的事务放入到队列中依次执行,比如读写-写读-读读-写写。

第二种是读已提交。当前事务只能读取到其他事务已提交的结果,这种隔离下读-读、读-写都是可以并行执行的,因为当前事务依赖的数据是前一个写操作的结果。

第三种是可重复读。在同一个事务中,多次读取到的结果是一致的。这种隔离下读-读、读-写都是可以并行执行的。

第四种是读未提交。当前事务能看到其他事务还没有提交的中间状态,这种隔离下,只有写锁,读是不加锁的,所以除了写-写,读-写、写-读、读-读都是可以并行的。代价是出现脏读。

透过这四种事务隔离,明显能看到读写锁带来的收益,那能不能再优化下呢?

答案是可以的,秘决就是多版本并发控制MVCC,它的本质是写时复制Copy on write。行记录每次修改时都会产生一个快照和一个版本号,版本号是单向增长的逻辑时间戳,用来表示先后顺序。而读操作只会读取到早于当前事务版本的记录。显然,这种技巧非常适合读多写少的场景,而且能达到读未提交的并发度,隔离级别更好。

既然读-写、写-读、读-读都是可以并行的,写-写也能并行就更好了。

我们先来看下写-写并行会有什么问题。假设用户A要给用户B转账100元,用户B也要给用户A转账100元,考虑到事务间原子操作顺序的不可见性,用户A的余额可能会在原来基础上增加了100元,银行得损失100元。针对这种情况,需要借助乐观锁的思想来保证数据的一致性,针对同一行记录,只有高版本的事务更新能成功,低版本的事务更新得回滚掉。缺点是并发高时失败率高,需要不断重试。

除了事务隔离,数据库设计的大师为了提高并发效率,还做了很多优化。比如每次写操作并不直接持久化到磁盘中,而是暂时存放在易丢失的内存中,然后通过一定的机制异步同步到磁盘。这样就保证了数据的持久性,确保事务一旦提交,操作肯定会固化到数据库中。类似生活中这种场景,餐馆老板娘很忙的时候,就把每笔交易写在黑板上,当老板娘空闲、黑板写满或者餐馆打烊后再整理写入到账本中。

谈谈数据库的事务ACID的更多相关文章

  1. 数据库零基础之---了解数据库的事务[ACID]

    事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功. 我们先举一个例子来描述一下事务: 假设要张三通过银行给李四进行转账1000元钱,张三原有余额10000元整,李四有人民币 ...

  2. 数据库事务ACID详解(转载)

    转载自:http://blog.csdn.net/shuaihj/article/details/14163713 谈谈数据库的ACID 一.事务 定义:所谓事务,它是一个操作序列,这些操作要么都执行 ...

  3. 【转】数据库事务ACID以及事务隔离

      本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指 ...

  4. 数据库中事务的四大特性(ACID)

    本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务 ...

  5. 【数据库】事务,ACID,CAP和一致性

    什么是事务 事务是指由一系列数据库操作组成的一个完整的逻辑过程,这个过程中的所有操作要么都成功,要么都不成功.比如:常见的例子就是银行转账的例子,一次转账操作会包含多个数据库操作,而这些数据库操作需要 ...

  6. 带你了解数据库中事务的ACID特性

    前言 前面我们介绍过数据库中 带你了解数据库中JOIN的用法 与 带你了解数据库中group by的用法的相关用法.本章节主要来介绍下数据库中一个非常重要的知识点事务,也是我们项目中或面试中经常会遇到 ...

  7. 谈谈数据库的ACID

    一.事务 定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位. 准备工作:为了说明事务的ACID原理,我们使用银行账户及资金管理的案例进行分析. // 创建 ...

  8. spring 传播行为与数据库事务ACID

    数据库事务ACID特性 数据库事务正确执行的4个基础要素是原子性(Atomicity).一致性(Consistency).隔离性(Isolation)和持久性(Durability). •原子性:整个 ...

  9. 数据库事务ACID特性(原子性、一致性、隔离性、持久性)

    ACID特性: 原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持久性(Durability) 原子性:一个事务必须被视为一个不可分割的最小工作单元,整个 ...

随机推荐

  1. 单元测试利器Mockito框架

    什么是Mock Mock 的中文译为仿制的,模拟的,虚假的.对于测试框架来说,即构造出一个模拟/虚假的对象,使我们的测试能顺利进行下去. Mock 测试就是在测试过程中,对于某些 不容易构造(如 Ht ...

  2. 一张图对比React、Angular、Vue.js

    文章原文地址:https://baijiahao.baidu.com/s?id=1609374985643812253&wfr=spider&for=pc

  3. Python基础(闭包函数、装饰器、模块和包)

    闭包函数 格式: def 函数名1(): def 函数名2(): 变量 = 值 return 变量 return 函数名2 func = 函数名1() key = func()

  4. Python爬取网易云音乐歌手歌曲和歌单

    仅供学习参考 Python爬取网易云音乐网易云音乐歌手歌曲和歌单,并下载到本地 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做 ...

  5. GET和POST的本质区别

    前言:相信小伙伴们面试时候一定都遇到过这个问题,即使没有遇到过,至少也听说过,网上资料一大片,大概每个人都能说出来一些.但是总感觉面试装逼不成功,所以就翻阅了部分资料,进一步整理了下. 一般当我们提到 ...

  6. vue 中使用echarts

    前言:在vue2.0中使用百度echarts有三种解决方案. 一.原始方法直接使用 这样每次都要获取图表dom元素 然后通过setOption渲染数据,最后在mounted中初始化.很麻烦. < ...

  7. Android Studio或者Eclipse中的最常用的快捷键,最简单的,部分不适用eclipse

    重写方法:ctrl+shift+s  然后选择Generate 构建即可: 执行程序:shift+F10 多行注释:ctrl+shift+/ 单行注释:ctrl+/ 快速打印log:logr 快速复制 ...

  8. Database4.exe用来导入excel

    从ACCESS数据库导出的EXCEL表格,可以通过database4.exe来连接,并导出sql脚本,再用database4.exe来连接ACCESS并先创建于脚本结构一致的表,然后复制脚本,从新生成 ...

  9. ios bug 分析

    ios中线上或者内部测试bug统计收集有两种方法: 1)使用第三方bug收集 1.bugHD 来源http://bughd.com/doc/ios-customize 2.bugtags 来源http ...

  10. 深入理解计算机系统 Start && 第一章要点

    对此书已经慕名已久了,抽空看了第1,2,3,5章,其他章节等有空闲继续看吧. 我的许多博客是给自己快速复习使用的,比如此读书后感,你可以根据我下面的建议读完原书几章再回来复习一下(或许那时候就没必要回 ...