Peewee:外部事务不会回滚内部事务(保存点)

Peewee: Outer transaction does not roll back inner transaction (savepoints)

运行 以下 python 脚本两次抛出此错误:

peewee.ProgrammingError: relation "test_table" already exists

因为 table 没有在 .rollback() 上删除。删除内部事务(with test_db.atomic())有效。为什么内部事务(根据 documentation 只是保存点)没有回滚?

from datetime import datetime
from peewee import Model, DateTimeField
from playhouse.postgres_ext import PostgresqlExtDatabase

"""
CREATE ROLE test WITH LOGIN;
DROP DATABASE IF EXISTS test;
CREATE DATABASE test WITH OWNER test;
"""

CREDENTIALS = {
    "database": "test",
    "user": "test",
    "password": None,
    "host": "localhost",
    "port": 5432,
    "register_hstore": False,
}


test_db = PostgresqlExtDatabase(**CREDENTIALS)
test_db.connect()
test_db.set_autocommit(False)
test_db.begin()  # start transaction

class TestTable(Model):
    timestamp = DateTimeField(null=False, default=datetime(1970,1,1,0,0,0,))

    class Meta:
        db_table = "test_table"
        database = test_db

with test_db.atomic():

    TestTable.create_table()
    TestTable.create()

test_db.rollback()  # rollback transaction

print TestTable.get().timestamp
test_db.close()

版本

peewee==2.8.3
psycopg2==2.6.2

PostgreSQL 9.5.1 on x86_64-apple-darwin15.3.0, compiled by Apple LLVM version 7.0.2 (clang-700.1.81), 64-bit

根据您使用的数据库,DDL(架构更改)可能无法回滚。

Postgresql 和 SQLite 似乎都支持回滚 DDL,但 MySQL 不支持。

但是,SQLite 的 Python 驱动程序有一个错误,导致它在您发出 DDL 时发出 COMMIT。第一个补丁于 2010 年提交:http://bugs.python.org/issue10740 .

另外看看 pysqlite2,它与标准库 sqlite3 基本相同:

https://github.com/ghaering/pysqlite/blob/ca5dc55b462a7e67072205bb1a9a0f62a7c6efc4/src/cursor.c#L537-L547