事务层 #

一、事务层概述 #

1.1 事务架构 #

text
事务层架构
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   SQL层                                                     │
│       │                                                     │
│       ▼                                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              事务协调器                             │   │
│   │   事务开始 / 提交 / 回滚                           │   │
│   └─────────────────────────────────────────────────────┘   │
│       │                                                     │
│       ▼                                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              并发控制                               │   │
│   │   锁管理 / 冲突检测                                │   │
│   └─────────────────────────────────────────────────────┘   │
│       │                                                     │
│       ▼                                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              时间戳管理                             │   │
│   │   HLC (混合逻辑时钟)                               │   │
│   └─────────────────────────────────────────────────────┘   │
│       │                                                     │
│       ▼                                                     │
│   分布式层 / 存储层                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 ACID保证 #

特性 说明
原子性 (Atomicity) 全部成功或全部失败
一致性 (Consistency) 数据约束保证
隔离性 (Isolation) 并发事务隔离
持久性 (Durability) 数据持久保存

二、事务模型 #

2.1 事务生命周期 #

text
事务生命周期
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   BEGIN TRANSACTION                                         │
│       │                                                     │
│       ▼                                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │ 1. 获取事务ID和时间戳                               │   │
│   │    Transaction ID + Timestamp (HLC)                 │   │
│   └─────────────────────────────────────────────────────┘   │
│       │                                                     │
│       ▼                                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │ 2. 执行SQL语句                                      │   │
│   │    读取: MVCC快照读取                               │   │
│   │    写入: 写入临时缓冲区                             │   │
│   └─────────────────────────────────────────────────────┘   │
│       │                                                     │
│       ▼                                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │ 3. 两阶段提交 (2PC)                                 │   │
│   │    Phase 1: Prepare (锁定)                          │   │
│   │    Phase 2: Commit (提交)                           │   │
│   └─────────────────────────────────────────────────────┘   │
│       │                                                     │
│       ▼                                                     │
│   COMMIT TRANSACTION                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.2 事务语法 #

sql
-- 显式事务
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

-- 带隔离级别的事务
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM accounts WHERE id = 1;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;

-- 只读事务
BEGIN TRANSACTION READ ONLY;
SELECT * FROM accounts;
COMMIT;

-- 设置事务参数
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET TRANSACTION PRIORITY HIGH;
SET TRANSACTION AS OF SYSTEM TIME '-10s';

三、隔离级别 #

3.1 支持的隔离级别 #

text
隔离级别
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   READ COMMITTED (默认):                                    │
│   ├── 读取已提交的数据                                     │
│   ├── 可能出现不可重复读                                   │
│   └── 性能较好                                             │
│                                                             │
│   SERIALIZABLE:                                             │
│   ├── 完全隔离                                             │
│   ├── 无并发问题                                           │
│   └── 可能需要重试                                         │
│                                                             │
│   隔离级别对比:                                             │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │ 问题          │ READ COMMITTED │ SERIALIZABLE      │   │
│   ├─────────────────────────────────────────────────────┤   │
│   │ 脏读          │      ✗         │      ✗           │   │
│   │ 不可重复读    │      ✓         │      ✗           │   │
│   │ 幻读          │      ✓         │      ✗           │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.2 设置隔离级别 #

sql
-- 设置默认隔离级别
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;

-- 单个事务设置隔离级别
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

-- 查看当前隔离级别
SHOW TRANSACTION ISOLATION LEVEL;

3.3 隔离级别示例 #

sql
-- READ COMMITTED 示例
-- 会话1
BEGIN;
SELECT balance FROM accounts WHERE id = 1;  -- 返回 1000

-- 会话2
BEGIN;
UPDATE accounts SET balance = 500 WHERE id = 1;
COMMIT;

-- 会话1
SELECT balance FROM accounts WHERE id = 1;  -- 返回 500 (不可重复读)
COMMIT;

-- SERIALIZABLE 示例
-- 会话1
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT balance FROM accounts WHERE id = 1;  -- 返回 1000

-- 会话2
BEGIN;
UPDATE accounts SET balance = 500 WHERE id = 1;
COMMIT;

