Rust in Everything
基于 sea-orm 2.0.4

连接与事务

查询主线和写入主线最后都落到同一个地方:ConnectionTrait 的某个方法,收一棵语句树或一个 Statement,交给一个具体的连接执行。这一部分讲这个「连接」:它是什么、怎么配、出错时给你什么。相关源码在 src/database/(mod.rs 752 行,Database::connect 和 ConnectOptions;db_connection.rs 926 行;connection.rs 250 行,ConnectionTrait;transaction.rs 816 行;mock.rs 886 行;proxy.rs 250 行)、src/driver/(sqlx_common.rs 183 行、sqlx_postgres.rs 951 行)和 src/error.rs(349 行)。

sea-orm 在这一层自己做的事很少:池、借连接、事务的 BEGIN / COMMIT、错误的原始信息都来自 sqlx,sea-orm 负责把 ConnectOptions 翻译过去、按后端分派、把 sqlx::Error 包进 DbErr。所以这几页会频繁链到 sqlx 卷的连接池和事务。

  1. DatabaseConnection 与 ConnectOptions:Database::connect 按 URL 的 scheme 选驱动;DatabaseConnection 在 2.0 是包着 DatabaseConnectionType 的 struct,Postgres 分支里只有一个 PgPool;ConnectOptions 每一项对应的 sqlx 设置和两边的默认值,connect_timeout 实际是 sqlx 的 acquire_timeout(两个都设时 acquire_timeout 赢);set_schema_search_path 拼出来的 SET 语句、statement_timeout、空闲才 ping 的 test_before_acquire_if_idle_for;收语句树的方法和 *_raw、execute_unprepared 各走哪种协议。
  2. 事务:DatabaseTransaction 持有一条池连接,事务里的语句都走它;嵌套、提交、回滚,以及没提交就 drop 时发生什么。
  3. 错误:DbErr 的每个分支在 2.0.4 里由谁构造、Display 长什么样;sql_err() 按 SQLSTATE 认出唯一约束和外键冲突;直接把错误文本显示给用户会泄漏什么。
  4. Mock 与 Proxy:MockDatabase 按顺序返回预置结果并记下每条语句,用来测生成了什么 SQL;ProxyDatabase 把语句交给你自己的回调。
flowchart TB
  opts[ConnectOptions] -->|"Database::connect"| dbc[DatabaseConnection]
  dbc --> inner["inner: DatabaseConnectionType"]
  inner --> pg["SqlxPostgresPoolConnection"]
  inner --> mock["Mock / Proxy"]
  pg --> pool["sqlx PgPool"]
  dbc -->|begin| txn["DatabaseTransaction"]
  txn --> one["一条 PoolConnection"]
  pool --> one
  pg -->|"sqlx::Error"| err[DbErr]

每条语句单独向池借一次连接、两条语句可能落在不同的后端进程上,一次 find 的全过程已经用实验看过,这一部分直接引用它的结论。

💬 关联讨论

发起讨论
加载中...