【问题标题】:SQLAlchemy(Postgresql) - Race ConditionsSQLAlchemy(Postgresql) - 竞争条件
【发布时间】:2012-06-17 12:47:37
【问题描述】:

我们正在编写一个库存系统,我对 sqlalchemy (postgresql) 和事务/会话有一些疑问。这是一个使用 TG2 的网络应用程序,不确定这是否重要,但对于很多信息来说从来都不是坏事。

  1. 如何确保在更改库存数量时不会遇到竞争状况。如果我理解正确,如果用户将减少某个项目的库存以说 0 并且用户 2 也试图将库存减少到 0,那么如果用户 1 的会话尚未提交,那么用户 2 的起始库存编号将会与用户相同,导致双方都提交时出现竞争条件,一个覆盖另一个而不是产生复合效果。

  2. 如果我想将 postgresql 序列用于订单/发票编号等内容,如何在不遇到竞争条件的情况下从 sqlalchemy 获取/设置下一个值?

编辑:我想我找到了我需要使用 with_lockmode 的解决方案,用于更新或共享。如果我弄错了,我将保留更多答案或让其他人纠正我。

TIA

【问题讨论】:

    标签: python postgresql web-applications sqlalchemy turbogears2


    【解决方案1】:

    如果两个事务尝试同时设置相同的值,其中一个会失败。丢失的将需要错误处理。对于您的特定示例,您将需要查询零件数并更新同一事务中的零件数。

    序列号没有竞争条件。保存使用数据库将自动分配的序列号的记录。

    编辑:

    注意 Limscoder 指出您需要将隔离级别设置为可重复读取。

    【讨论】:

    • 所以如果有 5 件库存。会话/交易 1 将减少 2(已售出 2 个),会话/交易 2 将检查库存以查看有多少。如果事务 2 在事务 1 完成之前运行,事务 2 是否知道有 3 个库存,还是仍然看到 5 个?
    • 您要做的是查询一次以显示有多少商品有库存。两个用户都将看到 5 件库存商品,都请求 3 件。当他们提出请求时,您开始事务,请求项目数量以确保您可以填写请求,然后尝试提交事务。如果两个事务同时发生,则所有对项目数的查询都将返回 5。在竞争条件中出现错误的事务将失败。您可以通过重新启动事务然后发现没有足够的项目并让用户知道来处理该故障。
    • 如果那是不可接受的(做音乐会门票或类似的销售点。)当用户询问有多少部分 X 时,您可以锁定部分 X 以供他们使用或留出一些他们正在考虑使用该项目时的零件数量。
    • “如果两个事务尝试同时设置相同的值,其中一个将失败”——此行为取决于查询的隔离级别。使用 postgresql 的默认隔离级别(已提交读),第二次更新将成功且没有错误,并且该行将包含不正确的值。
    • update tablename set columnname=columnname+? where tableid=? 这样的查询在默认(最快)隔离级别下是安全的。但我不认为 SQLAlchemy 可以生成这样的查询。
    【解决方案2】:

    设置您正在谈论的场景并查看您的配置如何处理它。只需打开两个单独的连接来测试它。

    还阅读了 FOR UPDATE For Update 以及事务隔离级别 Isolation Level

    【讨论】:

      猜你喜欢
      • 2014-04-02
      • 2014-02-23
      • 1970-01-01
      • 2022-01-23
      • 2018-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多