这个 INSERT.. ON DUPLICATE 什么时候会失败?
When Would This INSERT.. ON DUPLICATE Fail?
由于约束错误,我正在对 INSERT... ON DUPLICATE KEY
语句进行故障排除,但我不可逆转地编辑了有问题的行,并且我不再收到错误。我很确定我编辑了 request_path
或 target_path
。某些区域已经存在的一些值:
store_id | id_path | is_system
6 | category/494 | 1
查询是
INSERT INTO `core_url_rewrite` (`store_id`,`category_id`,`product_id`,`id_path`,`request_path`,`target_path`,`is_system`)
VALUES (6, 494, NULL, 'category/494', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/494', 1)
ON DUPLICATE KEY UPDATE
`store_id` = VALUES(`store_id`),
`category_id` = VALUES(`category_id`),
`product_id` = VALUES(`product_id`),
`id_path` = VALUES(`id_path`),
`request_path` = VALUES(`request_path`),
`target_path` = VALUES(`target_path`),
`is_system` = VALUES(`is_system`)
错误是
Integrity constraint violation: 1062 Duplicate entry 'category/494-1-6'
for key 'UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID'
这个 table 上有两个唯一键。
UNIQUE KEY `UNQ_CORE_URL_REWRITE_REQUEST_PATH_STORE_ID` (`request_path`,`store_id`),
UNIQUE KEY `UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID` (`id_path`,`is_system`,`store_id`)
在手动意外更改行上的某些值后,我不再收到此约束错误。什么会导致我的查询提示约束错误?
如果修复第一个唯一性约束(通过更新冲突行而不是插入新行)导致第二个失败,则会发生这种情况。
例如,假设您的 table 已经有以下行:
(6, 494, NULL, 'category/123', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/123', 1),
(6, 494, NULL, 'category/494', 'lessons/foobar/whatever', 'catalog/category/view/id/494', 1);
然后尝试插入新行:
(6, 494, NULL, 'category/494', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/494', 1)
将导致第一个约束失败(因为 request_path = 'lessons/teacher-s-planning-calendar/n-a'
和 store_id = 6
的行已经存在于 table 中),因此 ON DUPLICATE KEY UPDATE
子句将导致而是更新冲突的行。但这将导致它违反 second 约束,因为在 table 中已经有 另一个 行 id_path = 'category/494'
, is_system = 1
和 store_id = 6
.
Here's a simple example on SQLize demonstrating this behavior.
事实上,what really happens是,如果ON DUPLICATE KEY UPDATE
的INSERT
语句违反了多个唯一性约束,MySQL将尝试将更新应用到所有 冲突的行。对于这样的更新,将所有列设置为固定值,这几乎 保证 会导致进一步的约束违规,因为它实际上是在尝试在 [=48= 中创建两个不同的行] 相同。
如链接文档所述:
In general, you should try to avoid using an ON DUPLICATE KEY UPDATE
clause on tables with multiple unique indexes.
问:什么会导致我的查询提示约束错误?
INSERT
操作在第一个唯一键 (request_path,store_id)
上遇到重复键错误。该错误被 MySQL 捕获,然后 MySQL 执行了等同于
的操作
UPDATE core_url_rewrite
SET store_id = ?
, category_id = ?
, product_id = ?
, id_path = ?
, request_path = ?
, target_path = ?
, is_system = ?
WHERE ( request_path = ? AND store_id = ? )
OR ( id_path = ? AND id_system = ? AND store_id = ?)
LIMIT 1
更新操作试图将 id_path
和 id_system
列(在该行)设置为值 'category/494'
和 '1'
。
"duplicate key" 错误是从 UPDATE
操作返回的。该语句仅捕获由 INSERT
操作引起的重复键错误。
这部分错误信息:
'category/494-1-6'
表示构成 table 中已存在的唯一键的列中的值。
在错误消息中,破折号用作每列值之间的分隔符。通常,我们无法区分作为分隔符的破折号和作为值一部分的破折号;所以我们需要小心解析它。
在本例中,索引中有两个破折号和三列,因此我们可以找出分配给每一列的值。
如果 INSERT
抛出了 "duplicate key" 错误,我们就不会看到它。 MySQL 会捕捉到它,并调用 UPDATE
动作。导致错误的是 UPDATE
操作。
可能你刚刚解决了你的问题,但我在这里把提示留给像我一样从 google 来到这里的其他人。
当url_rewrite_id达到max unsigned int size 4,294,967,295
时也会产生这个错误
最快的解决方案就是 t运行cate this table,如果您不使用自定义重写,则再次重新编制索引。
$adapter->insertOnDuplicate($this->getMainTable(), $rewriteData);
似乎每次索引器为 运行.
时,INSERT ... ON DUPLICATE UPDATE(由 Magento 核心索引器使用)都会增加此索引
请注意,A.Maksymiuk 建议达到最大无符号整数大小也是一个原因。
在我们的例子中,我们在我们的 ERP 集成中手动插入和删除了很多行,因此 MySql AUTO_INCREMENT 字段的增加速度比实际记录快得多。
错误报告 'Duplicate Entry' 与此 MySql 错误有关:
https://bugs.mysql.com/bug.php?id=80373
https://bugs.mysql.com/bug.php?id=66566
在我们的例子中,我们将列的类型 url_rewrite_id 更改为 BIGINT
由于约束错误,我正在对 INSERT... ON DUPLICATE KEY
语句进行故障排除,但我不可逆转地编辑了有问题的行,并且我不再收到错误。我很确定我编辑了 request_path
或 target_path
。某些区域已经存在的一些值:
store_id | id_path | is_system
6 | category/494 | 1
查询是
INSERT INTO `core_url_rewrite` (`store_id`,`category_id`,`product_id`,`id_path`,`request_path`,`target_path`,`is_system`)
VALUES (6, 494, NULL, 'category/494', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/494', 1)
ON DUPLICATE KEY UPDATE
`store_id` = VALUES(`store_id`),
`category_id` = VALUES(`category_id`),
`product_id` = VALUES(`product_id`),
`id_path` = VALUES(`id_path`),
`request_path` = VALUES(`request_path`),
`target_path` = VALUES(`target_path`),
`is_system` = VALUES(`is_system`)
错误是
Integrity constraint violation: 1062 Duplicate entry 'category/494-1-6'
for key 'UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID'
这个 table 上有两个唯一键。
UNIQUE KEY `UNQ_CORE_URL_REWRITE_REQUEST_PATH_STORE_ID` (`request_path`,`store_id`),
UNIQUE KEY `UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID` (`id_path`,`is_system`,`store_id`)
在手动意外更改行上的某些值后,我不再收到此约束错误。什么会导致我的查询提示约束错误?
如果修复第一个唯一性约束(通过更新冲突行而不是插入新行)导致第二个失败,则会发生这种情况。
例如,假设您的 table 已经有以下行:
(6, 494, NULL, 'category/123', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/123', 1),
(6, 494, NULL, 'category/494', 'lessons/foobar/whatever', 'catalog/category/view/id/494', 1);
然后尝试插入新行:
(6, 494, NULL, 'category/494', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/494', 1)
将导致第一个约束失败(因为 request_path = 'lessons/teacher-s-planning-calendar/n-a'
和 store_id = 6
的行已经存在于 table 中),因此 ON DUPLICATE KEY UPDATE
子句将导致而是更新冲突的行。但这将导致它违反 second 约束,因为在 table 中已经有 另一个 行 id_path = 'category/494'
, is_system = 1
和 store_id = 6
.
Here's a simple example on SQLize demonstrating this behavior.
事实上,what really happens是,如果ON DUPLICATE KEY UPDATE
的INSERT
语句违反了多个唯一性约束,MySQL将尝试将更新应用到所有 冲突的行。对于这样的更新,将所有列设置为固定值,这几乎 保证 会导致进一步的约束违规,因为它实际上是在尝试在 [=48= 中创建两个不同的行] 相同。
如链接文档所述:
In general, you should try to avoid using an
ON DUPLICATE KEY UPDATE
clause on tables with multiple unique indexes.
问:什么会导致我的查询提示约束错误?
INSERT
操作在第一个唯一键 (request_path,store_id)
上遇到重复键错误。该错误被 MySQL 捕获,然后 MySQL 执行了等同于
UPDATE core_url_rewrite
SET store_id = ?
, category_id = ?
, product_id = ?
, id_path = ?
, request_path = ?
, target_path = ?
, is_system = ?
WHERE ( request_path = ? AND store_id = ? )
OR ( id_path = ? AND id_system = ? AND store_id = ?)
LIMIT 1
更新操作试图将 id_path
和 id_system
列(在该行)设置为值 'category/494'
和 '1'
。
"duplicate key" 错误是从 UPDATE
操作返回的。该语句仅捕获由 INSERT
操作引起的重复键错误。
这部分错误信息:
'category/494-1-6'
表示构成 table 中已存在的唯一键的列中的值。
在错误消息中,破折号用作每列值之间的分隔符。通常,我们无法区分作为分隔符的破折号和作为值一部分的破折号;所以我们需要小心解析它。
在本例中,索引中有两个破折号和三列,因此我们可以找出分配给每一列的值。
如果 INSERT
抛出了 "duplicate key" 错误,我们就不会看到它。 MySQL 会捕捉到它,并调用 UPDATE
动作。导致错误的是 UPDATE
操作。
可能你刚刚解决了你的问题,但我在这里把提示留给像我一样从 google 来到这里的其他人。
当url_rewrite_id达到max unsigned int size 4,294,967,295
时也会产生这个错误最快的解决方案就是 t运行cate this table,如果您不使用自定义重写,则再次重新编制索引。
$adapter->insertOnDuplicate($this->getMainTable(), $rewriteData);
似乎每次索引器为 运行.
时,INSERT ... ON DUPLICATE UPDATE(由 Magento 核心索引器使用)都会增加此索引请注意,A.Maksymiuk 建议达到最大无符号整数大小也是一个原因。
在我们的例子中,我们在我们的 ERP 集成中手动插入和删除了很多行,因此 MySql AUTO_INCREMENT 字段的增加速度比实际记录快得多。
错误报告 'Duplicate Entry' 与此 MySql 错误有关:
https://bugs.mysql.com/bug.php?id=80373
https://bugs.mysql.com/bug.php?id=66566
在我们的例子中,我们将列的类型 url_rewrite_id 更改为 BIGINT