【问题标题】:How do I perform a mongodb two phase commit in grails?如何在 grails 中执行 mongodb 两阶段提交?
【发布时间】:2014-01-27 07:26:41
【问题描述】:

我正在开发一个使用 mongodb 的系统。对于特定情况,我需要能够回滚保存。我该如何继续使用 GORM?

【问题讨论】:

  • MongoDB 中的两阶段提交不是原子的,如果你愿意,那么你需要一种真正支持它的技术
  • @Sammaye 我只想能够回滚。
  • 好的,这在 85% 的应用程序/数据库故障中应该是可行的,但请记住,两阶段提交不是服务器端的,所以在某些情况下应用程序可能仍然会遇到不一致.无论如何,我想我会明白这一点,让你更了解情况:)

标签: java mongodb grails grails-orm


【解决方案1】:

我只是按照http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits 的说明进行操作。我的代码如下:

FinancialTransaction financialTransaction = createFinancialTransaction(transactionType, amount, from, to,
             process)

        financialTransaction = financialTransaction.save(flush: true, failOnError: true)

        financialTransaction.transactionStatus = FinancialTransactionStatusEnum.PENDING
        financialTransaction = financialTransaction.save(flush: true, failOnError: true)


        def transactionLineNumber = 1
        financialTransaction.addToTransactionItems( new FinancialTransactionItem(financialAccount: from.financialAccount, 
            transactionLineNumber: transactionLineNumber++, debitAmount: amount, creditAmount: 0,
            description: "Money debited from Unions account for loan." ))
        financialTransaction.addToTransactionItems( new FinancialTransactionItem(financialAccount: to.financialAccount,
            transactionLineNumber: transactionLineNumber++, creditAmount: amount, debitAmount: 0, 
            description: "Money credited to Coops account from a loan received from a Union." ))

        financialTransaction.save( flush: true, failOnError: true)

        financialTransaction.transactionItems.each()  { transactionItem -> 
                    financialAccount = transactionItem.financialAccount


                if( financialAccount.pendingTransactions.contains(financialTransaction.id )) //transaction has been committed to this account(used during recovery)
                    return

                delta = (transactionItem.debitAmount == 0) ? transactionItem.creditAmount : transactionItem.debitAmount
                sign = (transactionItem.debitAmount == 0) ? 1.0 : -1.0
                newBalance = financialAccount.totalBalance + delta * sign

                financialAccount.totalBalance = newBalance
                financialAccount.pendingTransactions << financialTransaction.id

                financialAccount.save(flush: true, failOnError: true)

                if(log.isDebugEnabled())
                        log.debug("Saved Financial Account Id: ${transactionItem.financialAccount.id} Balance: ${newBalance}")

                new FinancialAccountChange(financialAccount: financialAccount, updatedBalance: newBalance,
                    delta: delta * sign, financialTransactionItem: transactionItem).save(flush: true, failOnError: true)

        }

        financialTransaction.transactionStatus = FinancialTransactionStatusEnum.COMMITTED
        financialTransaction = financialTransaction.save(flush: true, failOnError: true)

        financialTransaction.transactionItems*.financialAccount.each { fA ->
            fA.pendingTransactions - financialTransaction.id
            fA.save( flush: true, failOnError: true )           
        }

        financialTransaction.transactionStatus = FinancialTransactionStatusEnum.DONE
        financialTransaction = financialTransaction.save(flush: true, failOnError: true)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-13
    • 2012-11-06
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 2013-05-21
    相关资源
    最近更新 更多