您当前的位置:首页 > 电脑百科 > 数据库 > 百科

一文讲透数据库事务的四原则

时间:2020-01-04 09:58:16  来源:  作者:

说到数据库,以前我老师有一句很经典的话。你可以不会写SQL,但是一定不能不知道ACID

 

在工业领域,SQL可以说是应用最广泛的技术。从后端到算法,从数据到DBA,再到产品,甚至连一些运营也会基本的SQL。所以如果你现在还不太会的话,我建议你用一个下午的时间找个网站好好学一下。

 

原本我是想直接写些Hbase相关的内容,但是我发现要想讲清楚Hbase,必须要讲noSQL数据库。如果将noSQL,则又离不开最传统的关系型数据库。所以我们一步一步来,先从基础的关系型数据库讲起。或许我这么说并不准确,因为数据库并不基础,相反它十分复杂。从索引到各种优化和设计原理,再到内部的各种算法和数据结构,涉及到的内容非常多。我们先把浩如烟海的知识放一放,先从最核心的数据库四大原则开始说起。

 

数据库事务ACID四大原则,A代表Atomicity,即原子性。C表示Consistency,即一致性。I表示Isolation,即隔离性。D表示Durability,即持久性

 

这四个原则了解过数据库的应该都如雷贯耳。可是真正面试的时候被问起来,能一个不落说得上来,并且讲得清楚原委的就不多了。我觉得主要是因为我们的翻译过于文雅,不像英文那么直观,所以很难顾名思义。另一个原因是我们在学习的时候理解不够深入,只知道原因,不知道原因的究竟。所谓知其然,不知其所以然。

 

一文讲透数据库事务的四原则

 

 

原子性

 

让我们先从其中最简单的原子性开始。

 

原子性理解起来最简单,也最常用。我就在面试当中遇见过不止一次,还有一次让我用JAVA写一个转账的功能,其实就是想看看我知不知道原子性。

 

原子两个字看起来一头雾水,其实这里不是指物理学上的基本粒子,而是指的不可分割的意思。也就是说在一个事务当中的所有操作应该被视为一个不可分割的整体,要么全成功,要么全部失败。这点用转账这个问题举例最合适。A将银行卡里的钱转100给B,很明显,数据库需要做两件事情,一件事A账户扣款100,另一件是B账户收入100。但问题来了,计算机系统并不是100%可靠的,可能会存在极小的可能失败。如果A扣款之后,发生网络延迟或者系统down机,导致B账户的钱没有增加,那怎么办?A不是白白扣了钱?

 

一文讲透数据库事务的四原则

 

 

A白白扣了钱是小事,一个金融系统如此不稳定,显然是不能接受的。所以,在数据库的事务当中,应该保证原子性。扣钱和收钱虽然是两个操作,但是应该被视为一个。要么一起成功,要么一起失败。失败了还可以重试,如果成功了一半,那都不知道该怎么修复了。

 

事务的一种实现方法是在执行的时候先不将最终的结果更新到数据库,而是先写在事务日志上。等整个事务执行成功之后,再将事务日志上的内容同步到数据库当中。如果失败了,则将事务日志删除,完成回滚。

 

持久性

 

第二个要介绍的是持久性。

 

持久性指的是数据的持久性,指的是事务完成了之后,这个事务对数据库所作出的修改就被持久地保存进了数据库当中,不会再被回滚操作影响。即使出现了各种事故,比如机房断电、网络故障等等意外情况,数据库当中的数据也不能丢失。

 

但是前文当中说了,计算机系统很难做到100%可靠。如果万一的情况发生了,数据库当中的数据丢了,那么应该怎么办呢?

 

没关系,之前在介绍原子性的时候介绍过了。所有的事务操作在执行之前,都会先把数据记录到事务日志当中,再同步到数据库。即使是数据库里的数据丢失了,那么只要根据事务日志重新执行一遍对应的操作,就可以恢复数据库当中的数据,维持数据库的持久性。实际上,现在的数据库默认会将所有的操作都当做事务来执行,因此基本上不用担心数据丢失的情况。

 

隔离性

 

然后,介绍的是隔离性。

 

在我们理解了原子性之后,隔离性就很好理解了。当我们同时有多个事务一起执行的时候,如果隔离性做得不好,很有可能导致很多问题。

 

