May*_*ank 2 php postgresql transactions distributed-transactions prepared-statement
我有两个数据库服务器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
...
);
Run Code Online (Sandbox Code Playgroud)
现在,如果用户想创建一个相册,我的PHP代码需要做的是:
是否可以将这两个语句保留在事务中?我也可以使用php解决方案。我的意思是,如果有需要php代码来保留db句柄并在这些句柄上进行提交或回滚的解决方案,我就很好。
任何帮助深表感谢。
是的,有可能,但是您真的需要吗?
在确定这实际上必须是两个独立的数据库之前,请三思而后行。
您可以只保持两个连接都打开,如果第二个命令失败,则回滚第一个命令。
如果您确实需要准备交易,请继续阅读。
关于您的模式-为了方便起见,我将在数据库端使用序列生成器和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,
...
);
Run Code Online (Sandbox Code Playgroud)
现在,您将需要一些外部粘合剂-分布式事务处理协调器(?)-才能使其正常工作。
诀窍是使用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'" );
}
?>
Run Code Online (Sandbox Code Playgroud)
再说一遍-在使用前先考虑一下。欧文的建议可能更明智。
哦,还有一点需要注意...要使用此PostgreSQL功能,您需要将max_prepared_transactionsconfig变量设置为非零值。
| 归档时间: |
|
| 查看次数: |
4156 次 |
| 最近记录: |