MySQL中键“PRIMARY”的条目重复

8

我有一个名为 tbl_jobs 的表,用于存储应用程序中运行的一些后台作业的元数据。其模式如下:

CREATE TABLE `tbl_jobs` (
  `type` varchar(30) NOT NULL DEFAULT '',
  `last_run_on` datetime NOT NULL,
  `records_updated` text,
  PRIMARY KEY (`type`,`last_run_on`),
  UNIQUE KEY `index2` (`type`,`last_run_on`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$

每次作业运行时,都会在表中记录“类型”(用于区分不同作业的唯一标识符)、“运行时间”和“更新的记录数”。同时有两个不同的作业在相同时间运行,其类型为:MAILER_UNLOCKED_REWARDS 和 MAILER_ALMOST_UNLOCKED。当这些作业尝试插入具有相同时间戳的条目时,只有一个作业被插入,另一个则会抛出“关键字重复”的错误。例如,这两个作业运行了以下内容:
INSERT INTO tbl_jobs
            (type,
             last_run_on,
             records_updated)
VALUES     ('MAILER_ALMOST_UNLOCKED',
            '2012-08-22 19:10:00',
            'f8a35230fb214989ac75bf11c085aa28:b591426df4f340ecbce5a63c2a5a0174')

第一个作业成功运行,但是当第二个作业运行时出现了插入命令的问题。

INSERT INTO tbl_jobs
            (type,
             last_run_on,
             records_updated)
VALUES     ('MAILER_UNLOCKED_REWARDS',
            '2012-08-22 19:10:00',
            '8a003e8934c07f040134c30959c40009:59bcc21b33a0466e8e5dc50443beb945')

它抛出了错误

Duplicate entry 'M-2012-08-22 19:10:00' for key 'PRIMARY'

主键是由typelast_run_on列的组合。

如果我删除第一个任务的条目,则插入成功,即只要求timestamp唯一。

但是,相同timestamp的冲突仅在这两个任务之间发生。有其他作业插入相同的timestamp

对于可能存在的问题有什么想法吗?


1
你能展示一下 show create table tbl_jobs 吗? - jcho360
只是一条评论,我建议使用代理键。你可能会在每秒钟出现多个条目。 - Kermit
1
由于主键必须是唯一的,您应该从脚本中删除“UNIQUE KEY”行。 - sp00m
1
另外,如果您使用DEFAULT ''定义type列,则可能会遇到问题。如果您期望在该列中输入内容,则不应将其默认为空。 - Kermit
3个回答

5
你在索引中使用了整个“type”字段吗?还是只使用了第一个字符?因为MySQL抱怨的关键字是:
M-2012-08-22 19:10:00

替代 MAILER_...

尝试运行:

 SHOW INDEXES FROM tbl_jobs;

它应该提供类似如下的结果:
+----------+------------+----------+--------------+-------------+-----------+-------------+    ----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tbl_jobs |          0 | PRIMARY  |            1 | type        | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| tbl_jobs |          0 | PRIMARY  |            2 | last_run_on | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |

我猜它会在 PRIMARY 索引的 Sub_part 列中显示 "1" :
+----------+------------+----------+--------------+-------------+-----------+-------------+    ----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tbl_jobs |          0 | PRIMARY  |            1 | type        | A         |           0 |        1 | NULL   |      | BTREE      |         |               |
| tbl_jobs |          0 | PRIMARY  |            2 | last_run_on | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |

顺便提一下,主键始终是唯一的,因此您在那里声明的第二个索引 index2 是多余的。


我正在使用整个类型键。无法理解 M- 在那里的作用。 - mickeymoon
@mickeymoon,主键报告的错误与结果不一致。我认为定义中有问题,使用SHOW INDEXES命令可以帮助解决(检查“sub_part”列)。 - LSerni
@Iserni:正如您所指出的那样,列“type”的“sub_part”实际上为1,但这对它有什么影响?如何解决? - mickeymoon

0
我曾经遇到过这种错误,通常是由于系统关机或网络问题引起的。实际上,数据库中并不存在重复项。这是一个MySQL数据库错误。你只需要做的是:如果你执行插入操作但结果为false,那么只需将你想要插入的表中的某一列从varchar更改为textbigint,然后重新执行插入操作即可解决该问题。
If(!$insert)
{    
$alter=Mysql_query("alter table     

`table_name` change `table_name` 

`table_name` bigint(255) not null");    

If($alter){

//you then redo your insertion.     

} 


}

0
第一件事:您必须确保您的PRIMARY KEY已设置为AUTO_INCREMENT。 第二件事:您只需通过以下方式启用自动增量: ALTER TABLE [表名] AUTO_INCREMENT = 1 第三件事:当您执行插入命令时,您必须跳过此键。

主键 - 在这种情况下 - 是字母数字混合的,因此无法应用AUTO_INCREMENT设置。 - fusion3k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接