参考表中的值重复

时间:2014-03-27 20:11:38

标签: mysql stored-procedures transactions innodb database-normalization

我们的应用程序调用存储过程将其数据规范化为引用表,之后它将一条记录插入到主表中,该记录部分包含值并部分包含映射到引用表的ID。这是存储过程之一:

CREATE PROCEDURE `sp_name`(IN valueIn varchar(100), OUT valueOut int)
BEGIN
declare maxid int;
declare countid int;
select max(id) into valueOut from tableName where fieldName=valueIn;
IF valueOut is NULL
THEN
  start transaction with consistent snapshot;
  select count(*) into countid from tableName where fieldName=valueIn;
  IF countid=0
  THEN
    insert into tableName (fieldName) values (valueIn);
    select  last_insert_id() into valueOut;
  ELSE
    select max(id) into valueOut from tableName where fieldName=ValueIn;
  end IF;
commit;
end IF;
END

手动调用时,这可以正常工作,但在生产中调用时,我们最终会在参考表中出现多个重复值。

事务隔离级别为REPEATABLE_READ。

参考表:

CREATE TABLE `tableName` (
  `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `fieldName` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8

在字段fieldName上使用唯一键约束不是一个不错的选择。我们尝试了这个,但是后来我们发现自动增量没有获取重复值,而是跳过了ID。我们正在尝试保留ID,以便在数据类型方面不需要过度分配。我们的主表是巨大的(数十亿),因此我们必须有效地使用数据类型。

有谁了解这种现象?

1 个答案:

答案 0 :(得分:1)

如果你想为auto_increment构建自己的替代品,你必须清除很多障碍。您将发现可串行化,并发性,性能(通常与锁定相关)等问题。

我认为最简单的解决方案可能是在bigint unsigned类型的列上使用auto_increment。无符号整数的最大值是4,294,967,295:大约4x10 ^ 9。 unsigned bigint的最大值为18,446,744,073,709,551,615:大约1.8x10 ^ 19。

auto_increment仍会跳过id号码,但这是设计的,并且它不应该导致1.8x10 ^ 19范围内的麻烦。

在您开始使用此路径之前,请使用您的客户端软件测试大数字。有些人仍然没有与bigint妥协,无论是否签名。