rat_quickdb
🚀 强大的跨数据库ODM库,支持SQLite、PostgreSQL、MySQL、MongoDB的统一接口
✨ 核心特性
- 🎯 自动索引创建: 基于模型定义自动创建表和索引,无需手动干预
- 🗄️ 多数据库支持: SQLite、PostgreSQL、MySQL、MongoDB
- 🔗 统一API: 一致的接口操作不同数据库
- 🔒 SQLite布尔值兼容: 自动处理SQLite布尔值存储差异,零配置兼容
- 🏊 连接池管理: 高效的连接池和无锁队列架构
- ⚡ 异步支持: 基于Tokio的异步运行时
- 🧠 智能缓存: 内置缓存支持(基于rat_memcache),支持TTL过期和回退机制
- 🆔 多种ID生成策略: AutoIncrement、UUID、Snowflake、ObjectId、Custom前缀
- 📝 日志控制: 由调用者完全控制日志初始化,避免库自动初始化冲突
- 🐍 Python绑定: 可选Python API支持
- 📋 任务队列: 内置异步任务队列系统
- 🔍 类型安全: 强类型模型定义和验证
- 📋 存储过程: 跨数据库的统一存储过程API,支持多表JOIN和聚合查询
🔄 版本变更说明
v0.3.6 (当前版本) - 存储过程虚拟表系统
⚠️ 重要变更:连接池配置参数单位变更
v0.3.6 对连接池配置进行了重大改进,所有超时参数现在使用秒为单位:
// v0.3.6 新写法(推荐)
let pool_config = builder
.connection_timeout // 30秒(之前是5000毫秒)
.idle_timeout // 300秒(之前是300000毫秒)
.max_lifetime // 1800秒(之前是1800000毫秒)
.max_retries // 新增:最大重试次数
.retry_interval_ms // 新增:重试间隔(毫秒)
.keepalive_interval_sec // 新增:保活间隔(秒)
.health_check_timeout_sec // 新增:健康检查超时(秒)
.build?;
新功能:
- 🎯 存储过程虚拟表系统:跨四种数据库的统一存储过程API
- 🔗 多表JOIN支持:自动生成JOIN语句和聚合管道
- 📊 聚合查询优化:自动GROUP BY子句生成(SQL数据库)
- 🧠 类型安全存储过程:编译时验证和类型检查
📦 安装
在Cargo.toml中添加依赖:
[]
= "0.3.6"
🔧 特性控制
rat_quickdb 使用 Cargo 特性来控制不同数据库的支持和功能。默认情况下只包含核心功能,你需要根据使用的数据库类型启用相应的特性:
[]
= { = "0.3.6", = [
"sqlite-support", # 支持SQLite数据库
"postgres-support", # 支持PostgreSQL数据库
"mysql-support", # 支持MySQL数据库
"mongodb-support", # 支持MongoDB数据库
] }
可用特性列表
| 特性名称 | 描述 | 默认启用 |
|---|---|---|
sqlite-support |
SQLite数据库支持 | ❌ |
postgres-support |
PostgreSQL数据库支持 | ❌ |
mysql-support |
MySQL数据库支持 | ❌ |
mongodb-support |
MongoDB数据库支持 | ❌ |
melange-storage |
已弃用:L2缓存功能已内置在rat_memcache中 | ❌ |
python-bindings |
Python API绑定 | ❌ |
full |
启用所有数据库支持 | ❌ |
数据库版本要求
重要:不同数据库对JSON操作的支持版本要求不同:
| 数据库 | 最低版本要求 | JSON支持 | Contains操作符实现 | JsonContains操作符实现 |
|---|---|---|---|---|
| MySQL | 5.7+ / MariaDB 10.2+ | ✅ 完整支持 | 字符串字段使用LIKE,JSON字段使用JSON_CONTAINS() | ❌ 暂时不支持 |
| PostgreSQL | 9.2+ | ✅ 完整支持 | 字符串字段使用LIKE,JSON字段使用@>操作符 | ✅ 完全支持 |
| SQLite | 3.38.0+ | ✅ 基础支持 | 仅字符串字段支持LIKE操作 | ❌ 不支持 |
| MongoDB | 7.0+ | ✅ 原生支持 | 原生$regex操作符 | ✅ 完全支持 |
⚠️ 版本兼容性注意事项:
- MySQL 5.6及以下版本不支持JSON_CONTAINS函数,会导致运行时错误
- PostgreSQL早期版本可能需要启用JSON扩展
- SQLite JSON功能是可选的,需要在编译时启用
按需启用特性
仅使用SQLite:
[]
= { = "0.3.6", = ["sqlite-support"] }
使用PostgreSQL:
[]
= { = "0.3.6", = ["postgres-support"] }
使用所有数据库:
[]
= { = "0.3.6", = ["full"] }
L2缓存配置注意事项:
- L2缓存功能已内置在
rat_memcache中,无需额外特性 - L2缓存需要磁盘空间用于缓存持久化
- 配置示例见下面的"缓存配置"部分
运行示例
不同的示例需要不同的特性支持:
# 基础模型定义示例
# 复杂查询示例
# 分页查询示例
# 特殊类型测试示例
# ID生成策略示例
# 手动表管理示例
# 其他数据库示例
⚠️ 重要架构说明
ODM层使用要求 (v0.3.0+)
从v0.3.0版本开始,强制使用define_model!宏定义模型,不再允许使用普通结构体进行数据库操作。
所有数据库操作必须通过以下方式:
- 推荐:使用模型API
use *;
use ModelOperations;
// 定义模型
define_model!
// 创建和保存
let user = User ;
let user_id = user.save.await?;
// 查询
let found_user = find_by_id.await?;
- 备选:使用ODM API
use *;
// 通过add_database添加数据库配置
let config = builder
.db_type
.connection
.alias
.build?;
add_database.await?;
// 使用ODM操作数据库
let mut user_data = new;
user_data.insert;
create.await?;
- 禁止的用法
// ❌ 错误:不再允许直接访问连接池管理器
// let pool_manager = get_global_pool_manager();
// let pool = pool_manager.get_connection_pools().get("main");
这种设计确保了:
- 架构完整性: 统一的数据访问层
- 安全性: 防止直接操作底层连接池导致的资源泄漏
- 一致性: 所有操作都经过相同的ODM层处理
- 维护性: 统一的错误处理和日志记录
📋 从旧版本升级
从 v0.2.x 升级到 v0.3.0
v0.3.0 是一个重大变更版本,包含破坏性更改。请查看详细的迁移指南。
主要变更:
- ✅ 强制使用
define_model!宏定义模型 - ✅ 消除动态表结构推断的"保姆设置"问题
- ✅ 提供更明确的类型安全和字段定义
- ✅ 修复重大架构Bug
从 v0.3.1 升级到 v0.3.2+
🚨 破坏性变更:便捷函数必须显式指定ID策略
从v0.3.2版本开始,所有数据库配置的便捷函数(sqlite_config、postgres_config、mysql_config、mongodb_config)现在要求必须显式传入id_strategy参数。
变更原因:
- 消除硬编码的"保姆设置",确保用户完全控制ID生成策略
- 所有数据库统一默认使用
AutoIncrement策略 - 避免不同数据库有不同默认策略导致的混淆
API变更:
// v0.3.1及之前(已移除)
let config = sqlite_config?;
// v0.3.2+(新API)
let config = sqlite_config?;
迁移指南:
- 推荐方式:迁移到构建器模式,获得更好的类型安全性和一致性
// 推荐使用构建器模式替代便捷函数:
let config = builder
.db_type
.connection
.pool_config
.alias
.id_strategy
.build?;
// PostgreSQL使用UUID(PostgreSQL推荐)
let config = builder
.db_type
.connection
.pool_config
.alias
.id_strategy
.build?;
- 临时兼容:如果必须暂时维护现有代码,请添加必需的
IdStrategy参数,但尽快规划迁移到构建器模式
影响范围:
- 所有使用便捷函数配置数据库的代码
- 使用
mongodb_config_with_builder的代码(已移除重复函数) - 依赖特定数据库默认ID策略的应用
这个变更确保了配置的一致性和用户控制权,符合"不做保姆设置"的设计原则。
🚀 快速开始
基本使用
查看 examples/model_definition.rs 了解完整的模型定义和使用方法。
ID生成策略示例
查看 examples/id_strategy_test.rs 了解不同ID生成策略的使用方法。
数据库适配器示例
- SQLite:
examples/model_definition.rs(运行时使用--features sqlite-support) - PostgreSQL:
examples/model_definition_pgsql.rs - MySQL:
examples/model_definition_mysql.rs - MongoDB:
examples/model_definition_mongodb.rs
模型定义(推荐方式)
查看 examples/model_definition.rs 了解完整的模型定义、CRUD操作和复杂查询示例。
字段类型和验证
查看 examples/model_definition.rs 中包含的字段类型定义和验证示例。
索引管理
索引会根据模型定义自动创建,无需手动管理。参考 examples/model_definition.rs 了解索引定义方式。
🔒 SQLite布尔值兼容性
SQLite数据库将布尔值存储为整数(0和1),这可能导致serde反序列化错误。rat_quickdb提供了多种解决方案:
方案1: sqlite_bool_field() - 推荐(零配置)
use *;
define_model!
方案2: 手动serde属性 + 通用反序列化器
use *;
use Deserialize;
define_model!
方案3: 传统方式(需要手动处理)
// 对于已有代码,可以使用传统boolean_field()
// 但需要确保数据源中的布尔值格式正确
define_model!
反序列化器选择指南
deserialize_bool_from_any(): 支持整数、布尔值、字符串 "true"/"false"deserialize_bool_from_int(): 支持整数和布尔值sqlite_bool_field(): 自动选择最佳反序列化器
迁移指南
从传统boolean_field()迁移到sqlite_bool_field():
// 之前(可能有兼容性问题)
is_active: boolean_field,
// 之后(完全兼容)
is_active: sqlite_bool_field,
🆔 ID生成策略
rat_quickdb支持多种ID生成策略,满足不同场景的需求:
AutoIncrement(自增ID)- 默认推荐
builder
.id_strategy
.build?
// 便捷函数使用
let config = sqlite_config?;
UUID(通用唯一标识符)- PostgreSQL推荐
builder
.id_strategy
.build?
// 便捷函数使用
let config = postgres_config?;
⚠️ PostgreSQL UUID策略特殊要求
重要提醒:PostgreSQL对类型一致性有严格要求,如果使用UUID策略:
- 主键表:ID字段将为UUID类型
- 关联表:所有外键字段也必须为UUID类型
- 类型匹配:不允许UUID类型与其他类型进行关联
示例:
// 用户表使用UUID ID
define_model!
// 订单表的外键也必须使用UUID类型
define_model!
解决方案:
- 对于新项目:PostgreSQL推荐全面使用UUID策略
- 对于现有项目:可以使用
IdStrategy::Custom手动生成UUID字符串作为兼容方案 - 混合策略:主表使用UUID,关联表也必须使用UUID,保持类型一致性
✨ PostgreSQL UUID自动转换功能
从v0.3.4版本开始,PostgreSQL适配器支持UUID字段的自动转换,让用户可以使用字符串UUID进行查询操作。
功能特点:
- 自动转换:查询时传入字符串UUID,适配器自动转换为UUID类型
- 严格验证:无效UUID格式直接报错,不做容错修复
- 用户友好:保持API一致性,无需手动转换UUID类型
- 类型安全:确保数据库层面的UUID类型一致性
使用示例:
// 用户模型定义(注意:结构体中用String,字段定义中用uuid_field)
define_model!
// 文章模型,author_id为UUID外键
define_model!
// 查询:直接使用字符串UUID,自动转换!
let conditions = vec!;
let articles = find.await?;
// PostgreSQL适配器自动将字符串转换为UUID类型进行查询
⚠️ 反直觉的设计要求(重要!)
当前限制:使用UUID策略时,模型定义存在一个反直觉的设计要求:
define_model!
为什么会这样?
- Rust类型系统限制:宏系统在生成模型时需要统一的基础类型
- 数据库类型映射:
uuid_field()告诉适配器创建UUID数据库列 - 查询转换:运行时字符串UUID自动转换为UUID数据库类型
正确用法:
- ✅ 结构体字段:始终使用
String类型 - ✅ 字段定义:UUID字段使用
uuid_field(),其他字段使用对应函数 - ✅ 查询操作:直接使用
DataValue::String("uuid-string"),自动转换 - ✅ 类型安全:PostgreSQL数据库层面保持UUID类型一致性
错误用法:
- ❌ 结构体中使用
uuid::Uuid类型(编译错误) - ❌ UUID字段使用
string_field()定义(失去UUID类型支持) - ❌ 混用不同数据库的UUID策略(类型不匹配)
暂时无法解决的原因:
- Rust宏系统的类型推导限制
- 需要保持与现有代码的向后兼容
- 跨数据库的统一API设计要求
未来改进方向:
- v0.4.0计划引入更直观的类型安全的UUID字段定义
- 考虑使用编译时类型推导减少这种不一致性
- 提供更清晰的编译时错误提示
Snowflake(雪花算法)
builder
.id_strategy
.build?
ObjectId(MongoDB风格)
builder
.id_strategy
.build?
Custom(自定义前缀)
builder
.id_strategy
.build?
🔄 ObjectId跨数据库处理
rat_quickdb为ObjectId策略提供了跨数据库的一致性处理,确保在不同数据库后端都能正常工作。
存储方式差异
MongoDB:
- 存储为原生
ObjectId类型 - 查询时返回MongoDB原生ObjectId对象
- 性能最优,支持MongoDB所有ObjectId特性
其他数据库(SQLite、PostgreSQL、MySQL):
- 存储为24位十六进制字符串(如:
507f1f77bcf86cd799439011) - 查询时返回字符串格式的ObjectId
- 保持与MongoDB ObjectId格式的兼容性
使用示例
// MongoDB - 原生ObjectId支持
let config = mongodb_config?;
// SQLite/PostgreSQL/MySQL - 字符串格式ObjectId
let config = sqlite_config?;
模型定义
ObjectId策略在模型定义中统一使用String类型:
define_model!
查询和操作
// 创建文档
let doc = Document ;
let doc_id = doc.save.await?;
// 查询文档
let found_doc = find_by_id.await?;
// 注意:ObjectId为24位十六进制字符串格式
assert_eq!; // 其他数据库
// 在MongoDB中,这将是一个原生ObjectId对象
类型转换处理
rat_quickdb自动处理ObjectId在不同数据库中的类型转换:
- 保存时:自动生成ObjectId格式(字符串或原生对象)
- 查询时:保持原格式返回,框架内部处理转换
- 迁移时:数据格式在不同数据库间保持兼容
性能考虑
- MongoDB:原生ObjectId性能最优,支持索引优化
- 其他数据库:字符串索引性能良好,长度固定(24字符)
- 跨数据库:统一的字符串格式便于数据迁移和同步
这种设计确保了ObjectId策略在所有支持的数据库中都能一致工作,同时充分利用各数据库的原生特性。
🧠 缓存配置
基本缓存配置(仅L1内存缓存)
use ;
let cache_config = CacheConfig ;
builder
.cache
.build?
L1+L2缓存配置(内置L2缓存支持)
use ;
use PathBuf;
let cache_config = CacheConfig ;
builder
.cache
.build?
L2缓存特性说明:
- L2缓存功能已内置在
rat_memcache中,无需额外特性 - 需要磁盘空间存储缓存数据
- 适合缓存大量数据或需要持久化的场景
- 只需在
CacheConfig中配置l2_config即可启用L2缓存
缓存统计和管理
// 获取缓存统计信息
let stats = get_cache_stats.await?;
println!;
println!;
// 清理缓存
clear_cache.await?;
clear_all_caches.await?;
📝 日志控制
rat_quickdb现在完全由调用者控制日志初始化:
use ;
// 调用者负责初始化日志系统
let logger = new
.with_level
.with_file
.build;
logger.init.expect;
// 然后初始化rat_quickdb(不再自动初始化日志)
init;
🔧 数据库配置
推荐方式:使用构建器模式
推荐:使用DatabaseConfig::builder()模式,提供完整的配置控制和类型安全:
use *;
use ;
let pool_config = builder
.max_connections
.min_connections
.connection_timeout // 秒
.idle_timeout // 秒
.max_lifetime // 秒
.max_retries
.retry_interval_ms
.keepalive_interval_sec
.health_check_timeout_sec
.build?;
// SQLite 配置
let sqlite_config = builder
.db_type
.connection
.pool_config
.alias
.id_strategy // 推荐策略
.build?;
// PostgreSQL 配置
let postgres_config = builder
.db_type
.connection
.pool_config
.alias
.id_strategy // PostgreSQL推荐UUID策略
.build?;
// MySQL 配置
let mysql_config = builder
.db_type
.connection
.pool_config
.alias
.id_strategy // MySQL推荐自增策略
.build?;
// MongoDB 配置
let mongodb_config = builder
.db_type
.connection
.pool_config
.alias
.id_strategy // MongoDB推荐ObjectId策略
.build?;
// 添加到连接池管理器
add_database.await?;
add_database.await?;
add_database.await?;
add_database.await?;
高级MongoDB配置
use *;
use ;
let tls_config = TlsConfig ;
let zstd_config = ZstdConfig ;
let mongodb_builder = new
.with_auth
.with_auth_source
.with_direct_connection
.with_tls_config
.with_zstd_config;
let advanced_mongodb_config = builder
.db_type
.connection
.pool_config
.alias
.id_strategy
.build?;
add_database.await?;
🚨 即将废弃的便捷函数(不推荐使用)
重要警告:以下便捷函数已标记为废弃,将在v0.4.0版本中移除。请使用上面推荐的构建器模式。
// 🚨 即将废弃 - 请勿在新项目中使用
// 这些函数存在API不一致性和硬编码问题
// 废弃的SQLite配置
let config = sqlite_config?;
// 废弃的PostgreSQL配置
let config = postgres_config?;
// 废弃的MySQL配置
let config = mysql_config?;
// 废弃的MongoDB配置
let config = mongodb_config?;
废弃原因:
- ❌ API不一致性:不同数据库的便捷函数参数不统一
- ❌ 硬编码默认值:违背"不做保姆设置"的设计原则
- ❌ 功能限制:无法支持高级配置选项
- ❌ 维护困难:重复代码增加维护成本
推荐替代方案:
- ✅ 构建器模式:类型安全、配置完整、API统一
- ✅ 完全控制:用户完全控制所有配置选项
- ✅ 扩展性强:支持所有数据库的高级特性
- ✅ 类型安全:编译时检查配置正确性
ID策略推荐
根据数据库特性选择最适合的ID策略:
| 数据库 | 推荐策略 | 备选策略 | 说明 |
|---|---|---|---|
| SQLite | AutoIncrement | ObjectId | AutoIncrement原生支持,性能最佳 |
| PostgreSQL | UUID | AutoIncrement | UUID原生支持,类型安全 |
| MySQL | AutoIncrement | ObjectId | AutoIncrement原生支持,性能最佳 |
| MongoDB | ObjectId | AutoIncrement | ObjectId原生支持,MongoDB生态标准 |
重要提醒:PostgreSQL使用UUID策略时,所有关联表的外键字段也必须使用UUID类型以保持类型一致性。
🛠️ 核心API
数据库管理
init()- 初始化库add_database(config)- 添加数据库配置remove_database(alias)- 移除数据库配置get_aliases()- 获取所有数据库别名set_default_alias(alias)- 设置默认数据库别名
模型操作(推荐)
// 保存记录
let user_id = user.save.await?;
// 查询记录
let found_user = find_by_id.await?;
let users = find.await?;
// 更新记录
let mut updates = new;
updates.insert;
let updated = user.update.await?;
// 删除记录
let deleted = user.delete.await?;
ODM操作(底层接口)
create(collection, data, alias)- 创建记录find_by_id(collection, id, alias)- 根据ID查找find(collection, conditions, options, alias)- 查询记录update(collection, id, data, alias)- 更新记录delete(collection, id, alias)- 删除记录count(collection, query, alias)- 计数exists(collection, query, alias)- 检查是否存在
🏗️ 架构特点
rat_quickdb采用现代化架构设计:
- 无锁队列架构: 避免直接持有数据库连接的生命周期问题
- 模型自动注册: 首次使用时自动注册模型元数据
- 自动索引管理: 根据模型定义自动创建表和索引
- 跨数据库适配: 统一的接口支持多种数据库类型
- 异步消息处理: 基于Tokio的高效异步处理
🔄 工作流程
应用层 → 模型操作 → ODM层 → 消息队列 → 连接池 → 数据库
↑ ↓
└────────────── 结果返回 ←────────────────┘
📊 性能特性
- 连接池管理: 智能连接复用和管理
- 异步操作: 非阻塞的数据库操作
- 批量处理: 支持批量操作优化
- 缓存集成: 内置缓存减少数据库访问
- 压缩支持: MongoDB支持ZSTD压缩
🎯 支持的字段类型
integer_field- 整数字段(支持范围和约束)string_field- 字符串字段(支持长度限制,可设置大长度作为长文本使用)float_field- 浮点数字段(支持范围和精度)boolean_field- 布尔字段datetime_field- 日期时间字段uuid_field- UUID字段json_field- JSON字段array_field- 数组字段list_field- 列表字段(array_field的别名)dict_field- 字典/对象字段(基于Object类型)reference_field- 引用字段(外键)
⚠️ 字段使用限制和最佳实践
为了保持系统的简洁性和性能,请遵循以下字段使用原则:
Array字段 - 只支持简单格式
// ✅ 推荐:使用Array字段存储简单值列表
tags: array_field, // ["tag1", "tag2", "tag3"]
scores: array_field, // [95.5, 88.0, 92.3]
user_ids: array_field, // ["user_123", "user_456"]
// ❌ 不推荐:存储复杂嵌套结构
complex_data: array_field, // 复杂对象
nested_arrays: array_field, // 嵌套数组
限制说明:
- Array字段设计用于存储简单的同类型值列表
- 不支持在Array字段内存储复杂嵌套结构(对象、嵌套数组等)
- 如需存储复杂数据,请使用专门的模型表或JSON字段
- 避免在Array字段内搜索复杂查询条件
JSON字段 - 支持但不推荐复杂嵌套
// ✅ 推荐:使用JSON字段存储配置信息
config: json_field, // {"theme": "dark", "language": "zh-CN"}
metadata: json_field, // {"version": "1.0", "author": "张三"}
// ⚠️ 谨慎使用:深度嵌套的JSON结构
deep_nested: json_field, // {"level1": {"level2": {"level3": {"data": "value"}}}}
// ❌ 不支持:搜索JSON字段内的数组内容
// 例如:查询 config.tags 中包含 "tag1" 的记录
限制说明:
- JSON字段支持存储复杂嵌套结构,但深度嵌套会影响查询性能
- JsonContains查询操作符不支持搜索JSON字段内的数组内容
- 如需数组查询功能,请使用专门的Array字段类型
- 建议JSON结构保持在3层嵌套以内
设计原则
- 简单优先:能用简单字段就不要用复杂字段
- 类型明确:数组用Array字段,配置用JSON字段,对象用专门模型
- 查询友好:设计时考虑后续查询需求,避免无法查询的结构
- 性能考虑:复杂嵌套结构会显著影响查询和索引性能
替代方案推荐
// 场景1:需要存储用户标签(使用Array字段)
define_model!
// 场景2:需要存储用户配置(使用JSON字段)
define_model!
// 场景3:需要存储复杂数据关系(使用专门的模型)
define_model!
遵循这些原则可以确保你的应用具有良好的性能、可维护性和查询能力。
🕐 时间字段处理
UTC时间存储标准
rat_quickdb统一使用UTC时间存储所有datetime字段,确保跨时区的数据一致性。
存储方式
- 所有数据库: datetime字段统一存储为UTC时间
- SQLite: 时间戳格式(Unix timestamp)
- PostgreSQL/MySQL/MongoDB: 原生datetime类型(UTC)
存储过程中的时间处理
重要: 存储过程返回的时间字段可能需要手动转换格式,特别是SQLite中的时间戳。
// 手动转换时间戳为可读格式
match datetime_value
时间字段的3种结构方案
rat_quickdb 提供3种不同的时间字段定义方式,满足不同的时区处理需求:
方案1:标准UTC时间字段
// 模型定义
created_at: DateTime,
// 字段配置
created_at: datetime_field, // 默认UTC (+00:00)
// 数据创建
let now = now;
created_at: now, // 直接传入UTC时间
方案2:带时区的FixedOffset时间字段
// 模型定义
local_time_cst: DateTime,
// 字段配置
local_time_cst: datetime_with_tz_field, // 北京时间
// 数据创建
let now = now;
local_time_cst: now.into, // 转换为FixedOffset
方案3:时区字符串字段(RFC3339格式)
// 模型定义
local_time_est: String,
// 字段配置
local_time_est: datetime_with_tz_field, // 美东时间
// 数据创建
let now = now;
local_time_est: now.to_rfc3339, // 传入RFC3339字符串
核心原理
关键特性:开发者始终传入 Utc::now(),框架根据字段定义自动处理时区转换!
- ✅ 统一时间源:所有字段都使用
Utc::now()作为输入(入库时必须是UTC now) - ✅ 自动转换:读取时框架根据时区设置自动转换为对应时区(输出会自动根据datetime_with_tz_field设置)
- ✅ 存储一致性:数据库中存储的是统一的UTC时间戳
- ✅ 显示多样性:同一个UTC时间根据字段配置显示不同时区的本地时间
重要理解:
- 入库:所有时间字段都是同一个
Utc::now()时间戳 - 输出:框架根据
datetime_with_tz_field("+08:00")等设置自动转换显示
示例说明:
let now = now; // 假设是 2024-06-15 12:00:00 UTC
// 入库:所有字段都是同一个时间戳
created_at_utc: now, // 2024-06-15 12:00:00 UTC
local_time_cst: now.into, // 2024-06-15 12:00:00 UTC (存储)
local_time_est: now.to_rfc3339, // 2024-06-15 12:00:00 UTC (存储)
// 输出:框架自动转换显示
created_at_utc: 2024-06-15 12:00:00 UTC // 保持UTC
local_time_cst: 2024-06-15 20:00:00 +08:00 // 转换为北京时间
local_time_est: 2024-06-15 07:00:00 -05:00 // 转换为美东时间
时区格式规范
支持的时区格式:
+00:00- UTC+08:00- 北京时间-05:00- 美东时间+12:45- 支持分钟偏移-09:30- 支持负分钟偏移
无效格式示例:
- ❌
CST- 时区缩写 - ❌
UTC- 时区缩写 - ❌
+8:00- 缺少前导零 - ❌
+08:0- 分钟格式错误 - ❌
+25:00- 超出有效范围
完整示例
// 完整的3种时间字段模型
define_model!
// 数据创建 - 3种方案对比
let now = now;
let test_model = TimeZoneTestModel ;
最佳实践
- 推荐使用方案1(
datetime_field())作为主要时间字段 - 需要本地时间时使用方案2(
datetime_with_tz_field()) - 需要字符串格式时使用方案3(RFC3339)
- 始终使用
Utc::now()作为时间源,让框架处理转换
时区辅助工具
rat_quickdb 提供2个重要的时区处理工具,位于 rat_quickdb::utils::timezone 模块:
1. parse_timezone_offset_to_seconds()
将时区偏移字符串转换为秒数
use parse_timezone_offset_to_seconds;
let seconds = parse_timezone_offset_to_seconds?; // 返回 28800
let seconds = parse_timezone_offset_to_seconds?; // 返回 -18000
2. utc_to_timezone() ⭐ 非常常用
将UTC时间转换为指定时区的时间(如果要存储特定时区时间的话)
use utc_to_timezone;
let utc_now = now;
let beijing_time = utc_to_timezone?; // 北京时间
let ny_time = utc_to_timezone?; // 美东时间
工具使用示例:
use *;
// 手动时区转换(框架通常自动处理,但如果要存储特定时区时间很有用)
let now = now;
let beijing_dt = utc_to_timezone?; // 存储北京时间
let est_dt = utc_to_timezone?; // 存储美东时间
// 验证时区格式
let offset_seconds = parse_timezone_offset_to_seconds?; // 34200
完整示例参考:
examples/test_datetime_with_tz_field.rs- 3种时间字段完整演示
这种设计确保了:
- ✅ 时区一致性 - 避免时区混乱
- ✅ 跨数据库兼容 - 统一的UTC标准
- ✅ 性能优化 - 避免复杂的数据库时间转换
- ✅ 用户友好 - 灵活的显示格式控制
📝 索引支持
- 唯一索引:
unique()约束 - 复合索引: 多字段组合索引
- 普通索引: 基础查询优化索引
- 自动创建: 基于模型定义自动创建
- 跨数据库: 支持所有数据库类型的索引
🌟 版本信息
当前版本: 0.3.4
支持Rust版本: 1.70+
重要更新: v0.3.0 强制使用define_model!宏定义模型,修复重大架构问题,提升类型安全性!
📄 许可证
本项目采用 LGPL-v3 许可证。
🤝 贡献
欢迎提交Issue和Pull Request来改进这个项目!
📚 技术文档
数据库限制说明
- MySQL 限制说明 - 必须遵守的索引长度限制
- PostgreSQL 限制说明 - 必须遵守的UUID类型处理要求
其他文档
🔧 疑难杂症
并发操作的网络延迟问题
在高并发操作中,特别是跨网络环境访问数据库时,可能会遇到数据同步问题:
问题描述
在高并发写入后立即进行查询操作时,可能出现查询结果不一致的情况,这通常由以下原因造成:
- 网络延迟: 云数据库或跨地域访问的网络延迟
- 数据库主从同步: 主从复制架构下的同步延迟
- 连接池缓冲: 连接池中的操作队列缓冲
解决方案
方案1: 根据网络环境配置等待时间
// 网络环境与建议等待时间
let wait_ms = match network_environment ;
// 在写入操作后添加等待
sleep.await;
方案2: 使用重试机制
async
方案3: 智能延迟检测
// 动态检测网络延迟并调整等待时间
async
最佳实践建议
- 本地开发: 无需等待或等待5-10ms
- 局域网环境: 等待10-50ms
- 云数据库: 等待100-200ms或使用重试机制
- 生产环境: 强烈建议使用重试机制代替固定等待
- 高并发场景: 考虑使用批量操作减少网络往返
架构说明
rat_quickdb采用单Worker架构来保证数据一致性:
- 单Worker: 避免多连接并发写入导致的数据冲突
- 长连接: Worker与数据库保持持久连接,减少连接开销
- 消息队列: 通过异步消息队列处理请求,保证顺序性
这种设计在保证数据一致性的同时,仍能提供良好的并发性能。
📞 联系方式
如有问题或建议,请通过以下方式联系:
- 创建Issue: GitHub Issues
- 邮箱: oldmos@gmail.com