mysql中的确定性函数

a1e*_*x07 29 mysql deterministic user-defined-functions

我对一个看似简单的概念感到困惑.Mysql将确定性函数定义为函数

始终为相同的输入参数生成相同的结果

所以在我的理解中,功能就像

CREATE FUNCTION foo (val INT) READS SQL DATA
BEGIN
   DECLARE retval INT;
   SET retval = (SELECT COUNT(*) FROM table_1 WHERE field_1 = val);
   RETURN retval;
END;
Run Code Online (Sandbox Code Playgroud)

不确定(不保证在2次调用函数之间不会发生删除/更新/插入).同时,我看到许多函数几乎完全相同,即基于查询结果的返回值,并声明为DETERMINISTIC.看起来我错过了一些非常基本的东西.

任何人都可以澄清这个问题吗?

谢谢.

更新 感谢那些回答(+1); 到目前为止,似乎存在广泛滥用DETERMINISTIC关键字的问题.我很难相信有这么多人这样做,所以我会等待其他答案.

Xin*_*nt0 15

从MySQL 5.0参考:

对例程性质的评估基于创建者的"诚实":MySQL不会检查声明为DETERMINISTIC的例程是否没有产生非确定性结果的语句.但是,错误地说明例程可能会影响结果或影响性能.将非确定性例程声明为DETERMINISTIC可能会导致优化程序选择错误的执行计划,从而导致意外结果.将确定性例程声明为NONDETERMINISTIC可能会导致不使用可用的优化,从而降低性能.在MySQL 5.0.44之前,DETERMINISTIC特性被接受,但优化器不使用.

所以你有它,你可以标记存储的例程,DETERMINISTIC即使它不是,但它可能会导致意外的结果或性能问题.

  • 所以我们可能总有50%的机会选错了?大.大声笑你的评论让我更了解它. (3认同)

小智 12

DETERMINISTIC结果不是指在不同时间返回的不同结果集(取决于平均时间内添加的数据).此外,它是对使用相同数据的不同机器上的结果集的引用.例如,如果您有两台运行包含uuid()或引用服务器变量的函数的计算机,那么这些计算机应被视为NOT DETERMINISTIC.这在复制中很有用,因为函数调用存储在二进制日志(主服务器)中,然后也由从服务器执行.有关详细信息和示例,请参阅http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html

因此,DETERMINISTIC的使用(99%的时间)是正确的,不被认为是误用.


bik*_*868 8

我认为你的日常工作是确定性的.文档不是很清楚,这导致很多人对这个问题非常困惑,实际上更多的是关于复制而不是其他任何问题.

考虑在两个数据库之间设置复制的情况.master数据库记录所有已执行的存储例程(包括其输入参数),并将此日志发送给从站.从站以相同的顺序使用相同的输入参数执行相同的存储例程.slave数据库现在是否包含与master数据库相同的数据?如果存储的例程创建GUID并将它们存储在数据库中,则不会,主数据库和从属数据库将不同,复制将被破坏.

DETERMINISTIC标志的主要目的是告诉MySQL在复制日志中包含对此存储例程的调用是否会导致主数据库与复制的从属服务器之间存在差异,因此不安全.

在判断DETERMINISTIC标志是否适合存储的例程时,请考虑这样:如果我从两个相同的数据库开始,并且在具有相同输入参数的两个数据库上执行我的例程,我的数据库是否仍然相同?如果他们是,那么我的例程是确定性的.

如果你声明你的例程是确定性的,那么你的主数据库的副本可能与原始数据库的副本不同,因为MySQL只会将过程调用添加到复制日志,并且在slave上执行过程不会产生相同的结果.

如果您的例程是非确定性的,则MySQL必须在复制日志中包含受影响的行.如果您将例程声明为非确定性,则不会破坏任何内容,但复制日志将包含所有受影响的行,只需过程调用就足够了,这可能会影响性能.