以下四种问题最常见:

 

1. 脏读

 

脏读是指一个事务读到了另一个事务执行的中间结果。还用我们刚才的转账的例子举例:

 

一文讲透数据库事务的四原则

 

 

当我们转账的事务没有执行完,另一个事务就读取了它的中间结果,很有可能就造成脏读。因为万一之前的事务回滚,那么新读取到的结果就是错的,和A账号回滚之后的余额不一致。如果这个数据应用在其他的系统当中,就会引起大规模的数据问题。

 

2. 不可重复读

 

不可重复读的意思是说,如果在一个事务当中,我们读取了某个数据两次。刚好在这中间,有另一个事务修改了这条数据,那么同样会引起数据错误,因为这两次读取到的结果不一致。

 

一文讲透数据库事务的四原则

 

比如我们对A账户的一个事务还没有结束,这时候它的结果就被其他事务修改了。那么程序就会发生错乱,因为读到了它没有预料到的修改。

 

解决方法是针对当前修改的数据进行隔离,同一时刻只允许一个事务对该条数据进行修改,以保证数据的一致性。

 

3. 幻读

 

幻读的概念也很简单,就是一个事务读取两次,读到的数据条数不一致。这点和不可重复读非常类似,不过不同的是不可重复读针对的是确定的某一条数据,而幻读指的是对整个数据库或者是整个表而言。

 

一文讲透数据库事务的四原则

 

 

要解决也很简单,因为幻读是其他事务修改新增或者修改其他数据产生的,所以要排除掉这种情况,只针对我们修改的数据进行加锁和隔离是不够的。我们需要将整个数据库,或者是分区进行隔离,同一时刻,只允许一个事务对一个分片或者是数据表进行修改。

 

4. 更新丢失

 

更新丢失的定义很直观,当我们针对一条数据进行修改的时候。同时也有另一个事务在修改同一条内容,会导致后者覆盖前者的内容。比如说账户里原本100元,A事务往账户里添加10元,B事务往账户里扣除20元。A修改成110的同时,被B事务的80所覆盖,导致A的操作就像是没有执行过一样,引起更新丢失。这个问题在并发场景当中也最为经典。

 

一文讲透数据库事务的四原则

 

 

解决的办法同样是做好隔离操作,在一个写入完成之前,禁止其他事务的读入。事实上更新丢失是并发场景下最容易出现的错误,而且如果设计不合理,出现了错误也会非常难排查。

 

数据库解决隔离性问题的办法就是设置不同的隔离级别,不同的隔离级别对应不同的隔离策略,可以保证不同级别下的隔离性。不同的隔离级别意味着使用不同级别的锁,显然隔离级别越高意味着性能越差。所以这就需要数据库管理员(DBA)对于当前的应用场景,以及并发量和数据风险有一个非常清楚的认知。能够在性能和安全性之间做一个权衡。这里,我们不多做具体的探究,观察一下下图,简单了解一下即可:

 

一文讲透数据库事务的四原则

 

 

从上到下以此是四种隔离级别,越往下隔离级别越高,能够解决的隔离性问题也就越多。同样的,用到的锁也就越多,系统的性能也就越差。

 

最上面未提交读是最低的隔离级别,在读取的时候并不会判断是否可能会读取到没有提交的数据。所以它的隔离性最差,连最简单的脏读都无法解决

 

已提交读则是通过锁限制了只会读取已经提交的数据,读数据的时候使用的共享锁,在读取完成之后立即释放。这种隔离级别只能够解决最常见的脏读问题,它也是SQL server数据库的默认隔离级别

 

可重复读的读取过程和已提交级别一样,但是在读取的时候会保持共享锁,一直到事务结束。也就是说只要一个事务没有结束,锁就不会释放。其他的事务无法更新数据,保证了不会出现不可重复读的情况。

 

最后是可串行读,它是在可重复读的基础上进一步加强了隔离性。在事务进行当中,不仅会锁定受影响的数据本身,而且还会锁定整个范围。这就阻止了其他事务影响整体的情况出现。在这个隔离级别下,保证了事务之间不会有任何踩踏。

 

