1

我有这种形式的插入查询:

on INSERT into abc values .... on DUPLICATE KEY UPDATE .... 

在我没有分区的原始表中,唯一键是打开的,(subject_id, object_id)但现在我正在分区ts,我被迫拥有唯一键,(subject_id, object_id, ts)因为 mysql 要求在所有唯一键中都有分区键。

这意味着我的插入查询将失败,因为插入具有相同的 subject_id 和 object_id(来自以前的插入),但不同的时间戳将被视为唯一的新行,并将被插入而不是所需的更新。

有什么解决方法吗?

CREATE TABLE `abc` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `subject_id` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
  `object_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL,
  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`,`ts`),
  UNIQUE KEY `userint_sub_type_obj` (`subject_id`,`object_id`, `ts`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
/*!50100 PARTITION BY RANGE (unix_timestamp(ts))
(PARTITION p2012_08_27 VALUES LESS THAN (1346025600) ENGINE = InnoDB,
 PARTITION p2012_08_28 VALUES LESS THAN (1346112000) ENGINE = InnoDB,
 PARTITION p2012_08_29 VALUES LESS THAN (1346198400) ENGINE = InnoDB,
 PARTITION p2012_08_30 VALUES LESS THAN (1346284800) ENGINE = InnoDB,
 PARTITION p2012_08_31 VALUES LESS THAN (1346371200) ENGINE = InnoDB) */
4

1 回答 1

3

简而言之,如果不使分区键成为所有唯一(因此也是主)键的一部分,我就无法添加分区。

http://dev.mysql.com/doc/refman/5.5/en/partitioning-limitations-partitioning-keys-unique-keys.html

上周我实际上遇到了同样的问题,试图在启用/禁用列上删除一个分区。想到了两个解决方案。

  1. 您可以将时间戳移动到 meta_info 表中并对其进行分区。然后,您的具有时间条件的查找可以利用分区而不会弄乱您的 (subject_id, object_id) 键。开销当然是你需要加入。如果您的桌子很大,这可能不可行。
  2. 在更新之前进行检查。不是使用 ON DUPLICATE KEY 选项,而是将操作拆分为 SELECT 以查看记录是否存在,然后根据答案执行 INSERT 或 UPDATE。

不用说,我发现这种分区限制是一个巨大的痛苦,但它似乎是 MySQL 的一个限制,经过一些谷歌 Fu 和四处询问,似乎有简单的方法解决它。

于 2012-09-20T21:26:38.870 回答