Backends · 一个抽象层,六个 dialect

6 个后端
1 个抽象层

PostgreSQL / MySQL / MariaDB / SQLite / Oracle / SQL Server——同一份 ActiveRecord 代码,编译期检测后端能力 + 选择合适的 dialect。能力差异是显式的(CapabilityMatrix),dialect 差异是透明的(PG 的 EXCEPT、Oracle 的 MINUS、MySQL 的 ON DUPLICATE KEY、PG 的 ON CONFLICT——你只写一份 ORM 代码)。StorageBackend ABC 还允许你实现自己的 backend

StorageBackend · 抽象在哪里

ActiveRecord 把"怎么连数据库 / 怎么发 SQL / 怎么处理类型"全部下放给 StorageBackend ABC——上层 ActiveQuery / Builder 不知道你用的是哪种数据库,只知道它有一个 execute() 方法和一份 capabilities() 声明。这意味着:(1) 切换后端不改 ORM 代码,(2) 你可以写自己的 backend

SYSTEM · ActiveRecord 架构 ActiveRecord (Model API) CRUD / events ActiveQuery / Builder where / join / cte / set ops StorageBackend (ABC) ↑ 抽象接口:execute / fetch / capabilities ↓ 6 个内置 dialect 实现 + 你的 backend PG MySQL Maria SQLite Oracle MSSQL 数据库(PG / MySQL / SQLite / ...)
实现你自己的 backend
# your_backend.py
from rhosocial.activerecord.backend import StorageBackend

class YourBackend(StorageBackend):
  def execute(self, sql, params):
    return self._cursor.execute(sql, params)

  def capabilities(self):
    return {
      "cte": True,
      "recursive_cte": True,
      "json": True,
      "upsert": False,
    }

# 注册
Model.use_backend(YourBackend("yourdb://..."))

实现 ABC 的两个方法(execute + capabilities),加上 dialect 的几个细节(quoting、placeholder、自增 ID 取回方式),就能接入任何支持 DB-API 2.0 / async DB-API 的数据库。

每一个 · 都是一等公民

每个后端有独立的子目录(backends/postgresql/backends/mysql/ 等),里面有 setup(连接配置)、capabilities(详细能力清单)、dialect(特有语法)、ops(运维:连接池、慢查询、迁移)四类页面。点击下面的卡片进入。

能力矩阵 · 哪个后端支持哪个特性

12 项关键特性 × 6 个后端。● full 表示原生支持,◐ partial 表示有版本下限或语法限制(鼠标悬停查看具体版本), 表示不支持。所有数据来自 主仓 README 与各 dialect 实现的 capabilities() 声明。

特性 PostgreSQL MySQL MariaDB SQLite Oracle SQL Server
WITH (CTE) ◐ 8.0+ ◐ 10.2+ ◐ 3.8.3+
WITH RECURSIVE ◐ 8.0+ ◐ 10.2+ ◐ 3.8.3+
UNION / UNION ALL
INTERSECT / EXCEPT ◐ 8.0.31+ ◐ 10.3+ ◐ MINUS
JSON 字段类型 ● JSONB ◐ JSON ◐ JSON ◐ JSON1 ◐ 12c+ ◐ 2016+
ARRAY 字段类型 ◐ VARRAY
UPSERT (ON CONFLICT) ◐ ON DUP KEY ◐ ON DUP KEY ◐ 3.24+ ◐ MERGE ◐ MERGE
窗口函数 ◐ 8.0+ ◐ 10.2+ ◐ 3.25+
分区表
RETURNING 子句 ◐ 10.5+ ◐ 3.35+ ◐ INTO ◐ OUTPUT
异步驱动
嵌套事务(SAVEPOINT)

编译期检测SetOperationQueryCTEQuery、UPSERT API 等都会在编译期检查后端 capabilities()。不支持时给出明确错误("INTERSECT requires MySQL ≥ 8.0.31"),不会生成无法执行的 SQL。

选你用的后端 · 只看相关内容

能力矩阵适合横向比较。但当你已经决定用某个后端时,你只关心那一列——下面的选择器把视图收窄到单个 backend:安装命令、能力清单、版本限制、子目录链接。

SQLite 下方内容随选择实时更新