到这里,数据库事务四大原则当中的三个就介绍完了,内容看起来不少,但其实还没有结束,关于隔离的实现会牵扯到锁的使用,这块深挖下去,又会牵扯许多内容。不过对于我们算法从业者而言,能够了解到这一层,也差不多够了。

 

四原则当中还剩下一个一致性原则,一致性这个单词在很多地方都出现过,比如分布式存储系统、多副本的一致性等等。但是这些概念的意思并不相同,不可以简单地理解成同一回事。数据库的一致性表示数据的状态是正确的,在转移的时候,是从一个正确的状态转移到了另一个正确的状态。正确的状态其实就是指不出错的状态,也就是和程序员预期一致的状态。之前在介绍隔离性时谈到的种种问题,总结起来都是数据和程序员的预期不一致。也就是说如果和程序员的预期一致,就可以认为满足了一致性。

 

虽然一致性是数据库的四原则之一,但数据库系统当中并没有专门针对一致性的部分。其实在数据库眼中,满足了其他三原则,那么自然也就达成了一致性。一致性是目的,并不是手段。举个例子,还是以刚刚转账的情景距离。A向B转账100,我们都知道,前提条件是A的账户里的金额大于等于100,如果A账户里小于100,我们开发的时候没有做校验还强行转账成功。那么这个结果显然是错误的,也是和我们预期不一致的,但是这个问题发生的原因并不是因为数据库没有做好一致性,而是开发人员忽略了限制条件。

 

所以数据库的教材上才会写着“Ensuring the consistency is the responsibility of user, not DBMS.", "DBMS assumes that consistency holds for each transaction”。

 

“保证一致性是开发的责任,而不是数据库的,数据库假设每一个事务都符合 一致性。”

 

到这里,数据库事务的四原则就介绍完了,衷心祝大家,日拱一卒,每天都有收获。

 

喜欢本文的话,请顺手给个关注吧~



