She*_*ena 4 python postgresql privileges sqlalchemy grant
我有一个sqlalchemy脚本,它创建并使用代表许多用户连接的许多引擎实例.所有引擎都配置为指向同一个postgres数据库.
我有一个引擎,oSuperEngine可以做超级的东西.我为鲍勃提供了另一个引擎'oBobsEngine`.
现在我正在做这样的事情:
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
Run Code Online (Sandbox Code Playgroud)
得到:
ProgrammingError: (ProgrammingError) permission denied for relation NICE_TABLE
Run Code Online (Sandbox Code Playgroud)
为什么是这样?
在psql中\dp告诉我bob从未被授予权限.如果我用超级用户登录psql并手动授予bob他的权限,那么一切正常.在这种情况下,我使用完全相同的命令,因为我通过sqlalchemy执行.
有什么不能正确冲洗?sqlalchemy出于某种原因在尝试授予语句时是否会无声地失败?我怎样才能做到这一点?
不包括更多代码的道歉,代码库是适度复杂的.我已经使用日志确认了事件的顺序...如果您需要更多代码以便了解我的问题,请告诉我.
一些日志
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
Run Code Online (Sandbox Code Playgroud)
第一堆东西发生了oSuperEngine,第二堆用bob的引擎.错误看起来像:
ProgrammingError: (ProgrammingError) permission denied for relation MY_TABLE
'insert into "MY_TABLE" (stuff) values (stuff);' {}
Run Code Online (Sandbox Code Playgroud)
小智 7
我有同样的问题.通过这样做固定:
sSQL = "GRANT ALL PRIVILEGES ON TABLE \"NICE_TABLE\" to bob;"
with oSuperEngine.begin() as conn:
conn.execute(sSQL)
Run Code Online (Sandbox Code Playgroud)
如果执行上面的脚本,您会遇到事务隔离问题。其实我前段时间也遇到过类似的问题。这里要记住的是,Bob 的事务不会看到超级引擎所做的更改,因为事务仍在进行,并且隔离不允许未提交的读取。Postgres 有大量关于此的文档,但本质是:在 postgres 中不可能进行未提交的读取。
显然,您的解决方案是首先从超级引擎提交更改,然后在其他事务中使用它。如果还没有尝试过,但我的猜测是,您必须保持默认的读取已提交隔离级别(因为较高的隔离级别不允许检测自事务(在本例中为 Bob)启动以来的更改)。
因此,在执行 Bobs 查询之前:
oSuperEngine.execute("COMMIT")
Run Code Online (Sandbox Code Playgroud)
然而,这引发了一个附带问题,它有效地破坏了事务给您带来的美好事物:您无法轻松回滚,因为更改已经提交。您在这里基本上想要的是与保存点相反的内容:
尽管保存点尚未存储对数据库的更改,但它确保回滚只会返回到特定点,而不是一直返回。您想要相反的情况:将其存储在数据库中,但能够回滚并再次从中删除它。我不知道有这样的事情,并且我非常怀疑它的存在,因为它违反了事务隔离的原则。
我对这个问题的解决方案是编写自定义回滚例程,我将在异常时调用该例程,以便我可以手动撤消更改。但这是一项相当大的工作,而且从长远来看维护成本很高。最后,就我而言,我重新考虑了我的解决方案并放弃了多引擎方法(但这是您必须自己做出的决定)。
| 归档时间: |
|
| 查看次数: |
3182 次 |
| 最近记录: |