注册
达梦数据库原理学习之事务和事务隔离级别
培训园地/ 文章详情 /

达梦数据库原理学习之事务和事务隔离级别

Hi70KG 2023/08/25 1784 0 0

事务

事务简介

数据库事务是指作为单个逻辑工作单元的一系列操作的集合。一个典型的事务由应用程

序中的一组操作序列组成。

事务特性

原子性

这一组操作要么一起生效,要么都不生效,事务执行过程中如遇错误,已经执行的操作要全部撤回,这就是事务的原子性。

一致性

数据一致性是指表示客观世界同一事务状态的数据,不管出现在何时何处都是一致的、

正确的、完整的。换句话说,数据一致性是任何点上保证数据以及内部数据结构的完整性,

比如账户之间无论怎么转账,总额不会变等现实约束;年龄不能为负值。

隔离性

事务是隔离的,意味着每个事务的执行效果与系统中只有该事务的执行效果一样,也就

是说,某个并发事务所做的修改必须与任何其他的并发事务所做的修改相互隔离。

数据库为了提高资源利用率和事务执行效率、降低响应时间,允许事务并发执行。但是多个事务同时操作同一对象,必然存在冲突,事务的中间状态可能暴露给其它事务,导致一些事务依据其它事务中间状态,把错误的值写到数据库里。需要提供一种机制,保证事务执行不受并发事务的影响,让用户感觉,当前仿佛只有自己发起的事务在执行,这就是隔离性。

持久性

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其

他操作和数据库故障不应该对其有任何影响。

数据只要存储非易失存储介质,宕机就不会导致数据丢失。因此数据库可以采用以下方法来保证持久性:

事务完成前,所有的更改都保证存储到磁盘上了。
(2)提交完成前,事务的更改信息,以日志的形式存储在磁盘,重启过程根据日志恢复出数据库系统的内存状态。

事务开始

对于 DM 数据库来说,第一次执行 SQL 语句时,隐式地启动一个事务。

事务结束

显示事务结束

以 COMMIT 或 ROLLBACK 语句/方法显式地结束事务。

隐示事务结束

1)当连接的属性设置为自动提交时,每执行一条语句都会提交事务。

2)在执行 DDL 前,DM 数据库会自动把前面的操作进行提交,DDL 前面的操作作为一个完整的事务结束。DDL 语句本身所属事务则根据“DDL_AUTO_COMMIT”配置参数决定是否隐式地提交(注意,无论DDL_AUTO_COMMIT 参数如何设置,ALTER TABLESPACE 和 ALTER USER 操作总是自动提交的)。

3)事务所在的程序正常结束和用户退出;

4)系统非正常终止时。

保存点

为了提高事务管理的灵活性,数据库还提供了设置保存点(SAVEPOINT)和回滚到保存点的功能。保存点提供了一种灵活的回滚,事务在执行中可以回滚到某个保存点,在该

保 存 点 以 前 的 操 作 有 效 , 而 以 后 的 操 作 被 回 滚 掉 。 可 以 使 用 SAVEPOINT SAVEPOINT_NAME 命令创建保存点,使用 ROLLBACK TO SAVEPOINT SAVEPOINT_NAME

SQL> create table T1(id int,name varchar(10)); SQL> insert into T1 values(1,'a'); SQL> savepoint point01; SQL> insert into T1 values(2,'b'); SQL> select * from T1; 行号 ID NAME ---------- ----------- ---- 1 1 a 2 2 b SQL> rollback to savepoint point01; SQL> select * from T1; 行号 ID NAME ---------- ----------- ---- 1 1 a

事务隔离级别

三种读数据类型

脏读

如果一个事务在提交操作结果之前,另一个事务可以看到该结果,就会发生脏读。

脏读只有在读未提交的隔离级别下才会发生。读未提交隔离级别是最不严格的隔离级别。

SQL>  SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SQL>  select isolation from v$trx;

行号     ISOLATION  
---------- -----------
1          0

image.png

从上面可以看到,在设置读未提交的隔离级别下,会话1可以读到会话2未提交的事务,可以读到会话2插入未提交的数据。

