事务是为用户提供的最核心、最具吸引力的数据库功能之一。
事务是用户定义的一系列数据库操作(如查询、插入、修改或删除等)的集合从数据库内部保证了该操作集合(作为一个整体)的原子性(Atomicity)、一致性
(Consistency)、隔离性(lsolation)和持久性(Durability),这些特性统称事务的ACID特性。
A:原子性是指事务中的所有操作要么全部执行成功,要么全部执行失败。一个事务执行以后,数据库只可能处于上述两种状态之一,即使数据库在这些操作执行过程中发生故障,也不会出现只有部分操作执行成功的状态。
START TRANSACTION;
INSERT INTO t(a) VALUES(v1);
INSERT INTO t(a) VALUES(v2);
COMMIT;
C:一致性是指事务的执行会导致数据从一个一致的状态转移到另一个一致的状态,事务的执行不会违反一致性约束、触发器等定义的规则。
l:隔离性是指在事务的执行过程中,所看到的数据库状态受并发事务的影响程度。根据该影响程度的轻重,一般将事务的隔离级别分为读未提交、读已提交、可重复读和可串行化四个级别(受并发事务影响由重到轻)。
D:持久性是指一旦事务提交以后,即使数据库发生故障重启,该事务的执行结果不会丢失,仍然对后续事务可见。
根据分布式角色分为本地事务和全局事务
本地事务:普通事务,独立的一个数据库,保证在该数据库上操作的ACID,也叫单机事务,它是相对于全局事务而言的。
单机事务:在openGauss这样的分布式集群中,单机事务(亦称单分片事务)是指一个事务中所有的操作都发生在同一个分片(即DN)上
全局事务:涉及两个或多个数据库源的事务,即跨越多台同类或异类数据库的事务(由每台数据库的本地事务组成的),全局事务旨在保证这些本地事务的所有操作的ACID,使事务可以跨越多台数据库;
显式事务是指用户在所执行的一条或多条SQL后,显式添加了开启事务START TRANSACTION语句和提交事务COMMIT语句。
START TRANSACTION;
SELECT * FROM t;
INSERT INTO t(a) VALUES (100);
COMMIT;
隐式事务是指用户在所执行的一条或多条SQL语句的前后,没有显式添加开启事务和提交事务的语句。在这种情况下,每一条SQL语句在开始执行时,openGauss内部都会为其开启一个事务,并且在该语句执行完成之后,自动提交该事务。
两阶段事务2PC是分布式数据库和分布式系统中常见的事务模型,两阶段事务的架构中包含事务管理器和资源管理器等多个角色。
XA事务是2PC原子提交协议的一种实现,它通过引入协调者来统一参与者的步伐。
自治事务(Autonomous Transaction)将一个主事务分割成几个子事务,在执行完子事务以后再继续执行主事务。子事务是独立于主事务的,子事务中的ROLLBACK和COMMIT操作只会影响子事务中的DML操作;主事务中的ROLLBACK和COMMIT操作只会影响主事务中的DML操作,而不会影响子事务中的操作。在子事务中已经COMMIT的操作,不会被主事务中的ROLLBACK撤销
使用START TRANSACTION和BEGIN语法启动事务。
事务隔离级别
Vastbase只支持READ COMMITTED(读已提交隔离级别)和REPEATABLE READ(事务可重复读隔离级别);
SERIALIZABLE: Vastbase目前功能上不支持此隔离级别,等价于REPEATABLE READ
所谓预写日志,是指在事务提交的时候,先将事务对于数据库的修改写入一个顺序追加的WAL文件中。由于WAL的写操作是顺序lO,因此其可以达到一个比较高的性能。
对于真正修改的物理数据文件,再等待合适的时机写人磁盘,以尽可能合并该数据文件上的IO操作。在一个事务:记成日志的落盘操作(即写入磁盘)以后,该事务就可以完成提交动作。如果在此之后数据库发生崩溃,那么数据库会首先从已经写入磁盘的WAL文件中恢复出该事务对于数据库的修改操作,从而保证事务—旦提交即具备持久性的特点。
Vastbase G100数据库通过 WAL、事务提交信息日志clog以及更新记录的多版本来证写事务的原子性。
如果在事务写下提交日志之前,数据库发生宕机,那么数据库恢复过程中虽然会把这两条记录插入到数据页面中,但是并不会在CLOG中将该插入事务号标识为提交状态,后续查询也不会返回这两条记录。
如果在事务写下提交日志之店,数据库发生宕机,那么数据库恢复过程中,不仅会把这两条记录插入到数据页面中。同时,还会在CLOG中将该插入事务号标识为提交状态,后续查询可以同时看见这两条插入的记录。
如上,在故障场景下,上述插入两行记录的事务操作亦是原子性的。
在VB中,每个query在执行时,都会首先通过GetSnapshotData()来获取一张快照,这个快照可以认为是数据库在某一特定时间点下所有数据的集合,这张快照中包含的信息:
xmin,当前正在运行的事务集合中最小的xid值.所有在xmin之前的事务都被认为是已经结束的.xmax,当前结束运行的事务集合中最大的xid值.所有在xmax之后的事务都被认为是正在运行的
在VB中,有两种方法来实现快照:活跃事务数组法,时间戳方法。
解决的问题场景︰
并发执行的事务,某一个事务在执行过程中,它“眼中”其他所有并发事务的状态
在数据库业界,一般按由低到高将隔离性分为以下四个隔离级别:读未提交、读已提交、可重复读、可串行化。每个隔离级别按照在该级别下禁止发生的异常现象来定义。这些异常现象包括:
(1)脏读:指一个事务在执行过程中读到并发的、还没有提交的写事务的修改内容。
(2)不可重复读:指在同一个事务内,先后两次读到的同一条记录的内容发生了变化(被并发的写事务修改)。
(3)幻读:指在同一个事务内,先后两次执行的、谓词条件相同的范围查询,返回的结果不同(并发写事务插入了新记录)。
对于底层数据的访问和修改,如物理页面和元组为了保证读、写操作的原子性需要在每次的读、写操作期间加上共享锁或排他锁。当每次读、写操作完成之后,即可释放上述锁资源,无须等待事务提交,持锁窗口相对较短。
(一)读-读并发控制
在绝大多数情况下,并发的读-读事务是不会也没有必要相互阻塞的。只需要对它们加共享锁即可,不会发生锁等待的情况。
(二)读-写并发控制
VB中对于读、写事务的并发控制是基于MVCC和快照机制的,彼此之间不会存在事务级的长时间阻塞。相比之下,采用两阶段锁协议(Two-Phase Locking Protocol,2PL协议)的并发控制(如IBMDB2数据库),由于读、写均在记录的同一个版本上操作,因此排他锁等待队列后面的事务至少要阻塞到持锁者事务提交之后才能继续执行。