我有一个sqlalchemy脚本,它创建并使用许多表示许多用户连接的引擎实例。所有引擎都配置为指向同一数据库。
我有一个引擎,可以做超级的事情。我有另一个引擎“obobsenger”给鲍勃。
现在我正在做这样的事情:
sSQL = "GRANT ALL PRIVILEGES ON TABLE \"NICE_TABLE\" to bob;"
oSuperEngine.execute(sSQL)
sSQL = "insert into \"NICE_TABLE\" (foo) values (bar)"
oBobsEngine.execute(sSQL) # ERROR HERE
得到:
ProgrammingError: (ProgrammingError) permission denied for relation NICE_TABLE
这是为什么?
在psql中
oSuperEngine
告诉我bob从未被授予权限。如果我用超级用户登录psql并手动授予bob权限,那么一切正常。在我通过SqLalCyMy执行的情况下,我使用完全相同的命令。有什么东西不正确冲洗吗?sqlalchemy在尝试grant语句时是否出于某种原因喜欢无声地失败?我该怎么做?
道歉,不包括更多的代码,代码基础适度卷曲。事件的顺序已经用日志向我确认了…如果你需要更多的代码来理解我的问题,请告诉我。
一些原木
2014-03-10 10:07:24,767 - common.sqlalchemy_tools - DEBUG - connection string = "postgresql+psycopg2://super:password@localhost/db_name"
2014-03-10 10:07:24,767 - sqlalchemy.engine.base.Engine - INFO - BEGIN;
2014-03-10 10:07:24,767 - sqlalchemy.engine.base.Engine - INFO - {}
2014-03-10 10:07:24,767 - sqlalchemy.engine.base.Engine - INFO - GRANT ALL PRIVILEGES ON TABLE "MY_TABLE" to bob;
2014-03-10 10:07:24,767 - sqlalchemy.engine.base.Engine - INFO - {}
2014-03-10 10:07:24,768 - sqlalchemy.engine.base.Engine - INFO - COMMIT;
2014-03-10 10:07:24,768 - sqlalchemy.engine.base.Engine - INFO - {}
...
2014-03-10 10:07:24,804 - common.sqlalchemy_tools - DEBUG - connection string = "postgresql+psycopg2://bob:password@localhost/db_name"
2014-03-10 10:07:24,814 - sqlalchemy.engine.base.Engine - INFO - BEGIN;
2014-03-10 10:07:24,815 - sqlalchemy.engine.base.Engine - INFO - {}
2014-03-10 10:07:24,827 - sqlalchemy.engine.base.Engine - INFO - insert into "MY_TABLE" (stuff) values (other stuff);
2014-03-10 10:07:24,827 - sqlalchemy.engine.base.Engine - INFO - {}
2014-03-10 10:07:24,828 - sqlalchemy.engine.base.Engine - INFO - ROLLBACK
第一组发生在
\dp
上,第二组发生在bob的引擎上。错误如下:ProgrammingError: (ProgrammingError) permission denied for relation MY_TABLE
'insert into "MY_TABLE" (stuff) values (stuff);' {}
最佳答案
如果执行上述脚本,则会遇到事务隔离问题。我之前也有过类似的问题。这里要记住的一点是,bob的事务不会看到超级引擎所做的更改,因为事务仍在运行,隔离不允许非提交读取。关于这一点,PASGRESs有“AA>”,但本质是:一个未被接受的阅读是不可能的。
显然,您的解决方案是首先从超级引擎提交更改,然后在另一个事务中使用它。如果没有尝试过,但我的猜测是,您必须停留在默认的读提交隔离级别(因为较高的隔离将不允许检测变化,因为在这种情况下,事务-在这种情况下,BOBS -已经开始)。
因此,在执行bobs查询之前:
oSuperEngine.execute("COMMIT")
然而,这引发了一个侧面的问题,它有效地打破了交易带给你的可怕的东西:你不能轻易回滚,因为改变已经开始了。你基本上想要的是与保存点相反的:
尽管保存点尚未存储对数据库的更改,但它确保回滚仅返回到特定点,而不是一直返回。相反,您需要将其存储在数据库中,但可以回滚并再次将其从数据库中删除。我不知道这样的事情,我非常怀疑它的存在,因为它违反了交易隔离的原则。
我对这个问题的解决方案是编写自定义回滚例程,我将调用一个异常,以便我可以手动撤消更改。这是一个相当大的工作,但从长远来看是高维护。最后,在我的例子中,我重新考虑了我的解决方案,放弃了多引擎方法(但这是你必须自己做出的决定)。