MySQL存储例程中的动态SQL


Answers:


8

刚听到这个问题,我就会想到两个方面:

方面#1:功能应该是确定的

如果是这样,则意味着对于给定的参数集,函数应始终显示相同的返回数据,而在调用该函数时则无所谓。

现在,想象一个函数会由于在一天中的不同时间基于静态SQL收集数据而产生不同的答案。从某种意义上说,如果每次给定相同的参数集时查询同一组表和列,仍可以认为是确定的。

如果可以通过Dynamic SQL更改函数的基础表怎么办?您违反了DETERMINISTIC函数的定义。

请注意,MySQL在/etc/my.cnf中添加了此选项

log-bin-trust-function-creators

尽管这可能说得过于简单,但这允许函数在不严格执行DETERMINISTIC属性的情况下将数据写入二进制日志。

方面2:触发器应该能够回滚

  • 您能想象一个触发器具有与函数相同的所有行为,然后将Dynamic SQL引入到组合中吗?
  • 您是否可以想象在将MVCC应用于触发器所针对的基表之后,尝试对Dynamic SQL施加MVCC(多版本并发控制)

本质上,仅在MVCC中,您的数据就会呈平方(甚至指数)增长。至少可以说,使用可能是非DETERMINISTIC的触发器来管理SQL回滚的过程非常复杂。

鉴于这两个方面,我确信MySQL开发人员会想到这些事情,并通过施加限制迅速将其消除。

那么,为什么要取消对程序的限制?简而言之,您无需担心DETERMINISTIC属性或回滚。


3
如果其他DBMS可以很好地在触发器中支持MVCC和动态SQL,那么它就不会那么“复杂”。
a_horse_with_no_name 2012年

1
其实,@ a_horse_with_no_name,您是对的。对于Oracle和PostgreSQL,已经编写了复杂的代码。为您的评论+1。MySQL具有处理多个存储引擎的障碍,因此回滚和确定性可能需要存储引擎操作重叠。有点吓人。也许有人有胆量将“不合情理的复杂”完全推入InnoDB。甚至更期望的是以不允许在同一查询中混合存储引擎的方式创建特定于存储引擎的触发器实现。
RolandoMySQLDBA 2012年

5

这是一个很好的问题,但我不知道答案。我想这将必须交给内部团队,但我不知道他们会在这个网站中占重要地位。同时,我可以帮助您推断出一些答案。

首先,我看到以下内容:

触发器缓存不会检测基础对象的元数据何时更改。如果触发器使用表,并且自将触发器加载到缓存以来该表已更改,则触发器将使用过时的元数据进行操作。

这使我认为这与它有关。如果它甚至不监视元数据,也不会重新编译SQL。这意味着这是引擎问题。

出于同样的原因,当我阅读此代码块时,我会想到同一件事(引擎):

为防止服务器线程之间的交互问题,当客户端发出一条语句时,服务器使用可用于执行该语句的例程和触发器的快照。即,服务器计算在语句执行期间可能使用的过程,函数和触发器的列表,加载它们,然后继续执行该语句。这意味着在执行该语句时,将看不到其他线程执行的例程的更改。

所以总的来说,我不确定他们为什么不允许这样做,但是我可以猜到。抱歉,我不能为您提供更多帮助,我愿意继续提出更多建议。最好的是,一旦我们退出私人测试版,就希​​望有一些活跃的MySQL开发人员;)


1

在很大程度上,这是由于安全性。过程的例外是因为可以为过程内的动态SQL分配执行用户的安全上下文。这意味着,即使发动机不知道什么是要执行的,它可以使某些用户被允许访问引用的对象(S)。

除此之外,您还可以提出在可能的情况下可能发生的丑陋问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.