同一份 ORM 代码 · 6 个 dialect 的 SQL

backend 透明的最直接证据:一份 ActiveRecord 代码 → 6 种数据库各自的方言 SQL。下面以 UPSERT(最方言敏感的 DML)为例,看 StorageBackend 怎么把同一意图翻译到 6 种语法。差异部分用高亮标出。

同一份 ORM 代码(不变)
User.upsert(
  {"email": "alice@example.com", "name": "Alice", "login_count": 1},
  conflict_on=["email"],
  update_on_conflict={"login_count": User.c.login_count + 1}
)
→ PostgreSQL
INSERT INTO users(email, name, login_count)
VALUES (?, ?, 1)
ON CONFLICT (email) DO UPDATE SET
  login_count = users.login_count + 1;
→ MySQL
INSERT INTO users(email, name, login_count)
VALUES (?, ?, 1)
ON DUPLICATE KEY UPDATE
  login_count = login_count + 1;
→ MariaDB
INSERT INTO users(email, name, login_count)
VALUES (?, ?, 1)
ON DUPLICATE KEY UPDATE
  login_count = login_count + 1;
→ SQLite (3.24+)
INSERT INTO users(email, name, login_count)
VALUES (?, ?, 1)
ON CONFLICT(email) DO UPDATE SET
  login_count = login_count + 1;
→ Oracle
MERGE INTO users u
USING (SELECT ? email, ? name FROM DUAL) src
ON (u.email = src.email)
WHEN MATCHED THEN UPDATE SET login_count = login_count + 1
WHEN NOT MATCHED THEN INSERT (...) VALUES (...);
→ SQL Server
MERGE INTO users AS u
USING (VALUES (?, ?, 1)) AS src(email, name, lc)
ON u.email = src.email
WHEN MATCHED THEN UPDATE SET login_count = login_count + 1
WHEN NOT MATCHED THEN INSERT (...) VALUES (...);

这就是 backend 抽象的价值——你不需要记住 6 种 UPSERT 语法、哪个版本支持 RETURNING、Oracle 和 MSSQL 必须用 MERGE 的细节。StorageBackend 对应的 dialect 类负责把同一意图编译到正确的 SQL。同样的差异在 INTERSECT/EXCEPT、JSON 路径、窗口函数 OVER 子句、自增主键 RETURNING 上都存在。

选哪个后端 · 三句话决定

没有"最好的后端"——只有"最适合你这个阶段、这个团队、这个部署环境的后端"。下面三个典型场景给出推荐,同一个项目可以分阶段切换(开发用 SQLite、生产用 PG),ActiveRecord 代码不变。

阶段 · 开发 / 测试

SQLite

推荐 → SQLite
无服务器,单文件

开发期间 zero-setup(pip install 即可),测试用例每次创建新内存数据库(:memory:),CI 跑得飞快。3.8.3+ 已支持 CTE,3.24+ 支持 UPSERT,3.25+ 支持窗口函数——日常 ORM 能力齐全。

阶段 · 中小型生产

PostgreSQL

推荐 → PostgreSQL ≥ 14
能力最齐

新项目首选 PG。CTE / 递归 / JSONB / ARRAY / UPSERT / 窗口函数全部原生,索引类型最丰富(GIN / GiST / BRIN),EXPLAIN (ANALYZE, BUFFERS) 输出最详细。异步驱动 asyncpg 性能最好。

阶段 · 企业部署

Oracle / SQL Server

推荐 → 看 IT 既有栈
团队熟悉度优先

如果公司已经有 DBA 团队、合规要求、企业许可——继续用 Oracle 或 SQL Server 没问题。StorageBackend 透明处理 MERGE / MINUS / OUTPUT 等方言差异。MariaDB 在需要 temporal 表避开 Oracle 收购版 MySQL时是 MySQL 的合理替代。

不变的是 ActiveRecord 代码——业务逻辑、查询、模型定义不会因为切换后端而修改。这意味着从 SQLite 平滑升级到 PG / 从 MySQL 迁移到 PG 是可行路径,不需要重写应用层。当然 schema migration 仍然需要规划(不同后端的列类型、索引语法不同)——见 named-resources

深入 backends