Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 当扣除用户余额并调用第三方服务时,如何正确解释系统故障?_Postgresql - Fatal编程技术网

Postgresql 当扣除用户余额并调用第三方服务时,如何正确解释系统故障?

Postgresql 当扣除用户余额并调用第三方服务时,如何正确解释系统故障?,postgresql,Postgresql,假设一个用户想在网站上提取5.00美元的PayPal余额。因此,他们点击了一个取款端点,以确保他们有足够的余额,调用PayPal pay api,并在单个可序列化事务中扣除用户的现场余额 如果在成功执行PayPal支付请求并且用户获得其现场余额后,数据库服务器断开并且事务未能提交,会发生什么情况 有没有一种方法可以将所有这些调用封装在一个原子事务中?我假设您正在寻找两阶段提交 准备事务为两阶段准备当前事务 犯罪执行此命令后,事务不再关联 与本届会议的合作;相反,它的状态完全存储在磁盘上, 而且

假设一个用户想在网站上提取5.00美元的PayPal余额。因此,他们点击了一个取款端点,以确保他们有足够的余额,调用PayPal pay api,并在单个可序列化事务中扣除用户的现场余额

如果在成功执行PayPal支付请求并且用户获得其现场余额后,数据库服务器断开并且事务未能提交,会发生什么情况


有没有一种方法可以将所有这些调用封装在一个原子事务中?

我假设您正在寻找
两阶段提交

准备事务为两阶段准备当前事务 犯罪执行此命令后,事务不再关联 与本届会议的合作;相反,它的状态完全存储在磁盘上, 而且有很高的可能性,它可以被实施 成功,即使在提交之前发生数据库崩溃 请求的

一旦准备好,事务可以稍后提交或回滚 分别准备好提交或回滚


(我的扩张)

你不应该试图以原子的方式来做这件事。互联网API的本质使得这不可能

您可能应该执行类似以下伪代码的操作:

payment_id = random_payment_id()
try:
  db:
    insert into payments (payment_id, order_id, payment_amount, status, created)
      values (:payment_id, :order_id, :payment_amount, 'pending', now());
    commit;
  remote.create_payment(payment_id, payment_amount);
except remote.error:
  throw payment_error
付款确认时:

try:
  remote.execute_payment(payment_id);
  db:
    update payments set status='completed' where payment_id=:payment_id;
    commit;
except remote.error:
  throw payment_error
并且您必须定期检查“待定”付款的状态,因为您无法确定是否会收到所有付款确认:

db:
  select payment_id from payments
    where status='pending' and created<now()-'10 minutes';
for payment_id in db.result:
  if remote.payment_status(payment_id) == 'approved':
    remote.execute_payment(payment_id);
    db:
      update payments set status='completed' where payment_id=:payment_id;
      commit;
db:
从付款中选择付款id

其中status='pending'和createdTwo-phase commit不适合调用可能永远不会完成的远程、不可靠的函数。从链接文档:准备事务不用于应用程序或交互式会话。除非您正在编写事务管理器,否则可能不应该使用“准备事务”。在web上搜索“两阶段提交”
db:
  select payment_id from payments
    where status='pending' and created<now()-'10 days';
for payment_id in db.result:
  remote.cancel_payment(payment_id);
  db:
    update payments set status='failed' where payment_id=:payment_id;
    commit;