on_commit 是「事务提交之后再做」的标准写法(发通知、入队任务)。它到底什么时候执行?回滚了怎么办?多个回调互相影响吗?这篇用事件日志把每种情形排出来,并用另一个数据库连接验证「此刻数据是否已经可见」。
写入 a(还没提交) 注册回调 A 注册回调 B(内层) 内层 atomic 退出(保存点释放,外层还没提交) 回调 A 执行(另一个连接此刻能看到该行:True) 回调 B(在内层 atomic 里注册) 执行(另一个连接此刻能看到该行:True) 外层 atomic 退出(已提交)
回调是在 COMMIT 之后、atomic 块退出时执行的,所以可以放心地在里面通知别人「数据已经在了」(第 106、119、120 篇会用到)。
注册回调 R 事务因异常回滚 回调 N(autocommit,没有 atomic) 执行 autocommit 下注册 N 之后
没有事务时没有「提交」这件事,回调立即执行。
内层回滚 回调 外层 执行 回调 外层-2 执行 已提交
回调按保存点记录,保存点回滚时一起丢弃。
回调 1 执行 回调 X 抛出异常 atomic 退出时向外抛出 RuntimeError 回调抛异常之后,事务里写的行(kept-1)还在吗: True (事务在回调之前已经提交) --- robust=True: 回调 1 执行 回调 X 抛出异常 回调 3 执行 robust=True:没有异常向外抛,kept-2 在库里: True
事务已经提交,异常不会让数据回滚。用 robust=True 让后面的回调不受影响(异常只记录日志)。
回调里写库的 SQL:INSERT INTO "lab_acct" ("name") VALUES (回调里的数据库写入不在原事务里。