Rust in Everything
基于 sqlx 0.9.0

事务与迁移

这一部分讲建在连接之上的两样东西。它们都没有新的协议消息:事务是几条 BEGIN / SAVEPOINT / COMMIT / ROLLBACK 简单查询加一个记在连接上的深度计数,迁移是在一条连接上依次跑的十几条普通查询。代码量都不大:sqlx-core/src/transaction.rs 约 300 行(一半是注释掉的代码)加 Postgres 的 100 行;迁移是 sqlx-core/src/migrate/ 约 1000 行、sqlx-postgres/src/migrate.rs 370 多行、sqlx-macros-core/src/migrate.rs 不到 150 行。

  1. 事务:Transaction 是一条连接加一个 open 标记,深度记在连接上,begin / commit / rollback 发的 SQL 都由深度算出;没提交就 drop 只把 ROLLBACK 写进缓冲,池连接由归还时的 ping 发出,裸连接要等下一次使用;begin_with 怎么判定失败,0.9.0 里取消 begin 和事务内 begin_with 怎么让事务状态和连接对不上;Connection::transaction 闭包写法。
  2. 迁移:migrate! 在编译期把目录解析成 Migrator 常量(新增文件不触发重编译);run 的每一步和线上的消息;advisory lock 的键怎么从库名算出,出错时锁不释放;脚本和记账行同一个事务,-- no-transaction 的字面前缀和多语句陷阱;改了已应用迁移的报错;可逆迁移和 sqlx migrate revert;sqlx.toml 的 [migrate] 和 0.9 新增的 skip。
flowchart TB
  pool["Pool"] -->|"acquire"| conn["一条 PgConnection"]
  conn --> tx["Transaction 深度计数"]
  conn --> mig["Migrator::run"]
  mig -->|"每个迁移"| tx
  tx --> wire["BEGIN SAVEPOINT COMMIT ROLLBACK"]
  mig --> lock["pg_advisory_lock"]

两页都直接用前面的结果:事务控制语句为什么走简单查询协议见 Executor 与 Acquire,连接归还时的 ping 见 归还、Drop 与维护任务。

💬 关联讨论

发起讨论
加载中...