2011-04-19 58 views
6

今天我遇到了我见过的MySQL中最奇怪的事情之一。 我有一个简单的表:mysql auto_increment列按随机值递增

CREATE TABLE `features` 
(
    `feature_id` mediumint(6) unsigned NOT NULL AUTO_INCREMENT, 
    `feature_name` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL, 
    PRIMARY KEY (`feature_id`), 
    UNIQUE KEY `feature_name_key` (`feature_name`) 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; 

我里面与Java和MySQL连接器的Java-5.1.15库插入数据。 feature_name中的数据可能会重复,我只想要唯一的值。我可以使用INSERT忽略,但如果数据太长我可能会忽略它,所以我用这个:

pstmt = conn.prepareStatement( 
     "INSERT INTO features (feature_name) VALUES (?)"); 

for (String featureName: data4db.keySet()) 
{ 
    pstmt.setString(1, featureName); 

    try 
    { 
     pstmt.executeUpdate(); 
    } 
    catch (SQLException se) 
    { 
     if (se.getErrorCode() == 1062) // duplicate entry 
     { 
      continue; // ignore 
     } 

     throw se; // do not ignore anything else 
    } 
} 

数据已经被插入到数据库后,我发现有一些问题,我还没有甚至有望。上表中大概有4000条记录可以。唯一的问题是由于重复主键导致一些数据无法插入,所以我查看了这个表的auto inc值的外观。事实证明,对于大多数数据,下一个相邻行的id按预期递增1。由于原因,我不知道有时feature_id增加了3,5,1000,100000 - 完全随机的值。因此,我'在这个表中不合适的位置',因为一旦id达到中等int的最大值,它就不能被插入。

这是怎么发生的? 有没有人遇到过类似的东西? 值得一提的是,只有一个程序只有一个线程写入此表。 我'有更多的表几乎相同 - 列的宽度和名称是不同的。对于这一个也有类似的问题。

顺便说一句 - 一些数据:

​​

谢谢你的任何提示提前。

回答

10

这是正常的MySQL行为。发生的情况如下:将数据插入到auto_increment key 3中,然后重复键,因为您的feature_name_key被定义为唯一的。 问题是,MySQL将“浪费”整数4,并将继续到下一个,它将不会重用因键约束而写入失败的整数。

如果你有这样的事情:

PK | feature_name_key 
1 | key1 
2 | key2 
3 | key3 
4 | key1 (fails due to constraint, 4 is not going to be used for next successful insertion, hence the gaps in your primary key) 

那么你失去的可用主键/ AUTO_INCREMENT整数。在插入或构建表来保存数据时重新思考您的策略。

+0

你是对的。感谢同学们的快速和非常有用的教训。我已经仔细检查过它。因此,基本上数字是两个相邻行中的ID之间的差异,表示在这两行之间存在多少次重复插入尝试。 – Artur 2011-04-19 09:19:41

+0

当重复发现被禁用时会自动增加吗?有解决方法吗?我只想拥有一个带有id和一些唯一字符串的表,并且没有id空位,但不想使用insert ignore(它与autoinc有相同的问题),也不会在插入之前读取整个表以检查哪些值已经存在那里?程序? – Artur 2011-04-19 09:28:38

+0

有很多解决方法,但问题是 - 为什么你需要顺序ID?你在这里使用代理键时,从理论的角度来看,自然键将是更好的选择。您可以将您的feature_name_key作为主键(因此可以立即执行唯一约束),并且您可以创建一个触发器来更新名为sequence_id的列,然后可以按顺序指定整数,而无间隙地分配给您的功能名称。 – 2011-04-19 09:41:57

0

在你的插入之间,你有删除行吗? MySQL可能只是记住自动增量计数器。

+0

没有插入只 - 我知道答案已经 - 谢谢 – Artur 2011-04-19 09:23:57