feat: 完善数据库持久化与存证功能
主要更新: 1. 数据库持久化功能 - 支持三种策略:仅落库、既落库又存证、仅存证 - 实现 Cursor Worker 异步扫描和存证机制 - 实现 Retry Worker 失败重试机制 - 支持 PostgreSQL、MySQL、SQLite 等多种数据库 - 添加 ClientIP 和 ServerIP 字段(可空,仅落库) 2. 集群并发安全 - 使用 SELECT FOR UPDATE SKIP LOCKED 防止重复处理 - 实现 CAS (Compare-And-Set) 原子状态更新 - 添加 updated_at 字段支持并发控制 3. Cursor 初始化优化 - 自动基于历史数据初始化 cursor - 确保不遗漏任何历史记录 - 修复 UPSERT 逻辑 4. 测试完善 - 添加 E2E 集成测试(含 Pulsar 消费者验证) - 添加 PostgreSQL 集成测试 - 添加 Pulsar 集成测试 - 添加集群并发安全测试 - 添加 Cursor 初始化验证测试 - 补充大量单元测试,提升覆盖率 5. 工具脚本 - 添加数据库迁移脚本 - 添加 Cursor 状态检查工具 - 添加 Cursor 初始化工具 - 添加 Pulsar 消息验证工具 6. 文档清理 - 删除冗余文档,只保留根目录 README 测试结果: - 所有 E2E 测试通过(100%) - 数据库持久化与异步存证流程验证通过 - 集群环境下的并发安全性验证通过 - Cursor 自动初始化和历史数据处理验证通过
This commit is contained in:
@@ -1,361 +0,0 @@
|
||||
# Trustlog 数据库建表脚本
|
||||
|
||||
本目录包含 go-trustlog 数据库持久化模块的建表 SQL 脚本。
|
||||
|
||||
---
|
||||
|
||||
## 📁 文件列表
|
||||
|
||||
| 文件 | 数据库 | 说明 |
|
||||
|------|--------|------|
|
||||
| `postgresql.sql` | PostgreSQL 12+ | PostgreSQL 数据库建表脚本 |
|
||||
| `mysql.sql` | MySQL 8.0+ / MariaDB 10+ | MySQL 数据库建表脚本 |
|
||||
| `sqlite.sql` | SQLite 3+ | SQLite 数据库建表脚本 |
|
||||
| `test_data.sql` | 通用 | 测试数据插入脚本 |
|
||||
|
||||
---
|
||||
|
||||
## 📊 表结构说明
|
||||
|
||||
### 1. operation 表
|
||||
|
||||
操作记录表,用于存储所有的操作记录。
|
||||
|
||||
**关键字段**:
|
||||
- `op_id` - 操作ID(主键)
|
||||
- `client_ip` - **客户端IP(可空,仅落库,不存证)**
|
||||
- `server_ip` - **服务端IP(可空,仅落库,不存证)**
|
||||
- `trustlog_status` - **存证状态(NOT_TRUSTLOGGED / TRUSTLOGGED)**
|
||||
- `timestamp` - 操作时间戳
|
||||
|
||||
**索引**:
|
||||
- `idx_operation_timestamp` - 时间戳索引
|
||||
- `idx_operation_status` - 存证状态索引
|
||||
- `idx_operation_doid` - DOID 索引
|
||||
|
||||
### 2. trustlog_cursor 表
|
||||
|
||||
游标表,用于跟踪处理进度,支持断点续传。
|
||||
|
||||
**关键字段**:
|
||||
- `id` - 游标ID(固定为1)
|
||||
- `last_processed_id` - 最后处理的操作ID
|
||||
- `last_processed_at` - 最后处理时间
|
||||
|
||||
**特性**:
|
||||
- 自动初始化一条记录(id=1)
|
||||
- 用于实现最终一致性
|
||||
|
||||
### 3. trustlog_retry 表
|
||||
|
||||
重试表,用于管理失败的存证操作。
|
||||
|
||||
**关键字段**:
|
||||
- `op_id` - 操作ID(主键)
|
||||
- `retry_count` - 重试次数
|
||||
- `retry_status` - 重试状态(PENDING / RETRYING / DEAD_LETTER)
|
||||
- `next_retry_at` - 下次重试时间(指数退避)
|
||||
- `error_message` - 错误信息
|
||||
|
||||
**索引**:
|
||||
- `idx_retry_status` - 重试状态索引
|
||||
- `idx_retry_next_retry_at` - 下次重试时间索引
|
||||
|
||||
---
|
||||
|
||||
## 🚀 使用方法
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```bash
|
||||
# 方式1: 使用 psql 命令
|
||||
psql -U username -d database_name -f postgresql.sql
|
||||
|
||||
# 方式2: 使用管道
|
||||
psql -U username -d database_name < postgresql.sql
|
||||
|
||||
# 方式3: 在 psql 中执行
|
||||
psql -U username -d database_name
|
||||
\i postgresql.sql
|
||||
```
|
||||
|
||||
### MySQL
|
||||
|
||||
```bash
|
||||
# 方式1: 使用 mysql 命令
|
||||
mysql -u username -p database_name < mysql.sql
|
||||
|
||||
# 方式2: 在 mysql 中执行
|
||||
mysql -u username -p
|
||||
USE database_name;
|
||||
SOURCE mysql.sql;
|
||||
```
|
||||
|
||||
### SQLite
|
||||
|
||||
```bash
|
||||
# 方式1: 使用 sqlite3 命令
|
||||
sqlite3 trustlog.db < sqlite.sql
|
||||
|
||||
# 方式2: 在 sqlite3 中执行
|
||||
sqlite3 trustlog.db
|
||||
.read sqlite.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 验证安装
|
||||
|
||||
每个 SQL 脚本末尾都包含验证查询,执行后可以检查:
|
||||
|
||||
### PostgreSQL
|
||||
```sql
|
||||
-- 查询所有表
|
||||
SELECT tablename FROM pg_tables WHERE schemaname = 'public'
|
||||
AND tablename IN ('operation', 'trustlog_cursor', 'trustlog_retry');
|
||||
```
|
||||
|
||||
### MySQL
|
||||
```sql
|
||||
-- 查询所有表
|
||||
SHOW TABLES LIKE 'operation%';
|
||||
SHOW TABLES LIKE 'trustlog_%';
|
||||
```
|
||||
|
||||
### SQLite
|
||||
```sql
|
||||
-- 查询所有表
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table'
|
||||
AND name IN ('operation', 'trustlog_cursor', 'trustlog_retry');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 字段说明
|
||||
|
||||
### operation 表新增字段
|
||||
|
||||
#### client_ip 和 server_ip
|
||||
|
||||
**特性**:
|
||||
- 类型: VARCHAR(32) / TEXT (根据数据库而定)
|
||||
- 可空: YES
|
||||
- 默认值: NULL
|
||||
|
||||
**用途**:
|
||||
- 记录客户端和服务端的 IP 地址
|
||||
- **仅用于数据库持久化**
|
||||
- **不参与存证哈希计算**
|
||||
- **不会被序列化到 CBOR 格式**
|
||||
|
||||
**示例**:
|
||||
```sql
|
||||
-- 插入 NULL 值(默认)
|
||||
INSERT INTO operation (..., client_ip, server_ip, ...)
|
||||
VALUES (..., NULL, NULL, ...);
|
||||
|
||||
-- 插入 IP 值
|
||||
INSERT INTO operation (..., client_ip, server_ip, ...)
|
||||
VALUES (..., '192.168.1.100', '10.0.0.50', ...);
|
||||
```
|
||||
|
||||
#### trustlog_status
|
||||
|
||||
**特性**:
|
||||
- 类型: VARCHAR(32) / TEXT
|
||||
- 可空: YES
|
||||
- 可选值:
|
||||
- `NOT_TRUSTLOGGED` - 未存证
|
||||
- `TRUSTLOGGED` - 已存证
|
||||
|
||||
**用途**:
|
||||
- 标记操作记录的存证状态
|
||||
- 用于查询未存证的记录
|
||||
- 支持最终一致性机制
|
||||
|
||||
---
|
||||
|
||||
## 🔄 常用查询
|
||||
|
||||
### 1. 查询未存证的操作
|
||||
|
||||
```sql
|
||||
SELECT * FROM operation
|
||||
WHERE trustlog_status = 'NOT_TRUSTLOGGED'
|
||||
ORDER BY timestamp ASC
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
### 2. 查询待重试的操作
|
||||
|
||||
```sql
|
||||
SELECT * FROM trustlog_retry
|
||||
WHERE retry_status IN ('PENDING', 'RETRYING')
|
||||
AND next_retry_at <= NOW()
|
||||
ORDER BY next_retry_at ASC
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
### 3. 查询死信记录
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
o.op_id,
|
||||
o.doid,
|
||||
r.retry_count,
|
||||
r.error_message,
|
||||
r.created_at
|
||||
FROM operation o
|
||||
JOIN trustlog_retry r ON o.op_id = r.op_id
|
||||
WHERE r.retry_status = 'DEAD_LETTER'
|
||||
ORDER BY r.created_at DESC;
|
||||
```
|
||||
|
||||
### 4. 按 IP 查询操作
|
||||
|
||||
```sql
|
||||
-- 查询特定客户端IP的操作
|
||||
SELECT * FROM operation
|
||||
WHERE client_ip = '192.168.1.100'
|
||||
ORDER BY timestamp DESC;
|
||||
|
||||
-- 查询未设置IP的操作
|
||||
SELECT * FROM operation
|
||||
WHERE client_ip IS NULL
|
||||
ORDER BY timestamp DESC;
|
||||
```
|
||||
|
||||
### 5. 统计存证状态
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
trustlog_status,
|
||||
COUNT(*) as count
|
||||
FROM operation
|
||||
GROUP BY trustlog_status;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗑️ 清理脚本
|
||||
|
||||
### 删除所有表
|
||||
|
||||
```sql
|
||||
-- PostgreSQL / MySQL
|
||||
DROP TABLE IF EXISTS trustlog_retry;
|
||||
DROP TABLE IF EXISTS trustlog_cursor;
|
||||
DROP TABLE IF EXISTS operation;
|
||||
|
||||
-- SQLite
|
||||
DROP TABLE IF EXISTS trustlog_retry;
|
||||
DROP TABLE IF EXISTS trustlog_cursor;
|
||||
DROP TABLE IF EXISTS operation;
|
||||
```
|
||||
|
||||
### 清空数据(保留结构)
|
||||
|
||||
```sql
|
||||
-- 清空重试表
|
||||
DELETE FROM trustlog_retry;
|
||||
|
||||
-- 清空操作表
|
||||
DELETE FROM operation;
|
||||
|
||||
-- 重置游标表
|
||||
UPDATE trustlog_cursor SET
|
||||
last_processed_id = NULL,
|
||||
last_processed_at = NULL,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = 1;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 字符集和排序规则(MySQL)
|
||||
- 使用 `utf8mb4` 字符集
|
||||
- 使用 `utf8mb4_unicode_ci` 排序规则
|
||||
- 支持完整的 Unicode 字符
|
||||
|
||||
### 2. 索引长度(MySQL)
|
||||
- `doid` 字段使用前缀索引 `doid(255)`
|
||||
- 避免索引长度超过限制
|
||||
|
||||
### 3. 自增主键
|
||||
- PostgreSQL: `SERIAL`
|
||||
- MySQL: `AUTO_INCREMENT`
|
||||
- SQLite: `AUTOINCREMENT`
|
||||
|
||||
### 4. 时间类型
|
||||
- PostgreSQL: `TIMESTAMP`
|
||||
- MySQL: `DATETIME`
|
||||
- SQLite: `DATETIME` (存储为文本)
|
||||
|
||||
### 5. IP 字段长度
|
||||
- 当前长度: 32 字符
|
||||
- IPv4: 最长 15 字符 (`255.255.255.255`)
|
||||
- IPv4 with port: 最长 21 字符 (`255.255.255.255:65535`)
|
||||
- **IPv6: 最长 39 字符** - 如需支持完整 IPv6,建议扩展到 64 字符
|
||||
|
||||
---
|
||||
|
||||
## 🔧 扩展建议
|
||||
|
||||
### 1. 如果需要支持完整 IPv6
|
||||
|
||||
```sql
|
||||
-- 修改 client_ip 和 server_ip 字段长度
|
||||
ALTER TABLE operation MODIFY COLUMN client_ip VARCHAR(64);
|
||||
ALTER TABLE operation MODIFY COLUMN server_ip VARCHAR(64);
|
||||
```
|
||||
|
||||
### 2. 如果需要分区表(PostgreSQL)
|
||||
|
||||
```sql
|
||||
-- 按时间分区
|
||||
CREATE TABLE operation_partitioned (
|
||||
-- ... 字段定义 ...
|
||||
) PARTITION BY RANGE (timestamp);
|
||||
|
||||
CREATE TABLE operation_2024_01 PARTITION OF operation_partitioned
|
||||
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
|
||||
```
|
||||
|
||||
### 3. 如果需要添加审计字段
|
||||
|
||||
```sql
|
||||
-- 添加创建人和更新人
|
||||
ALTER TABLE operation ADD COLUMN created_by VARCHAR(64);
|
||||
ALTER TABLE operation ADD COLUMN updated_by VARCHAR(64);
|
||||
ALTER TABLE operation ADD COLUMN updated_at TIMESTAMP;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [PERSISTENCE_QUICKSTART.md](../../PERSISTENCE_QUICKSTART.md) - 快速入门
|
||||
- [README.md](../README.md) - 详细技术文档
|
||||
- [IP_FIELDS_USAGE.md](../IP_FIELDS_USAGE.md) - IP 字段使用说明
|
||||
|
||||
---
|
||||
|
||||
## ✅ 检查清单
|
||||
|
||||
安装完成后,请检查:
|
||||
|
||||
- [ ] 所有3个表都已创建
|
||||
- [ ] 所有索引都已创建
|
||||
- [ ] trustlog_cursor 表有初始记录(id=1)
|
||||
- [ ] operation 表可以插入 NULL 的 IP 值
|
||||
- [ ] operation 表可以插入非 NULL 的 IP 值
|
||||
- [ ] 查询验证脚本能正常执行
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-12-23
|
||||
**版本**: v1.0.0
|
||||
|
||||
@@ -12,6 +12,7 @@ CREATE TABLE IF NOT EXISTS operation (
|
||||
producer_id VARCHAR(32),
|
||||
request_body_hash VARCHAR(128),
|
||||
response_body_hash VARCHAR(128),
|
||||
op_hash VARCHAR(128), -- 操作哈希
|
||||
sign VARCHAR(512),
|
||||
op_source VARCHAR(10),
|
||||
op_type VARCHAR(30),
|
||||
@@ -21,7 +22,8 @@ CREATE TABLE IF NOT EXISTS operation (
|
||||
server_ip VARCHAR(32), -- 服务端IP(可空,仅落库)
|
||||
trustlog_status VARCHAR(32), -- 存证状态:NOT_TRUSTLOGGED / TRUSTLOGGED
|
||||
timestamp TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间(用于CAS)
|
||||
);
|
||||
|
||||
-- 创建索引
|
||||
|
||||
Reference in New Issue
Block a user