Tags:数据库   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
安装环境Linux服务器:Centos 6 64位Oracle服务器:Oracle11gR2 64位 系统要求说明:内存必须高于1G的物理内存;交换空间,一般为内存的2倍(1G的内存可以设置swap 分区为3G大小);硬...【详细内容】
2021-12-27  Tags: 数据库  点击:(2)  评论:(0)  加入收藏
《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的HasorDB 是一个全功能数据库访问工具,提供对象映射、丰...【详细内容】
2021-12-22  Tags: 数据库  点击:(5)  评论:(0)  加入收藏
作者丨Rafal Grzegorczyk译者丨陈骏策划丨孙淑娟【51CTO.com原创稿件】您是否还在手动对数据库执行各种脚本?您是否还在浪费时间去验证数据库脚本的正确性?您是否还需要将...【详细内容】
2021-12-22  Tags: 数据库  点击:(4)  评论:(0)  加入收藏
读取SQLite数据库,就是读取一个路径\\192.168.100.**\position\db.sqlite下的文件<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/...【详细内容】
2021-12-16  Tags: 数据库  点击:(21)  评论:(0)  加入收藏
测试的目的和原因,公司有很多程序员,每个程序员对数据库和表结构都有自己的理解。而且每个程序员的理解往往是以效率考虑。既然都是为了效率考虑,那么我就来测试一下究竟哪种使...【详细内容】
2021-12-08  Tags: 数据库  点击:(14)  评论:(0)  加入收藏
当你们考虑项目并发的时候,我在部署环境,当你们在纠结使用ArrayList还是LinkedArrayList的时候,我还是在部署环境。所以啊,技术不止境,我在部环境。今天这篇文章缕一下在同一台服...【详细内容】
2021-12-08  Tags: 数据库  点击:(17)  评论:(0)  加入收藏
概述DBConvert Studio 是一款强大的跨数据库迁移和同步软件,可在不同数据库格式之间转换数据库结构和数据。它将成熟、稳定、久经考验的 DBConvert 和 DBSync 核心与改进的现...【详细内容】
2021-11-17  Tags: 数据库  点击:(26)  评论:(0)  加入收藏
说明Web应用程序,MySQL数据库,数据库中有三张表:health_patient(病人表)、health_patient_account(病人账户表)、 health_patient_medical_history(病例表),视图需求是,页面分页展示病...【详细内容】
2021-11-05  Tags: 数据库  点击:(32)  评论:(0)  加入收藏
1. 介绍1.1 介绍今天开始我们来学习Java操作MySQL数据库的技巧,Java操作MySQL是借助JdbcTemplate这个对象来实现的。JdbcTemplate是一个多数据库集中解决方案,而我们今天只讲...【详细内容】
2021-11-05  Tags: 数据库  点击:(30)  评论:(0)  加入收藏
互联网时代,不论是个人还是组织,都将数据视为一项重要的资产。为了便于存储、管理,企业常常会为各项数据建立一个数据库,如果没有做好安全风险防护,一旦数据库被攻占,企业将迎来很...【详细内容】
2021-10-28  Tags: 数据库  点击:(50)  评论:(0)  加入收藏
▌简易百科推荐
1增1.1【插入单行】insert [into] <表名> (列名) values (列值)例:insert into Strdents (姓名,性别,出生日期) values (&#39;开心朋朋&#39;,&#39;男&#39;,&#39;1980/6/15&#3...【详细内容】
2021-12-27  快乐火车9d3    Tags:SQL   点击:(2)  评论:(0)  加入收藏
最近发现还有不少做开发的小伙伴,在写存储过程的时候,在参考已有的不同的写法时,往往很迷茫, 不知道各种写法孰优孰劣,该选用哪种写法,以及各种写法的优缺点,本文以一个简单的查询...【详细内容】
2021-12-23  linux上的码农    Tags:sql   点击:(9)  评论:(0)  加入收藏
《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的HasorDB 是一个全功能数据库访问工具,提供对象映射、丰...【详细内容】
2021-12-22  GitHub精选    Tags:HasorDB   点击:(5)  评论:(0)  加入收藏
作者丨Rafal Grzegorczyk译者丨陈骏策划丨孙淑娟【51CTO.com原创稿件】您是否还在手动对数据库执行各种脚本?您是否还在浪费时间去验证数据库脚本的正确性?您是否还需要将...【详细内容】
2021-12-22    51CTO  Tags:Liquibase   点击:(4)  评论:(0)  加入收藏
场景描述:由于生产环境的表比较复杂,字段很多。这里我们做下简化,只为说明今天要聊的问题。有两张表 tab1,tab2: tab1 数据如下: tab2 数据如下: 然后给你看下,我用来统计 name=&#3...【详细内容】
2021-12-20  Bald    Tags:SQL   点击:(7)  评论:(0)  加入收藏
前言知识无底,学海无涯,知识点虽然简单,但是比较多,所以将MySQL的基础写出来,方便自己以后查找,还有就是分享给大家。一、SQL简述1.SQL的概述Structure Query Language(结构化查...【详细内容】
2021-12-16  谣言止于独立思考    Tags:SQL基础   点击:(13)  评论:(0)  加入收藏
前言作为一名测试工程师,工作中在对测试结果进行数据比对的时候,或多或少要和数据库打交道的,要和数据库打交道,那么一些常用的 SQL 查询语法必须要掌握。最近有部分做测试小伙...【详细内容】
2021-12-14  柠檬班软件测试    Tags:SQL   点击:(15)  评论:(0)  加入收藏
话说C是面向内存的编程语言。数据要能存得进去,取得出来,且要考虑效率。不管是顺序存储还是链式存储,其寻址方式总是很重要。顺序存储是连续存储。同质结构的数组通过其索引表...【详细内容】
2021-12-08  小智雅汇    Tags:数据存储   点击:(18)  评论:(0)  加入收藏
概述DBConvert Studio 是一款强大的跨数据库迁移和同步软件,可在不同数据库格式之间转换数据库结构和数据。它将成熟、稳定、久经考验的 DBConvert 和 DBSync 核心与改进的现...【详细内容】
2021-11-17  雪竹聊运维    Tags:数据库   点击:(26)  评论:(0)  加入收藏
一、前言 大家好,我是小诚,《从0到1-全面深刻理解MySQL系列》已经来到第四章,这一章节的主要从一条SQL执行的开始,由浅入深的解析SQL语句由客户端到服务器的完整执行流程,最...【详细内容】
2021-11-09  woaker    Tags:SQL   点击:(35)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条