MySQL本身提供一个叫rand的函数,返回的v范围为0 <= v < 1.0。
介绍此函数的MySQL文档也介绍道,可以通过此计算公式FLOOR(i + RAND() * (j – i)),获取i <= v < j的随机数字v。
CREATE FUNCTION rand_num ( start_num INTEGER,end_num INTEGER) RETURNS INTEGERDETERMINISTICBEGINRETURN FLOOR(start_num + RAND() * (end_num - start_num + 1));END;
比如,要获取1-9的随机数,如此调用即可:
select rand_num(1, 9);
因为CREATE PROCEDURE, CREATE FUNCTION, ALTER PROCEDURE,ALTER FUNCTION,CALL, DROP PROCEDURE, DROP FUNCTION等语句都会被写进二进制日志, 然后在从服务器上执行。
但是,一个执行更新的不确定子程序(存储过程、函数、触发器)是不可重复的,
在从服务器上执行(相对与主服务器是重复执行)可能会造成恢复的数据与原始数据不同,从服务器不同于主服务器的情况。
为了解决这个问题,MySQL强制要求:
在主服务器上,除非子程序被声明为确定性的或者不更改数据,否则创建或者替换子程序将被拒绝。
这意味着当创建一个子程序的时候,必须要么声明它是确定性的,要么它不改变数据。
声明方式有两种,
第一种: 声明是否是确定性的
DETERMINISTIC和NOT DETERMINISTIC指出一个子程序是否对给定的输入总是产生同样的结果。
如果没有给定任一特征,默认是NOT DETERMINISTIC,所以必须明确指定DETERMINISTIC来声明一个子程序是确定性的。
这里要说明的是:使用NOW() 函数(或它的同义)或者RAND() 函数不会使一个子程序变成非确定性的。
对NOW()而言,二进制日志包括时间戳并会被正确的执行。RAND()只要在一个子程序内被调用一次也可以被正确的复制。
所以,www.linuxidc.com可以认为时间戳和随机数种子是子程序的确定性输入,它们在主服务器和从服务器上是一样的。
