Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.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
Google app engine 如果最近的事务引发了一个“错误”,事务db.get()是否可能返回一个过时的结果;特别";例外?_Google App Engine_Google Cloud Datastore - Fatal编程技术网

Google app engine 如果最近的事务引发了一个“错误”,事务db.get()是否可能返回一个过时的结果;特别";例外?

Google app engine 如果最近的事务引发了一个“错误”,事务db.get()是否可能返回一个过时的结果;特别";例外?,google-app-engine,google-cloud-datastore,Google App Engine,Google Cloud Datastore,这是在appengine中 注意:如果应用程序在提交事务时收到异常,并不总是意味着事务失败。在事务已提交并最终将成功应用的情况下,您可以接收超时、TransactionFailedError或InternalError异常 考虑以下场景 我更新交易中的实体A 事务操作导致上述特殊“异常”,其中事务已提交并最终将应用 我在另一个事务中运行db.get(entity\u a\u key\u goes\u here),或者几乎与步骤2同时运行 如果上面的步骤3返回None,我通过将键设置为entity

这是在appengine中

注意:如果应用程序在提交事务时收到异常,并不总是意味着事务失败。在事务已提交并最终将成功应用的情况下,您可以接收超时、TransactionFailedError或InternalError异常

考虑以下场景

  • 我更新交易中的实体
    A
  • 事务操作导致上述特殊“异常”,其中事务已提交并最终将应用
  • 我在另一个事务中运行
    db.get(entity\u a\u key\u goes\u here)
    ,或者几乎与步骤2同时运行
  • 如果上面的步骤3返回
    None
    ,我通过将键设置为
    entity\u a\u key\u goes\u here
    db.put()
    来创建该实体(步骤3和该步骤在同一事务中运行)
  • 我的问题:


    上面步骤3中的事务性
    db.get()
    操作是否可能返回过时的值(或者不是步骤1中设置的更新值)?事务性的
    db.get()
    操作是否保证返回最新的结果,即使“奇怪的”事务异常恰好发生在它之前?

    我认为在这种情况下,步骤3的结果将是一个过时的值。在这种情况下,“最新鲜”的结果可能不是步骤1中的实体


    我的建议是在检索值时使用memcache(在memcache未命中时返回到
    db.get()
    调用),并在更新实体时更新memcache。使用实体键作为memcache键。事实上,这就是ndb自动工作的方式。

    根据我对“ndb”文档的阅读,我理解如果您在“transactions”中同时运行
    get()
    put()
    @ndb.transactional
    ),那么您将不会得到过时的数据。”ndb'将为更新的数据提供服务,或两者都失败

    事务要么失败,要么成功。与其他dbms一样,ndb也维护“日志”

    希望这有帮助。

    get不是真正的“事务性”;如果事务只包含读取,那么提交事务实际上不会做任何事情。在事务中执行读取只保证一件事:如果读取返回的值在应用事务中的任何写入操作时不再是最新值,则事务将中止,并且不会发生任何写入操作

    因此,允许发生以下一系列事件:

  • 启动事务1
  • 在事务1中,您读取实体A,它返回状态A1
  • 在事务1中,将实体A从状态A1更新为状态A2
  • 提交事务1时,它会失败,出现上述异常之一
  • 启动事务2
  • 在事务2中,您读取实体A,它返回状态A1
  • 事务1应用于后台的数据存储,将状态A1更改为状态A2
  • 结束事务2(没有提交,因为没有写入)
  • 但是,这一系列事件是不同的:

  • 启动事务1
  • 在事务1中,您读取实体A,它返回状态A1
  • 在事务1中,将实体A从状态A1更新为状态A2
  • 提交事务1时,它会失败,出现上述异常之一
  • 启动事务2
  • 在事务2中,您读取实体A,它返回状态A1
  • 在事务2中,您将实体A从状态A1更新为状态A3
  • 事务1应用于后台的数据存储,将状态A1更改为状态A2
  • 事务2现在将不会成功提交,因为它将要应用的写操作基于过时的实体A版本。它将失败,而A将处于状态A2
  • 因此,在问题中添加步骤4后,您将进入第二个事件序列。即使实体确实存在,步骤3中的get也可能返回None,但在这种情况下,后续写入不可能成功:事务已过期,因此无法提交。事务将被重试,第二次,get将返回在步骤1中编写的对象,这正是您想要的


    因此,非常简短的回答是:是的,它可以返回一个过时的值,但是可以保证,如果结果是过时的,那么在同一事务中对该实体的后续写入将失败,因此这实际上不会导致问题。

    在执行put()的事务之后,我在一个单独的事务中运行get(),put()返回了“特殊”异常。谢谢@Torne!我编辑了我的问题以添加步骤4。如果步骤3返回None(这意味着它不存在),那么我创建它。我使用该实体来确保事务不会运行两次,因为我的操作不是真正的幂等。我的问题是步骤3
    db.get()是否有可能
    返回
    None
    当它实际上已经通过延迟的事务事件创建时,然后继续成功提交事务中的所有内容?谢谢!编辑回答以澄清,但对您的评论的直接回答是“否,它将无法提交”: