DBLOG
» WTF
Toggle navigation
DBLOG
主页
OCM
1、概览
2、数据导入导出
3、GaussDB(DWS)数据库管理
4、数据库调优与开发实践
5、湖仓一体
6、开发应用
7、集群管理
8、巡检和维运维
About Me
归档
标签
2、事务
无
2025-05-22 15:09:00
0
0
0
admin
[TOC] # 事务概述 ## 事务介绍 - **数据库事务**是数据库系统执行过程中的一个逻辑单位,由一组有限的数据库操作序列构成,包含对数据库的读或写操作。 - 当事务被提交后,数据库需要确保该事务中的所有操作都成功完成,并且数据结构被永久保存。 - 如果事务中有操作没有成功完成,则事务中的所有操作需要回滚,恢复到事务执行前的状态。 - 每个事务对数据库正在执行的其他事务无影响,给人的感觉是它们在独立运行。 - 并非任意的对数据库操作的序列都是数据库事务,其中有四个最重要的特性,称为 **ACID 特性**。 - 在进行多个相关更改时,在一个事务内执行多个语句有助于保证一致性:在所有相关更新完成之前,其他会话将无法看到中间状态。 - **使用事务时**,可以显式启动事务或使用自动提交事务。 - **显式事务**: ```sql BEGIN; -- 开启事务 INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1); COMMIT; -- 提交事务 ``` - **自动提交事务**:默认情况下(没有 `BEGIN`),数据库在“自动提交”模式中执行事务,每个语句都在自己的事务中执行,并在语句结束时隐式地执行一次提交(如果执行失败,会回滚)。 ```sql INSERT INTO t1 VALUES(1); -- 自动提交 INSERT INTO t1 VALUES(1); -- 自动提交 UPDATE t2 SET c2=100 WHERE c2=50; -- 自动提交 ``` ## 事务原理概述 - ACID - **事务需满足四个性质**: - **原子性 (Atomicity)**:一个事务要么全做,要么全不做。 - **一致性 (Consistency)**:事务执行前后,数据都是正确的,不存在矛盾。 - **隔离性 (Isolation)**:不同事务之间不会互相影响。 - **持久性 (Durability)**:事务提交后,对数据库的改变不会消失。 - **示例:转账场景**:用户 A 向用户 B 转账 50 元 - A:要么转账成功,要么转账失败。 - C:A 和 B 的存款总额不变。 ```sql BEGIN; UPDATE t_balance SET balance=balance-50 WHERE user_id='A'; UPDATE t_balance SET balance=balance+50 WHERE user_id='B'; COMMIT; ``` - I:转账过程中,A 或 B 查询自己的余额不会有变化。 - D:转账成功后,A 一定少了 50 元,B 一定多了 50 元。 ## DWS 如何实现 ACID - **原子性 (Atomicity)**:通过事务号(XID)区分不同事务,并进行事务的提交和回滚,事务结束时写入提交日志(CLog)。 - **一致性 (Consistency)**:通过定义的一些规则来保证,比如主键、数据类型、数据长度、外键、触发器等约束。 - **隔离性 (Isolation)**:通过多版本快照(MVCC)保证并行事务之间互不干扰。 - **持久性 (Durability)**:事务的修改保存在重做日志(Redo Log,xlog)中。 ## 原子性 - 事务号 - 为了区别不同的事务,数据库会为它们分配唯一的标识事务号(XID),这是一个单调递增的数字。 - 事务在修改(insert/update/delete)之前先获取事务号。 - DWS 采用 64 bit 的 XID,最大值为 2^60-1。 - **查询当前事务号**: - 函数 `txid_current()` 可以查询事务号。  - **获得当前显式事务的事务号**:  ## 原子性 - 事务提交日志(Commit Log) - 事务提交日志(CLog)记录事务执行的结果状态。 - **如何产生**: - 事务提交时,CLog 中记录 `commit`。 - 事务回滚时,CLog 中记录 `abort`。 - **主要应用**: - 查询一个事务修改是否有效时,需要查询事务对应的 CLog 状态。 - **查询事务状态**: - 函数 `pgxc_is_committed()` 可以查询事务状态。 - 函数 `pgxc_xacts_iscommitted()` 可以查询各节点上事务的状态。 - **注意事项**: - CLog 日志记录事务的提交和回滚状态,非常重要,不得随意删除或移动。  ## 隔离性/一致性 - 不一致读 - 隔离性保证了在任何一个事务看来,其他事务要么在它开始之前已经完成,要么在它完成之后才开始。即任何事务都感受不到其他事务在系统中并发执行。 - **脏读**:一个事务读取了另一个未提交事务写入的数据。 - **不可重复读**:一个事务重新读取前面读取过的数据,发现该数据已被另一个已提交事务修改。 - **幻读**:一个事务重新执行查询,返回符合查询条件的行,发现这些行因其它最近提交的事务而发生了改变(如行的增加、减少或更新)。 - **隔离级别与问题现象**: | 隔离级别 | 脏读 | 不可重复读 | 幻读 | |---------------------|-------|-------------|-------| | 未提交读 (Read Uncommitted) | √ | × | √ | | 已提交读 (Read Committed) | × | √ | √ | | 可重复读 (Repeatable Read) | × | × | √ | | 可序列化 (Serializable) | × | × | × | - √:可能出现;×:不会出现。 ## 隔离性/一致性 - 事务快照与可见性规则 - **快照**是当前时刻所有活跃的事务号的集合。 - 扫描数据时,每个事务看到的只是获取快照那一时刻的数据,而不是数据的当前最新状态。这样可以避免一个事务看到其他并发事务的更新而导致不一致的数据。 - **可见性**是指针对某条数据在当前查询中是否可见: - 快照中的活跃事务的修改不可见。 - 在本事务启动之前提交的事务,其修改可见。 - 在本事务启动之后提交的事务,其修改不可见。 - DWS 默认隔离级别是 **读已提交**,严格保证该隔离级别下数据的一致性。  ## 隔离性/一致性 - 并发事务的可见性 (1) 模拟转账业务(Session1)和查询业务(Session2)并发进行,使用默认的隔离级别(READ COMMITTED): - **T3** 时刻,Session2 读到的是转账前两个账户的余额。 - **T4** 时刻,Session1 进行转账,但事务未提交。 - **T5** 时刻,Session2 查询出的余额依旧是未转账成功的余额。 - **T6** 时刻,Session1 提交,转账业务完成。 - **T7** 时刻,Session2 可以查询到转账后的实时余额。 ```sql -- Session1 BEGIN; UPDATE t_balance SET balance=balance-50 WHERE user_id='A'; UPDATE t_balance SET balance=balance+50 WHERE user_id='B'; COMMIT; -- Session2 BEGIN; SELECT balance FROM t_balance WHERE user_id='A'; -- 100 SELECT balance FROM t_balance WHERE user_id='B'; -- 100 COMMIT; ``` ## 隔离性/一致性 - 并发事务的可见性 (2) 如果查询业务使用 **Repeatable Read** 隔离级别: - **T3-T6** 没有变化。 - **T7** 时刻,Session2 查询到的依旧是转账前的余额数据。 ```sql -- Session1 BEGIN; UPDATE t_balance SET balance=balance-50 WHERE user_id='A'; UPDATE t_balance SET balance=balance+50 WHERE user_id='B'; COMMIT; -- Session2 BEGIN; SELECT balance FROM t_balance WHERE user_id='A'; -- 100 SELECT balance FROM t_balance WHERE user_id='B'; -- 100 COMMIT; ``` ## 持久性 - 重做日志(Redo Log) - 在 DWS 中,重做日志也叫 WAL 日志或 xlog,记录着数据的修改操作,用于数据的恢复及持久化。 - **如何产生**: - 对数据的修改会产生重做日志,默认单个文件大小为 16M,保存在 `pg_xlog` 目录。 - **主要应用**: - 归档、节点重启恢复、备份恢复、容灾。 - **注意事项**: - xlog 非常重要,记录数据库发生的各种事务信息,不得随意删除或移动这些日志文件,否则将面临数据库无法恢复的风险。 - FPW(full page writes)会产生大量 xlog,因为修改的数据量是 8K,产生的 xlog 是固定的。 - 带索引导入会产生大量 xlog,因为带索引导入时数据使用 xlog 进行主备复制,而不带索引导入时使用页复制进行同步。 - 带索引导入推荐做法:在导入前删掉索引,导入完成后重建索引。 ## 持久性 - 重做日志(Redo Log)查询 - 获取当前重做日志的写入位置: ```sql SELECT pg_current_xlog_location(); ```  - 获取当前写入的重做日志的文件名: ```sql SELECT pg_xlogfile_name(location); ```  - 获取当前写入的重做日志的文件名并返回在文件中的字节偏移量: ```sql SELECT pg_xlogfile_name_offset(location); ```  # 分布式事务原理 ## 分布式事务 - DWS 是 **share-nothing** 架构,CN 节点下发事务,其他节点(CN 或 DN)共同参与一个事务的作业。 - 一个事务由不同服务器上的不同节点共同完成,所有节点上的事务要么全部成功,要么全部失败。 - DWS 采用 **两阶段提交(2PC)** 实现分布式事务: - 第一阶段:事务协调者要求每个涉及到事务的节点预提交操作,并反馈是否可以提交。 - 第二阶段:事务协调者要求每个数据库提交数据或回滚数据。 - DWS 通过 GTM 实现了分布式事务的强一致性。  ## 分布式事务 - 2PC 流程 - 根据事务涉及的节点不同,分为以下三种情况: 1. **单节点 DML**:仅涉及单个 DN 节点的写操作。 2. **跨节点 DML**:涉及多个 DN 节点的写操作。 3. **DDL**:涉及所有 CN 节点与 DN 节点的写操作。 ## 2PC 流程 - 单节点 DML - 单节点 DML,即在一个事务中,DML 操作只涉及某一个 DN 节点。 ```sql BEGIN; INSERT INTO t_balance VALUES('C', 135790, 100); SELECT txid_current(); COMMIT; ``` - 因为数据一定只落在一个 DN 节点上,所以只需要这个 DN 以及发起事务的 CN 参与事务,其他节点不参与。  ## 2PC 流程 - 跨节点 DML - 跨节点 DML,即在一个事务中,DML 操作涉及多个 DN 节点。 ```sql BEGIN; UPDATE t_balance SET balance = balance + 100; SELECT txid_current(); COMMIT; ``` - 因为数据落在所有的 DN 上,所以所有 DN 以及发起事务的 CN 都参与事务,其他 CN 节点不参与。  ## 2PC 流程 - DDL - 分布式 DDL,更新所有实例上的元数据信息。 ```sql BEGIN; ALTER TABLE t_balance ADD COLUMN birth VARCHAR(100); SELECT txid_current(); COMMIT; ``` - 因为元数据信息存储在所有实例上,所以更新元数据信息需要在所有 CN 和 DN 上都更新一遍,即所有 CN、DN 都参与事务。 
上一篇:
2、SQL编辑器
下一篇:
2、历史TopSQL解析
0
赞
1 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网