在数据库中新建一个字段并且设置为索引列,还有删除整张表的数据,类似这些操作都是一系列操作的组合,执行后不能出现中间状态,也就是不会出现新建了字段却不是索引的情况,也不会出现只有一部分数据被删除的情况。这种保证是事务在发挥作用,虽然我们没有使用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. go语言之抛出异常

    一: panic和recover 作用:panic 用来主动抛出错误: recover 用来捕获 panic 抛出的错误. 概述: ,引发panic有两种情况 )程序主动调用panic函数 )程序产生 ...

  2. 一个简单的Android音乐播放器

    Android小白的期末作业 Android期末项目,仅用作学习使用,在线音乐部分只获取了网易云热歌榜,API来自鼻子亲了脸 传送门: GitHub 参考: anddiencn 实现功能 展示出本地的 ...

  3. Kafka Broker源码:网络层设计

    一.整体架构 1.1 核心逻辑 1个Acceptor线程+N个Processor线程(network.threads)+M个Request Handle线程(io threads) 多线程多React ...

  4. hdu6704 2019CCPC网络选拔赛1003 K-th occurrence 后缀数组

    题意:给你一个长度为n的字符串,有q个询问,每次询问一个子串s(l,r)第k次出现的位置,若子串出现次数少于k次输出-1. 解题思路:先把SA跑出来,然后对于每次询问可以由l和rank[]找到l在所有 ...

  5. mock之初体验

    刚接触vue的时候,看到github上有人的开源项目介绍使用mock可以模拟接口调用,可以使用模拟数据避免跟后端交互也可以实现前端功能的完美展现,当时觉得卧槽,mock这个东西这么神奇的吗?那一定要学 ...

  6. SSM整合+WebUpload使用(spring+springmvc+mybatis+maven)

      SSM框架整合以及webupload的集成与使用 在项目中最近用到了webupload.js,也方方面面遇到了不少问题,比如上传文件前对表单参数校验,当校验失败不予提交,及在文件上传成功后,选择同 ...

  7. Johnson全源最短路

    例题:P5905 [模板]Johnson 全源最短路 首先考虑求全源最短路的几种方法: Floyd:时间复杂度\(O(n^3)\),可以处理负权边,但不能处理负环,而且速度很慢. Bellman-Fo ...

  8. IE9 报错 script1004缺少“;”

    在IE9中不支持 let关键字,修改为var就可以了 作者:彼岸舞 时间:2020\07\31 内容关于:工作中用到的小技术 本文来源于网络,只做技术分享,一概不负任何责任

  9. docker 停止、启动、删除镜像指令

    容器 docker ps // 查看所有正在运行容器 docker stop containerId // containerId 是容器的ID docker ps -a // 查看所有容器 dock ...

  10. Linux通过命令行将英文改成中文

    1.首先查看当前系统是否有中文语言包 locale -a 如果没有zh_CN.utf8,就需要下载中文语言包,否则,如果有中文语言包,跳过第二步. 2.安装中文语言包 Ubuntu: sudo apt ...