事务层 #
一、事务层概述 #
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