Postgresql: 准备交易[英] Postgresql: PREPARE TRANSACTION

本文是小编为大家收集整理的关于Postgresql: 准备交易的处理方法,想解了Postgresql: 准备交易的问题怎么解决?Postgresql: 准备交易问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我有两个数据库服务器 db1 和 db2.

db1 有一个名为 tbl_album
的表db2 有一个名为 tbl_user_album

的表
CREATE TABLE tbl_album
(
id    PRIMARY KEY,
name  varchar(128)
...
);

CREATE TABLE tbl_user_album
(
id          PRIMARY KEY,
album_id    bigint
...
);

现在,如果用户想要创建相册,我的 php 代码需要做的是:

  • 在 db1 中创建一条记录并保存它的 id(主键)
  • 使用保存在第一个语句中的记录在 db2 中创建记录

是否可以将这两个语句保留在事务中?我也可以使用 php 解决方案.我的意思是,如果有一个解决方案需要 php 代码来保留数据库句柄并在这些句柄上提交或回滚,那我很好.

非常感谢任何帮助.

推荐答案

有可能,但你真的需要吗?

在决定这确实必须是两个独立的数据库之前,请三思而后行.

如果第二个命令失败,您可以只保持两个连接打开并回滚第一个命令.

如果您真的需要准备好的交易,请继续阅读.

关于您的架构 - 为了方便起见,我会在数据库端使用序列生成器和 RETURNING 子句.

CREATE TABLE tbl_album (
  id    serial PRIMARY KEY,
  name  varchar(128) UNIQUE,
  ...
);
CREATE TABLE tbl_user_album (
  id          serial PRIMARY KEY,
  album_id    bigint NOT NULL,
  ...
);

现在您需要一些外部粘合剂 - 分布式事务协调器 (?) - 以使其正常工作.

诀窍是使用 PREPARE TRANSACTION而不是 COMMIT.然后在两个事务都成功后,使用 COMMIT PREPARED.

PHP 概念验证如下.

警告!此代码缺少关键部分 - 即错误控制.$db2 中的任何错误都应该被捕获并且 ROLLBACK PREPARED 应该在 $db1 上执行如果您没有发现错误,您将留下 $db1 冻结交易,这非常非常糟糕.

<?php
$db1 = pg_connect( "dbname=db1" );
$db2 = pg_connect( "dbname=db2" );
$transid = uniqid();

pg_query( $db1, 'BEGIN' );
$result = pg_query( $db1, "INSERT INTO tbl_album(name) VALUES('Absolutely Free') RETURNING id" );
$row = pg_fetch_row($result);
$albumid = $row[0];
pg_query( $db1, "PREPARE TRANSACTION '$transid'" );
if ( pg_query( $db2, "INSERT INTO tbl_user_album(album_id) VALUES($albumid)" ) ) {
    pg_query( $db1, "COMMIT PREPARED '$transid'" );
}
else {
    pg_query( $db1, "ROLLBACK PREPARED '$transid'" );
}
?>

再一次 - 在你使用它之前三思而后行.Erwin 的建议可能更明智.

哦,还有一点需要注意...要使用此 PostgreSQL 功能,您需要设置 max_prepared_transactions 配置变量为非零值.

本文地址:https://www.itbaoku.cn/post/1764122.html