GAE:防止无意中覆盖数据
GAE: Prevent inadvertent overwriting of data
假设我有一个具有两个属性的人的实体:
class Person(ndb.Model)
payments = ndb.IntegerProperty(default=0)
name = ndb.StringProperty()
我想我会在事务中更新 payments
,但在更新 name
时我不需要事务。
但是,在下面的场景中,我可能会丢失 payments
的值:
TIME | INSTANCE1 | INSTANCE2 (in transaction)
=====================================================
|| | person1 = key1.get() |
|| | person1.name = "John" | person1 = key1.get()
|| | [other stuff that] | person1.payments = 100
|| | [takes some time] | person1.put()
|| | person1.put() |
|| |
\/
在这种情况下,似乎INSTANCE1会覆盖INSTANCE2中写入的支付金额,支付金额将丢失。
这是否意味着我在更新时也需要使用事务name
以确保重要数据永不丢失?
或者更一般地说,如果我使用事务来更新实体的任何 属性,我应该使用事务来更新该实体的所有内容吗?
交易仅在 .put() 调用期间进行...因此无论您是否使用交易,您的示例在两种情况下都将具有相同的效果。您将需要实现自己的锁定机制来识别对象自加载以来是否已更改...就像检查 last_updated DateTimeProperty ...然后引发异常 (https://en.m.wikipedia.org/wiki/Optimistic_concurrency_control)
(抱歉格式太平淡...我在移动浏览器上)
是的,为所有更新使用事务以避免您描述的情况可能是最安全的。您唯一的选择(我能想到的)是使用@Nick Franceschina 建议的锁定机制。
是的,在这种情况下您将失去 payments
的新值。数据存储没有更新 属性 值的概念,实体总是被完全覆盖。
The Datastore API does not distinguish between creating a new entity and updating an existing one. If the object's key represents an entity that already exists, the put() method overwrites the existing entity.
当两者都是交易时,它工作正常。结果就是这样。
When a transaction starts, App Engine uses optimistic concurrency control by checking the last update time for the entity groups used in the transaction. Upon commiting a transaction for the entity groups, App Engine again checks the last update time for the entity groups used in the transaction. If it has changed since our initial check, an exception is thrown.
在这种特殊情况下,当提交实例 A
中的事务时,App Engine 注意到自事务开始以来该实体已在其他地方更新。事务 A
已取消,默认情况下会重试。
假设我有一个具有两个属性的人的实体:
class Person(ndb.Model)
payments = ndb.IntegerProperty(default=0)
name = ndb.StringProperty()
我想我会在事务中更新 payments
,但在更新 name
时我不需要事务。
但是,在下面的场景中,我可能会丢失 payments
的值:
TIME | INSTANCE1 | INSTANCE2 (in transaction) ===================================================== || | person1 = key1.get() | || | person1.name = "John" | person1 = key1.get() || | [other stuff that] | person1.payments = 100 || | [takes some time] | person1.put() || | person1.put() | || | \/
在这种情况下,似乎INSTANCE1会覆盖INSTANCE2中写入的支付金额,支付金额将丢失。
这是否意味着我在更新时也需要使用事务name
以确保重要数据永不丢失?
或者更一般地说,如果我使用事务来更新实体的任何 属性,我应该使用事务来更新该实体的所有内容吗?
交易仅在 .put() 调用期间进行...因此无论您是否使用交易,您的示例在两种情况下都将具有相同的效果。您将需要实现自己的锁定机制来识别对象自加载以来是否已更改...就像检查 last_updated DateTimeProperty ...然后引发异常 (https://en.m.wikipedia.org/wiki/Optimistic_concurrency_control)
(抱歉格式太平淡...我在移动浏览器上)
是的,为所有更新使用事务以避免您描述的情况可能是最安全的。您唯一的选择(我能想到的)是使用@Nick Franceschina 建议的锁定机制。
是的,在这种情况下您将失去 payments
的新值。数据存储没有更新 属性 值的概念,实体总是被完全覆盖。
The Datastore API does not distinguish between creating a new entity and updating an existing one. If the object's key represents an entity that already exists, the put() method overwrites the existing entity.
当两者都是交易时,它工作正常。结果就是这样。
When a transaction starts, App Engine uses optimistic concurrency control by checking the last update time for the entity groups used in the transaction. Upon commiting a transaction for the entity groups, App Engine again checks the last update time for the entity groups used in the transaction. If it has changed since our initial check, an exception is thrown.
在这种特殊情况下,当提交实例 A
中的事务时,App Engine 注意到自事务开始以来该实体已在其他地方更新。事务 A
已取消,默认情况下会重试。