-- 会话1
SELECT balance FROM accounts WHERE id = 1;  -- 返回 1000 (可重复读)
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 可能需要重试
COMMIT;

四、并发控制 #

4.1 乐观并发控制 #

text
乐观并发控制
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   阶段:                                                     │
│                                                             │
│   1. 读取阶段                                               │
│      ├── 读取数据到本地                                    │
│      └── 记录读取的时间戳                                  │
│                                                             │
│   2. 验证阶段                                               │
│      ├── 检查是否有冲突                                    │
│      └── 冲突则重试                                        │
│                                                             │
│   3. 写入阶段                                               │
│      ├── 提交事务                                          │
│      └── 写入新版本数据                                    │
│                                                             │
│   冲突检测:                                                 │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │ Transaction 1: Read A, Write A                      │   │
│   │ Transaction 2: Read A, Write A                      │   │
│   │                                                      │   │
│   │ T1 读取 A (ts=100)                                  │   │
│   │ T2 读取 A (ts=100)                                  │   │
│   │ T2 写入 A (ts=110)                                  │   │
│   │ T2 提交成功                                          │   │
│   │ T1 写入 A (ts=120)                                  │   │
│   │ T1 提交时检测到冲突 → 重试                          │   │
│   └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.2 冲突处理 #

sql
-- 自动重试
-- CockroachDB 自动重试可序列化事务

-- 手动重试示例
DO $$
BEGIN
    DECLARE
        attempts INT DEFAULT 0;
    BEGIN
        LOOP
            BEGIN
                UPDATE accounts SET balance = balance - 100 WHERE id = 1;
                UPDATE accounts SET balance = balance + 100 WHERE id = 2;
                COMMIT;
                EXIT;
            EXCEPTION WHEN serialization_failure THEN
                attempts := attempts + 1;
                IF attempts > 3 THEN
                    RAISE;
                END IF;
                ROLLBACK;
            END;
        END LOOP;
    END;
END;
$$;

4.3 事务优先级 #

sql
-- 设置高优先级
SET TRANSACTION PRIORITY HIGH;

-- 设置低优先级
SET TRANSACTION PRIORITY LOW;

-- 优先级说明
-- HIGH: 优先执行,较少重试
-- NORMAL: 默认优先级
-- LOW: 最后执行,更多重试

五、两阶段提交 #

5.1 2PC流程 #

text
两阶段提交 (2PC)
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   参与者:                                                   │
│   ├── Coordinator: 事务协调者                              │
│   └── Participants: 参与的 Range                           │
│                                                             │
│   Phase 1: Prepare                                          │
│                                                             │
│   Coordinator                                               │
│       │                                                     │
│       ├──► Participant 1: Prepare                          │
│       │       │                                             │
│       │       └── 锁定资源                                 │
│       │       └── 返回 Ready                               │
│       │                                                     │
│       ├──► Participant 2: Prepare                          │
│       │       │                                             │
│       │       └── 锁定资源                                 │
│       │       └── 返回 Ready                               │
│       │                                                     │
│       └──► Participant 3: Prepare                          │
│               │                                             │
│               └── 锁定资源                                 │
│               └── 返回 Ready                               │
│                                                             │
│   Phase 2: Commit                                           │
│                                                             │
│   Coordinator (所有参与者 Ready)                            │
│       │                                                     │
│       ├──► Participant 1: Commit                           │
│       ├──► Participant 2: Commit                           │
│       └──► Participant 3: Commit                           │
│                                                             │
│   返回成功                                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.2 事务状态 #

text
事务状态机
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   ┌─────────┐                                              │
│   │ Pending │  事务开始                                    │
│   └────┬────┘                                              │
│        │                                                    │
│        ▼                                                    │
│   ┌─────────┐                                              │
│   │ Staging │  Prepare 阶段                                │
│   └────┬────┘                                              │
│        │                                                    │
│        ├─────────────────────┐                             │
│        ▼                     ▼                             │
│   ┌─────────┐          ┌─────────┐                         │
│   │Committed│          │ Aborted │                         │
│   └─────────┘          └─────────┘                         │
│                                                             │
│   状态说明:                                                 │
│   ├── Pending: 事务进行中                                  │
│   ├── Staging: 准备提交                                    │
│   ├── Committed: 已提交                                    │
│   └── Aborted: 已回滚                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

六、时间戳管理 #

6.1 HLC时钟 #

text
混合逻辑时钟 (HLC)
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   组成:                                                     │
│   ├── 物理时间戳 (NTP同步)                                 │
│   └── 逻辑计数器                                           │
│                                                             │
│   格式:                                                     │
│   <physical_timestamp>.<logical_counter>                    │
│                                                             │
│   示例:                                                     │
│   1711555200.000000001                                      │
│                                                             │
│   特点:                                                     │
│   ├── 因果一致性                                           │
│   ├── 单调递增                                             │
│   └── 跨节点同步                                           │
│                                                             │
│   用途:                                                     │
│   ├── 事务时间戳                                           │
│   ├── MVCC版本                                             │
│   └── 时间旅行查询                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

6.2 时间旅行查询 #

sql
-- 查询历史数据
SELECT * FROM users 
AS OF SYSTEM TIME '-10s';

-- 指定时间点
SELECT * FROM users 
AS OF SYSTEM TIME '2024-01-01 00:00:00';

-- 使用时间戳
SELECT * FROM users 
AS OF SYSTEM TIME 1711555200000000000;

-- 在事务中使用
BEGIN AS OF SYSTEM TIME '-1h';
SELECT * FROM users;
COMMIT;

七、事务最佳实践 #

7.1 事务设计原则 #

text
事务设计原则
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   1. 保持事务简短                                           │
│      ├── 减少事务持有时间                                  │
│      └── 降低冲突概率                                      │
│                                                             │
│   2. 避免热点                                               │
│      ├── 避免频繁更新同一行                                │
│      └── 使用队列或批处理                                  │
│                                                             │
│   3. 合理设置隔离级别                                       │
│      ├── 默认使用 READ COMMITTED                           │
│      └── 需要强一致性时使用 SERIALIZABLE                   │
│                                                             │
│   4. 处理重试                                               │
│      ├── 实现自动重试逻辑                                  │
│      └── 设置合理的重试次数                                │
│                                                             │
│   5. 使用合适的优先级                                       │
│      ├── 重要事务使用 HIGH                                 │
│      └── 后台任务使用 LOW                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

7.2 常见问题处理 #

sql
-- 问题1: 事务超时
-- 解决: 设置合理的超时时间
SET statement_timeout = '30s';

-- 问题2: 序列化失败
-- 解决: 实现重试逻辑
DO $$
BEGIN
    DECLARE
        retry_count INT DEFAULT 0;
    BEGIN
        WHILE retry_count < 3 LOOP
            BEGIN
                -- 事务逻辑
                UPDATE accounts SET balance = balance - 100 WHERE id = 1;
                COMMIT;
                EXIT;
            EXCEPTION WHEN serialization_failure THEN
                retry_count := retry_count + 1;
                ROLLBACK;
            END;
        END LOOP;
    END;
END;
$$;

-- 问题3: 死锁
-- 解决: CockroachDB 自动检测并处理
-- 无需手动干预

八、事务监控 #

8.1 查看事务状态 #

sql
-- 查看活跃事务
SELECT * FROM crdb_internal.cluster_transactions;

-- 查看事务统计
SELECT 
    database,
    count(*) as transaction_count
FROM crdb_internal.cluster_transactions
GROUP BY database;

-- 查看锁等待
SELECT * FROM crdb_internal.cluster_locks;

8.2 事务指标 #

text
事务监控指标
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   关键指标:                                                 │
│   ├── 事务吞吐量 (TPS)                                     │
│   ├── 事务延迟                                             │
│   ├── 重试次数                                             │
│   ├── 冲突率                                               │
│   └── 超时次数                                             │
│                                                             │
│   监控方式:                                                 │
│   ├── Web UI                                               │
│   ├── Prometheus + Grafana                                 │
│   └── 系统表查询                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

九、总结 #

事务层要点:

特性 说明
ACID 完整的事务保证
隔离级别 READ COMMITTED, SERIALIZABLE
并发控制 乐观并发控制
两阶段提交 分布式事务提交

下一步,让我们学习数据操作!

最后更新:2026-03-27