生成Code的函数返回相同的内容

时间:2016-09-09 09:02:01

标签: mysql duplicates

我们的网络系统中有一个MySQL函数来生成代码。代码的结构是

district_cd(length:2) + date(length:8) + sequence no(length:5,start at 1).<like : ab2016090800001>

序列号保存在表格中,并在生成新代码时更新(+1)。

但有时候它会返回两个相同的代码,让我们陷入困境。以下是复制此问题的捕获,我将在此之后附加DDL。

步骤1.Client1-&gt;更改为手动提交然后生成代码,但不提交。

SET autocommit = 0;
select * from applies;
select * from sequence where apply_date = "2016-09-08";
select nextval("ab");
insert into applies (apply_id,apply_no,created,district_cd) values (2,"ab2016090800002","ab",now());
select * from sequence where apply_date = "2016-09-08";

Step2.Client2-&gt;更改为手动提交然后生成代码,卡在Client1锁定

SET autocommit = 0;
select * from applies;
select * from sequence where apply_date = "2016-09-08";
insert into applies (apply_id,apply_no,created,district_cd) values (3,"ab20160908123456780","ab",now());

Step3.Client1-&GT;提交;

commit;
select * from sequence where apply_date = "2016-09-08";

生成了Step4.Client2-&gt;代码,并且在序列表中出现了两条记录

select * from sequence where apply_date = "2016-09-08";

capture of Step4

Step5.Client2-&gt; commit;删除了序列表中出现的两条记录之一。生成的代码是重复的。

commit;
select * from sequence where apply_date = "2016-09-08";
select * from applies;

capture of Step5

※DDL

表:适用(apply_no:保存代码)

CREATE TABLE `applies` (
  `apply_id` varchar(100) NOT NULL DEFAULT '',
  `apply_no` varchar(100) NOT NULL DEFAULT '',
  `district_cd` varchar(100) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  PRIMARY KEY (`apply_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表:序列(current_value:保存当前序列值)

CREATE TABLE `sequence` (
  `district_cd` varchar(3) NOT NULL DEFAULT '',
  `current_value` int(11) NOT NULL DEFAULT '0',
  `apply_date` date NOT NULL DEFAULT '0000-00-00',
  PRIMARY KEY (`district_cd`,`current_value`,`apply_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

功能:currval-&gt;通过district_cd获取当前序列值

DELIMITER ;;
CREATE DEFINER=`usr`@`%` FUNCTION `currval`(d VARCHAR(3)) RETURNS int(11)
    DETERMINISTIC
BEGIN
    DECLARE value INTEGER;
    DECLARE needInitSequence INTEGER;
    DECLARE today DATE;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET needInitSequence = 1;

    SET value = 0;
    SET today = current_date();

    SELECT `current_value` INTO value
        FROM `sequence`
        WHERE `district_cd` = d AND `apply_date` = today limit 1;

    IF needInitSequence = 1 THEN
        INSERT INTO `sequence` (`district_cd`, `current_value`, `apply_date`) VALUES (d, value, today);
    END IF;

    RETURN value;
END
;;
DELIMITER ;

功能:nextval-&gt;按区域生成代码

DELIMITER ;;
CREATE DEFINER=`usr`@`%` FUNCTION `nextval`(d VARCHAR(3)) RETURNS varchar(16) CHARSET utf8
    DETERMINISTIC
BEGIN
    DECLARE value INTEGER;
    SET value = currval(d);

    UPDATE `sequence`
        SET `current_value` = `current_value` + 1
        WHERE `district_cd` = d AND `apply_date` = current_date();

    RETURN concat(d, date_format(now(), '%Y%m%d'), LPAD(currval(d), 5, '0'));
END
;;
DELIMITER ;

应用的触发器 - &gt;业务逻辑,如果apply_no的长度大于18,则会调用函数:nextval生成新代码

DELIMITER ;;
CREATE TRIGGER `convert_long_no` BEFORE INSERT ON `applies` FOR EACH ROW BEGIN
    IF ((SELECT LENGTH(NEW.apply_no)) >= 18) THEN
        SET NEW.apply_no = (SELECT nextval(NEW.district_cd));
    END IF;
END
;;
DELIMITER ;

我的问题:

  1. 为什么函数:nextval返回两个相同的代码?

  2. 为什么在更新记录时会出现两条记录。

0 个答案:

没有答案