Pony ORM 作者在这里。
此行为是 MySQL 特定的错误,已在 Pony ORM 0.4.9 版本中修复,因此请升级。我的答案的其余部分是对导致该错误的原因的解释。
该错误的原因如下。为了防止丢失更新,Pony ORM 使用乐观检查。 Pony 跟踪在程序执行期间读取或更改了哪些属性,然后在WHERE
相应的部分UPDATE
询问。这样Pony就保证了不会因为并发更新而丢失数据。让我们考虑下一个例子:
@db_session
def some_function()
obj = MyObject[123]
print obj.x
obj.x = 100
退出时some_function
the @db_session
装饰器将提交正在进行的事务。在提交之前,对象的数据将通过以下方式保存UPDATE
命令:
UPDATE MyTable
SET x = <new_value>
WHERE id = 123 and x = <old_value>
您可能想知道,为什么这个附加条件and x = <old_value>
加入?这是因为 Pony 知道程序看到了属性的先前值x
并且可以使用该值来计算相同属性的新值。因此 Pony 采取措施保证该属性在当前时刻保持不变。UPDATE
。这种方法称为“乐观并发检查” http://www.avaje.org/occ.html(另请参阅维基百科文章《乐观并发控制》 http://en.wikipedia.org/wiki/Optimistic_concurrency_control)。由于大多数数据库默认使用的隔离级别不是SERIALIZABLE
,如果没有这个额外的检查,其他一些事务可能已经设法更新了x
属性在我们的事务提交之前,那么并发事务写入的值将会丢失。
当Python数据库驱动执行时UPDATE
查询,返回满足条件的行数UPDATE
标准。这样 Pony 就知道更新是否成功。如果结果为 1,则意味着成功找到并更新了一行,但如果结果为 0,则意味着该行已被另一个事务修改,并且现在不满足WHERE
部分。发生这种情况时,Pony 会终止当前事务以防止更新丢失。
该错误的原因是,虽然所有其他数据库驱动程序都返回由WHERE
部分标准,MySQLdb
驱动程序默认返回实际修改的行数!因此,如果属性的新值与同一属性的原始值相同,MySQLdb
报告 0 行被修改,Pony(0.4.9 版本之前)错误地认为这意味着该行被并发事务修改。从 0.4.9 版本开始 Pony ORM 讲述MySQLdb
驱动程序以标准方式运行并返回找到的行数,而不是实际更新的行数。
希望这可以帮助 :)
附:我偶然发现您的问题,为了可靠地获得有关 Pony ORM 的答案,我建议您将问题发送到我们的邮件列表http://ponyorm-list.ponyorm.com http://ponyorm-list.ponyorm.com。如果您认为发现了错误,可以在此处打开问题:https://github.com/ponyorm/pony/issues https://github.com/ponyorm/pony/issues。
谢谢你的问题!