关键字:
事务、事务的ACID特性、事务的隔离级别
1.什么是事务?
事务(Transaction)是并发控制的基本单位,所谓事务是一个操作序列,这些操作要么都做,要么都不做,是一个不可分的工作单位。
2.为什么使用事务
以银行转账为例,小红给小明转账,这个业务的执行流程是这样的:
(1)小红账户-500
(2)小明账户+500
如果该转账操作执行了一半,断电了或者程序奔溃了,那么小红账户的钱就永久消失了?那么事务就显得尤为重要,事务可以解决这个问题,事务将一组操作封装为一个执行单元,要么一起成功,要么一起失败,该例子具体操作如下图所示:
如果在执行上面的sql语句时出现了网络错误,小红的账户就会减少500元,但是小明账户没有增加对应的500元,就会发生错误,带来麻烦。
3.事务的使用
- 事务通常以BEGIN开始,以COMMIT或ROLLBACK操作结束。
2.事务的提交:
(1)提交事务意味着在该事务中所做的所有修改都成为永久的。
(2)KingbaseES事务提交的具体过程:
●在SGA中的REDO日志缓冲区的RODO日志项写到连接REDO日志文件
●释放所有的锁。
●对事务标志“完成”。
(3)注意:对一提交的事务的修改,存储在SGA的数据缓冲区中,并不一定立即写到磁盘中。
3.事务回滚
(1)事务回滚意味着由一个未提交的SQL语句所做的任何修改都被撤销。KingbaseES允许任何未提交的事务回滚。
(2)KingbaseES事务回滚的实现:
●在一个事务内可以声明保存点,保存点通常用作把一个长事务分解成小块。
●使用保存点可以在长事务内的任意点加标记,在以后事务回滚时回滚到事务内保存点之后。
4.事务的ACID特性
为了保证数据库中的数据一致性,确保KingbaseES 能够在并发访问和系统发生故障时对数据进行维护,事务作为数据库工作的基本单位,具有下列四个特性,称为事务的 ACID 特性。
(1)原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败,不会出现执行一半的情况,把这种特性叫做原子性。原子性是事务最重要的特性,全部执行失败并不是不执行,而是通过逆操作rollback回滚数据。
(2)一致性(Consistency):事务执行前后的数据必须保持一种合法的状态,也就是事务总是从一个一致状态到另一个一致状态。
(3)隔离性(Isolation):多个事务并发执行时,事务之间相互隔离,一个事务在执行的时候不影响另一个事务。
(4)持久性(Durability):事务执行成功之后,所有被修改的数据都会被永久的保存下来。
5.事务的隔离级别
事务隔离级别是指一个事务的隔离级别决定当其他事务并行运行时该事务能看见什么数据,主要包含以下四种隔离级别:
1.读未提交(READ UNCOMMITES)
(1)读未提交概念:
在此隔离级别的事务中,可以读取到其他事务未提交的数据,而未提交的数据如果发生了回滚操作,那么此事务读到的数据就是脏数据,这种情况叫做脏读。
(2)脏读的实现步骤:
●在数据库test中创建account表并插入数据:
●设置当前客户端1事务隔离级别为读未提交并开启事务:
●客户端2开启事务:
●客户端2执行修改操作给小红账户+1000:
●客户端1执行了查询操作,查询到了客户端2未提交的数据即脏读:
●客户端2执行了回滚操作,那么客户端1读到的就是脏数据:
●结论:事务隔离级别为读未提交时存在脏读问题。
2.读已提交
(1)读已提交概念:
读已提交可以解决脏读的问题,但它存在不可重复读的问题。该隔离级别的事务能读到已经提交事务的数据,因此它不会有脏读问题,但它由于事务的执行中可以读到 其他事务提交的结果,所以在不同时间的相同SQL查询中,可能会得到不同的结果,这种现象叫做不可重复读。不可重复读就是在一个事务中使用相同的SQL,执行两次得到了不同的结果,在一个事务的两次查询中间,另一个事务把这条数据修改了,这个就叫做不可重复读。读已提交是KingbaseES默认的事务隔离级别。
(2)不可重复读的实现步骤:
●在数据库test中创建city表并插入数据:
●设置客户端1的事务隔离级别为读已提交并开启事务:
●客户端1执行查询id=1的数据:
●客户端2开启事务,执行了修改操作将id为1的城市改名为长安,并且提交事务:
●客户端1再一次查询id=1的数据:
在客户端1中前后执行相同的SQL语句得到了不同的结果,这就是不可重复读:
●结论:读已提交的事务隔离级别可以解决脏读问题,但是它存在不可重复读的问题。
3.可重复读
(1)可重复读的概念:
可重复读它能确保同一事务多次查询结果一致,但是它会出现新的问题,当同一SQL查询语句在不同的时间执行产生不同的结果,就是事务中的幻读问题。幻读就是一个select语句被执行了两次,但是第二次返回了第一次没有返回的一行,那么这个现象就叫做幻读。
(2)幻读实现步骤:
●在数据库test中创建city表并插入数据:
●设置客户端1的事务隔离级别为可重复读并开启事务:
●客户端1执行了一个查询操作:
●客户端2开启事务并且添加了一条数据,然后提交事务:
●执行查询操作,查询语句和上面步骤中的语句一致:
●客户端1使用相同的SQL语句两次查询的结果不一致,第二次查询比第一次多了一条数据,这多出来的一条数据就是幻读问题。
●可重复读的事务隔离级别可以解决不可重复读的问题,但存在幻读的问题。
4.序列化
序列化是事务的最高隔离级别,它会强制事务排序,使之不会发生冲突,从而解决了脏读,不可重复读和幻读的问题,但因为执行效率低,所以真正的使用场景并不多。
- 综上所述我们得出了在事务不同隔离级别中所存在的问题,SQL 标准实现的事务隔离级别中存在的问题如下所示:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 可能 | 可能 | 可能 |
读已提交 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 可能 |
序列化 | 不可能 | 不可能 | 不可能 |
6.KingbaseES的事务隔离级别:
(1)read commit (默认值)
●事务中的查询只能看到该查询执行之前提交的数据
●并发更新同一个元组时,一个事务提交,另一个事务对新元组进行更新(满足更新条件)
(2)Serializable
●事务中的查询只能看到该事务执行之前提交的数据。
●并发更新同一个元组时,一个事务提交,另一个事务回滚。
- 设置事务隔离级别
(1)设置一个事务的隔离级别
set transaction isolation level read commit/serializable/readonly
(2)设置一个会话以后所有事务的隔离级别
alter session set.....
6.数据库对事务的管理
1.事务的管理,KingbaseES 支持事务的隐式和显式提交,即自动提交和非自动提交。
(1)提交事务
默认一个 SQL 语句为一个事务,当此语句执行成功后,由系统隐式提交。数据更改被数据库接受。当 SQL 执行失败,自然视做回滚,不对数据造成影响。KingbaseES默认提交事务方式为自动提交。
(2)非自动提交事务
事务的开始为第一个 SQL 语句。事务的结束必须用户显式的使用 COMMIT 语句提交整个事务或者使用 ROLLBACK 语句回滚整个事务。如果客户端连接断开,那么未提交的事务做回滚操作。 当用户想自己控制事务的执行,可以显式的用 BEGIN 语句开始一个事务,然后在事务结束时应该使用 COMMIT 或 ROLLBACK 语句显式提交。
接口中也有对事务提交方式的控制,配置相应的配置文件可以使会话处于自动提交或非自动提交模式。
一个事务提交对数据库实例造成如下影响:
●所有数据库更改对整个数据库生效。
●保证此事务产生的日志写到磁盘。
●释放所有此事务进行过程中申请的锁。
●数据库标记此事务结束。
- 一个事务回滚对数据库实例造成如下影响:
●撤销所有对数据的更改到此事务开始之前的状态。
●释放所有此事务进行过程中申请的锁。
●数据库标记此事务结束。
7.总结
本文主要介绍了事务的基本概念、事务的ACID特性以及事务的隔离级别。