【发布时间】:2018-11-20 10:01:59
【问题描述】:
结合两个语句(INSERT 或(BACKUP 和 UPDATE))并在 golang 中以原子方式执行它们的最佳方法是什么?
但那里的解决方案不满足以下要求中的 2 个:
- 对 DUPLICATE KEY 上的值执行备份,
- 使用标准 SQL
- 不使用存储过程,但
- 保持原子性。
【问题讨论】:
结合两个语句(INSERT 或(BACKUP 和 UPDATE))并在 golang 中以原子方式执行它们的最佳方法是什么?
但那里的解决方案不满足以下要求中的 2 个:
【问题讨论】:
这更像是一个 SQL 问题/答案,而不是 Go 特定的,因此可能的解决方案是基于 SQL 的。
可能的解决方案:
(1) 替换成
REPLACE INTO books
(id, title, author, year_published)
VALUES
(1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
这将覆盖现有记录。适用于唯一约束。虽然当找到匹配的记录时,它将被删除,因此它可能是不想要的行为。
(2) 插入忽略
INSERT IGNORE INTO books
(id, title, author, year_published)
VALUES
(1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
如果记录不存在,这将添加。适用于唯一约束。
来自手册:
如果您使用 IGNORE 修饰符,则在执行 INSERT 语句被忽略。例如,如果没有 IGNORE,那么一行 复制表中现有的 UNIQUE 索引或 PRIMARY KEY 值 导致重复键错误并且语句被中止。和 IGNORE,该行被丢弃并且不发生错误。忽略的错误可能 而是生成警告,尽管重复键错误不会。
(3) 插入 ... 在重复密钥更新时
INSERT INTO books
(id, title, author, year_published)
VALUES
(1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
ON DUPLICATE KEY UPDATE
title = 'No Green Eggs and Ham';
如果插入失败,来自ON DUPLICATE KEY 的值将用于生成更新语句。
要进行备份,请创建一个历史表(具有相同结构但修改了列以获取更改日期的表)并执行INSERT ... SELECT。要成为原子,您可能需要使用具有正确锁定策略的事务 - 不确定如何为 MySQL 正确设置。
参考:
【讨论】: