Jak*_*sel 12 mysql postgresql oracle jdbc transaction
背景:我在http://sqlfiddle.com 上工作(我的网站)上工作,并试图防止那里可能出现的一种滥用途径。我希望通过询问我目前正在解决的问题,我不会无意中使潜在的虐待变得更糟,但是你能做什么?我相信你们。
我想阻止任何用户在给定的事务块内发出显式的“提交”调用。从 SQL Fiddle 的上下文来看,事务块是在右侧面板上执行的代码。基本上,我正在循环执行一个纯文本 SQL 命令列表,并且我想确保它们所做的所有更改都将在批处理结束时回滚。通常,他们的更改会回滚,但有时文本中会有明确的“提交”语句,因此我的回滚当然不起作用。这种显式提交很可能来自用户试图破坏 SQL Fiddle 上的架构,因此其他人会看到错误。
主要期望结果:如果可能,我想在 JDBC 级别禁用显式提交。这是因为我要支持多个数据库后端供应商,当然每个供应商在低级别都有自己的怪癖。
回退选项:如果无法将 JDBC 配置为禁用显式提交,那么我愿意接受在为以下每个后端处理批处理时检测显式提交的解决方案:SQL Server、Oracle、MySQL 和 PostgreSQL。
对于 SQL Server,我想到了这个解决方案:在我执行它之前解析语句的 XML 查询计划,并检查是否存在与此 XPath 匹配的条目:
//*[@StatementType="COMMIT TRANSACTION"]
Run Code Online (Sandbox Code Playgroud)
我认为这对 SQL Server 非常有效。但是,这种方法不适用于其他数据库类型。Oracle 用于显式提交的 XML 执行计划输出并未提及您正在运行提交语句这一事实(而是简单地重复它提交的查询的执行计划输出)。PostgreSQL 和 MySQL 根本不为显式提交提供任何执行计划输出(XML 或其他)。
这让我需要检查“提交”一词的实际语句。这会起作用,除非可能有各种变化:
declare @sql varchar(50)
set @sql = 'com' + 'mit'
exec(@sql);
Run Code Online (Sandbox Code Playgroud)
上面是 SQL Server 的一个例子(我可以解决),但我猜想类似的事情对于 Oracle、MySQL 和 PostgreSQL 也是可能的。我在这个假设上错了吗?也许他们不允许“动态”提交语句?随意使用 SQL Fiddle(最好不是示例模式或其他人可能正在使用的模式)来查看是否可以在 Oracle、MySQL 和 PostgreSQL 中进行类似的操作。如果没有,也许简单的字符串检测可能适用于那些。
还有一种可能
我想到了另一个选择 - 如果您知道一种将这些数据库中的任何一个设置为只读模式的方法,例如在该模式下无法提交任何内容,那也可以。我仍然需要允许启动事务并在其中运行代码,只要在该模式下不能提交任何内容。那可能吗?
更新
我最近学到的 - 这实际上不是 PostgreSQL 的问题。显然,如果同一块最终被回滚(在 Postgres 中),则在事务块内发出的提交将不适用。Postgres 万岁!
感谢 Phil 指向 SO 帖子的链接,我想我可以使用 DEFERRABLE INITIALLY DEFERRED hack for Oracle 来完成我所追求的事情(如果发出提交会抛出错误,但我可以解决这个问题)。这应该针对 Oracle。(我想了一会儿嵌套事务可能在这里工作,但它看起来不像 Oracle 支持嵌套事务?无论如何我找不到任何以这种方式工作的东西)。
还没有真正的 MySQL 解决方案。尝试使用嵌套事务,但这似乎不起作用。我正在认真考虑对 MySQL 采取更激进的方法,例如在右侧不允许除 SELECT 之外的任何内容,或者在每次查询后删除/重新创建数据库。不过都不好听。
解析度
所以,我现在已经为 SQL Server 和 Oracle 实施了所描述的解决方案,正如我所提到的,这实际上对 PostgreSQL 来说不是问题。对于 MySQL,我采取了一些不幸的步骤,将查询面板限制为仅选择语句。MySQL 的 DDL 和 DML 只需在模式面板(左侧)上输入即可。我希望这不会打破太多陈旧的问题,但我认为这只是确保数据一致性所必须做的。谢谢!
对于 Oracle 来说,这似乎是一种捕获 COMMIT 的好方法:
他没有提到的是,您也应该能够捕获代码中的约束违规,以阻止第二种情况的发生。