mysql中的确定性函数
我被一个看似简单的概念弄糊涂了。Mysql将确定性函数定义为 始终为相同的输入参数生成相同的结果 所以在我的理解中,函数mysql中的确定性函数,mysql,user-defined-functions,deterministic,Mysql,User Defined Functions,Deterministic,我被一个看似简单的概念弄糊涂了。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; 不确定(不能保证在两次调用函数之间不会发生删除
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;
不确定(不能保证在两次调用函数之间不会发生删除/更新/插入)。同时,我看到许多函数的功能基本相同,即基于查询结果返回值,并声明为确定性
。看起来我缺少了一些基本的东西
有人能澄清这个问题吗
谢谢
更新
感谢那些回答(+1)的人;到目前为止,
确定性
关键字似乎被广泛滥用。我仍然很难相信有这么多人这么做,所以我会等待其他答案 来自MySQL 5.0参考:
对例程性质的评估基于创建者的“诚实”:MySQL不会检查声明为确定性的例程是否没有产生不确定性结果的语句。但是,错误声明例程可能会影响结果或影响性能。将非确定性例程声明为确定性例程可能会导致优化器做出错误的执行计划选择,从而导致意外结果。将确定性例程声明为非确定性例程可能会导致不使用可用的优化,从而降低性能。在MySQL 5.0.44之前,优化器接受确定性特征,但不使用
因此,您可以将存储的例程标记为
确定性
,即使它不是确定性的,但它可能会导致意外的结果或性能问题。您不会遗漏任何内容。这个函数是不确定的。声明它不会导致数据库融化,但可能会影响性能:“将非确定性例程声明为确定性例程可能会导致优化器做出错误的执行计划选择,从而导致意外结果。”但是MySQL不会强制或检查您声明的确定性例程是否确实是确定性的——MySQL相信您知道自己在做什么。确定性结果并不指在不同时间返回的不同结果集(取决于同时添加的数据)。此外,它是使用相同数据的不同机器上的结果集的参考。例如,如果有两台机器运行一个包含uuid()或引用服务器变量的函数,那么这些机器应该被认为是不确定的。例如,这在复制中很有用,因为函数调用存储在二进制日志(主)中,然后也由从机执行。有关详细信息和示例,请参见
因此,确定性的使用(99%的时间)是正确的,不应被视为误用。如果您打开了复制,或者某一天可能会使用它,则确定性非常重要。例如,导致行更改(更新或插入)的非确定性函数调用需要使用二进制(基于行)进行复制,其中确定性函数可以基于语句进行复制。
当查看上面的SQL示例时,这会变得很有趣,哪些示例在使用基于语句的复制时会发生相同的情况(给出相同的结果),哪些示例应该使用在主控中获得的结果(基于行)进行复制。如果这些语句是使用适当的锁定执行的,并且可以保证在从机上以相同的顺序执行,那么它们确实是确定性的。如果从机使用的锁定/语句顺序(无并发,按照语句启动的顺序对语句进行串行处理)意味着答案可能不同,那么函数应该是非确定性的。我认为您的例程是确定性的。文档不是很清楚,这导致许多人对这个问题感到非常困惑,实际上,这个问题更多的是关于复制 考虑在两个数据库之间设置复制的情况。主数据库保存所有已执行的存储例程的日志,包括它们的输入参数,并将此日志发送给从数据库。从机使用相同的输入参数以相同的顺序执行相同的存储例程。从属数据库现在是否包含与主数据库相同的数据?如果存储的例程创建guid并将其存储在数据库中,则否,主数据库和从数据库将不同,复制将中断 DETERMINISTIC标志的主要目的是告诉MySQL,在复制日志中包含对该存储例程的调用是否会导致主数据库和复制从属数据库之间的差异,因此是不安全的 当决定确定性标志是否适用于存储的例程时,可以这样想:如果我从两个相同的数据库开始,并使用相同的输入参数在两个数据库上执行例程,那么我的数据库是否仍然相同?如果它们是确定的,那么我的程序就是确定的 如果声明例程是确定性的,而不是确定性的,那么主数据库的副本可能与原始数据库不同,因为MySQL只会将过程调用添加到复制日志中,并且在从属数据库上执行过程不会产生相同的结果
如果您的例程是不确定的,那么MySQL必须在复制日志中包含受影响的行。如果在不确定的情况下将例程声明为非确定性,则不会中断任何内容,但复制日志将包含所有受影响的行,而仅过程调用就足够了,这可能会影响性能。您能否说明一个您正在谈论的“多功能”示例?@Mat:例如,(在用户评论部分,搜索“创建函数db.fnful