I have insert query of this form:
on INSERT into abc values .... on DUPLICATE KEY UPDATE ....
In my original table without partitions, the unique key was on (subject_id, object_id) but now I am partitioning by ts and I am forced to have the unique key as (subject_id, object_id, ts) because of mysql requirement of having the partition key in all the unique keys.
This means my insert query will fail coz an insert with same subject_id and object_id (from some previous insert) but a different timestamp will be treated as a unique new row and will get inserted instead of the desired update.
Is there any workaround?
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) */
To put it shortly, there is no way that I know of to add a partition without making the partition key a part of all your unique (and therefore also primary) keys.
http://dev.mysql.com/doc/refman/5.5/en/partitioning-limitations-partitioning-keys-unique-keys.html
I actually had this same problem last week trying to drop a partition on an enabled/disabled column. There’s two solutions that came to mind.
Needless to say I’ve found this restriction of partitioning to be a huge pain in the rear, but it does appear to be a limitation in MySQL and after some Google Fu and asking around, it seems like there is simple way around it.