2017-02-17 47 views
1

我已经得到了跨越某些表提交一些数据的一些客户端代码,简单来说就像这样:如何在更新后立即获取时间戳值?

  • 客户端[ID,平衡,时间戳]
  • ClientAssets [ID,由assetid,数量]
  • ClientLog [ID,客户端Id,BalanceBefore,BalanceAfter]

当客户购买的资产,我做了下面的伪代码:

初学者ñ交易

  1. GetClientRow其中id = 1
  2. 拥有新资产的成本余额不足?是...
  3. 插入到客户资产...
  4. UpdateClient - >更新客户端设置余额= f_SumAssetsForClient(1)WHERE ID = 1和时间戳= TS从步骤1;
  5. GetClientRow当ID = 1
  6. 插入进ClientLog BalanceBefore =余额在步骤1中,BalanceAfter =余额在步骤5. COMMIT

在步骤4中,客户端行中1个更新语句中使用更新的一个函数'f_SumAssetsForClient',它为客户端汇总资产并返回这些资产的余额。同样在第4步,时间戳会自动更新。

我的问题是,当我在第5步再次调用GetClientRow时,有人可能更新了客户端余额,所以当我在步骤6中写入日志时,它不是真正的这一套步骤后的平衡。这将是这笔交易之外的另一笔写款之后的余额。

如果我在步骤4中调用UPDATE时可以从客户端行获取新更新的时间戳,那么我可以通过此步骤仅抓取客户端行,其中TS =新更新的TS。这可能吗?或者是我的设计有缺陷。我无法找到解决步骤5和步骤6之间的陈旧数据问题的方法。我觉得在表格设计中存在问题,但无法完全看到它。

+1

听起来像你需要一个步骤3。5那就是'选择f_SumAssetsForClient(1)'然后存储该值,然后进行更新,然后写日志的价值观 - 你不应该有在所有处理时间戳 - 或做全过程作为存储过程 –

+0

@MichaelCoxon哦,现在总是有意义的。基本上,在步骤4之后的任何时候,数据读取都是不可信的。但如果我在最终的UPDATE之前获取所有的值,这些值由时间戳检查保护,并确定提交或回滚,并使用它们来构建报告,那么它应该没问题。谢谢 :)。 –

+1

那么,你在一个事务中运行这些语句,所以常用的方法是将第一选择中的锁升级到WRITE锁(似乎是MySQL中的SELECT ... FOR UPDATE),这会阻止其他会话从修改这个ID。 – dnoeth

回答

1

步骤1需要是SELECT ... FOR UPDATE。任何其他需要更改的数据也需要“锁定”FOR UPDATE

这样,另一个线程不能潜入并修改这些行。他们可能会被推迟到COMMITted之后,或者可能会出现死锁。无论哪种方式,你担心的事情都不会发生。没有时间戳游戏。

+0

是的,我将不得不改变我的答案,因为这是我最终使用和什么似乎最正确的。我最初的问题表明,我正在处理一个像数据结构的树/图,SELECT ... FOR UPDATE专门用于处理这种数据模型。 –

1

从评论复制

听起来像是你需要逐步3.5是SELECT f_SumAssetsForClient(1)然后 商店值,然后进行更新,然后写日志的价值观 - 你 不应该有应对带有时间标记在所有 - 或做整个过程作为 一个存储过程

相关问题