不可重复读

一个事务间隔一段时间先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。

这个很好理解,比如A用户在查询某张表的某条记录时,B用户修改了这了一条数据,那么A用户再次查询的时候与上次查询的结果不一致。即原始读取不可重复
image.png

可以看到会话1两次查询的同一条记录不一致

幻读

一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻像读。

幻觉读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么后面就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样,称之为幻读

image.png

会话1查询到自己预期更新的结果,但是有多了一行,感觉像发生了幻觉一样。要想避免幻读,只能将事务隔离级别设置为串行化。

不可重复读与脏读区别

不可重复读侧重某一行数据发生了变化。

幻读侧重行数量发生了变化;

同一个事务中,某一行之前没有,后来读到了,那我认为读到幻影行了(比如其他事务插入了新行)不可重复读。

广义上讲,第一次读和第二次读数据不一样了,这包含两种情况:

同一行数据发生了变化;
行数量发生了变化;
为了区分来这两种情况,就把后者单独叫“幻读”,而不可重复读通常指的就是第一种情况。

所以“不可重复读”和“幻读”都是读的过程中数据前后不一致,只是前者侧重于修改,后者侧重于增删。个人认为,严格来讲“幻读”可以被称为“不可重复读”的一种特殊情况。但是从数据库管理的角度来看二者是有区别的。解决“不可重复读”只要加行级锁就可以了。而解决“幻读”则需要加表级锁。

达梦支持的事务隔离级别

读提交

读提交隔离可以确保只访问到已提交事务修改的数据,保证数据处于一致性状态,能够满足大多数应用的要求,并最大限度的保证系统并发性能,但可能会出现不可重复读取和幻像读。读提交是DM数据库默认使用的事务隔离级别,可重复读升级为更严格的串行化隔离级。

用户可以在事务开始时使用以下语句设定事务为读提交隔离级:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

读未提交

读未提交隔离级别是最不严格的隔离级别。实际上,在使用这个隔离级别时,有可能发

生脏读、不可重复读和幻像。一般来说,读未提交隔离级别通常只用于访问只读表和只读视图,以消除可见性判断带来的系统开销,提升查询性能。

用户可以在事务开始时使用以下语句,设定事务为读未提交隔离级:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

串行化

在要求消除不可重复读取或幻像读的情况下,我们可以设置事务隔离级为串行化。跟读

提交隔离级相比,串行化事务的查询本身不会增加任何代价,但修改数据可能引发“串行化

事务被打断”错误。

用户可以在事务开始时使用以下语句设定事务为串行化隔离级:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

只读事务

除了前面所述的各种标准特性外,DM 数据库还支持只读事务,只读事务只能访问数据,

但不能修改数据。并且只读事务不会改变事务原有的隔离级。

用户可以在事务开始时使用以下语句,设定事务为只读事务:

SET TRANSACTION READ ONLY;

如果在设置了只读事务的会话里面执行写操作,会报如下错误:

SQL> SET TRANSACTION READ ONLY; 操作已执行 已用时间: 1.307(毫秒). 执行号:59500. SQL> insert into T1 values(4,'d'); insert into T1 values(4,'d'); [-6506]:试图在只读事务中修改数据. 已用时间: 0.972(毫秒). 执行号:0.

在日常运维中,数据库很少设置成只读事务,所以如果在发生只能读,无法写入的场景下,排除数据库设置成只读事务外,优先排查应用开发语言中某些框架里是否设置只读,笔者在日常维护过程中,多次遇到在应用开发语言中某些框架设置成只读,导致应用只能读无法写!

读类型与隔离级别关系

在 SQL-92 标准中,定义了四种隔离级别:读未提交、读提交、可重复读和串行化。

每种隔离级别下对于读数据有不同的要求。

类别 脏读 不可重复读 幻读
读未提交 Y Y Y
读提交 N Y Y
可重复读 N N Y
串行化 N N N

DM 数据库支持三种事务隔离级别:读未提交、读提交和串行化,不支持可重复读。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服