详解关系型数据库ACID四个特性和怎么去做事务控制
概述
数据库管理系统中事务(transaction)的四个特性(分析时根据首字母缩写依次解释):原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
ACID特性
所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。(执行单个逻辑功能的一组指令或操作称为事务)
1. 原子性
原子性是指事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。
可采用“A向B转账”这个例子来说明解释
在DBMS中,默认情况下一条SQL就是一个单独事务,事务是自动提交的。只有显式的使用start transaction开启一个事务,才能将一个代码块放在事务中执行。
2. 一致性
一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
如A给B转账,不论转账的事务操作是否成功,其两者的存款总额不变(这是业务逻辑的一致性,至于数据库关系约束的完整性就更好理解了)。
保障机制(也从两方面着手):数据库层面会在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,check约束等)和触发器设置;此外,数据库的内部数据结构(如 B 树索引或双向链表)都必须是正确的。业务的一致性一般由开发人员进行保证,亦可转移至数据库层面。
3. 隔离性
多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。
在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
事务最复杂问题都是由事务隔离性引起的。完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能。
关于隔离性中的事务隔离等级(事务之间影响),参见相应博文
4. 持久性
这是最好理解的一个特性:持久性,意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。(完成的事务是系统永久的部分,对系统的影响是永久性的,该修改即使出现致命的系统故障也将一直保持)
write ahead logging:SQL Server中使用了WAL(Write-Ahead Logging)技术来保证事务日志的ACID特性,在数据写入到数据库之前,先写入到日志,再将日志记录变更到存储器中。
事务的控制
事务的开始是隐形声明的,不用也没有语句可以进行操作,默认从对数据的修改开始就开始了当前事务。
对数据库的设置主要有一下语句:
SET TRANSACTION-----设置事务属性
SET CONSTRANS-------设置约束模式
SAVEPOINT-----------建立存储点
RELEASE SAVEPOINT---释放存储点
ROLLBACK------------回滚
COMMIT--------------提交
1、设置事务属性
设置事务属性主要可以用来完成以下工作:
* 指定事务的隔离层
* 规定回滚事务时所使用的存储空间
* 命名事务
注:SET TRANSACTION必须是事务的第一个语句。并在事务终止后自动失效。
SET TRANSACTION ISOLATION LEVEL READ COMMITED
A事务设置为READ COMMITED,该开始后B事务修改了数据,此时A无法得到新数据,B提交之后,A可以查询到更新数据。 A不可能错读,但可能发生假读和非重复读。
在需要并发数很大时应该使用READ COMMITED,对于多用户并发的性能和响应速度都比较好。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
事务和事务之间完全隔离开,事务以串行的方式执行。不是说必须等一个结束,而是事务一旦开始,在结束之前查询到的数据永远是开始时刻的数据。由于留存的模式会比较多,所以会消耗一定的系统资源。
SET TRANSACTION READ ONLY
当前事务不能有任何修改数据的操作,READ ONLY是SERIALIZABLE的一个子集,基本上属于最高的安全级。
SET TRANSACTION READ WRITE
在READ的基础上增加WRITE权限,不常用
2、设置约束延期性
在操作过程中可能需要违反约束向表中插入重复的数据,其实需要设置约束延期性。
设置格式如下:
SET CONSTRAINT ALL | <constraint_name>
DEFERRED | IMMEDIATE
可以选择要延期的约束名,也可以使用ALL关键字延期所有的约束
DEFERRED表示延期,IMMEDIATE表示应用
注:理论上在COMMIT前需要设置回IMMEDIATE,但是系统可以隐式自动完成这一操作。
注意:要使用延迟的约束,必须在创建时就进行说明:
ALTER TABLE T1 ADD CONSTRAINT <constraint_name> DEFERRABLE INITIALLY IMMEDIATE
后面的DEFERRABLE 指名可以使用延迟,INITIALLY 设定了初始值
3、存储点
由于事务太大,一次回滚会对系统造成很大的压力。而且有时候在某一段特定的代码附近会特别发生错误而回滚。这时就需要在希望的地方设置一个存储点,可以显示得操作数据在发生错误时回滚到指定的存储点,而节省不必要的开销。
创建格式如下:
SAVEPOINT <savepoint_name>
使用格式如下:
ROLLBACK TO [SAVEPOINT] <savepoint_name>
4、结束事务
以下操作为将事务结束:
* 使用COMMIT提交事务,数据被永久保存
* 使用ROLLBACK回滚事务(不包括回滚到存储点)
* 执行DDL时,结束默认COMMIT
* 用户断开连接,此时事务自动COMMIT
* 进程意外中止,此时事务自动ROLLBACK
注:事务COMMIT时会生成一个唯一的系统变化号(SCN)保存到事务表
ACID特性是关系数据库的一个很重要的特点,也是面试过程中会经常问的一个点,大家还是要多熟悉下的。
后面会分享更多关于devops和dba方面的内容,感兴趣的朋友可以关注下~