对重复密钥的原子更新和备份insert else-golang sql语句

cygmwpex  于 2021-06-19  发布在  Mysql
关注(0)|答案(1)|浏览(300)

组合两个语句(insert或(backup and update))并在golang中以原子方式执行它们的最佳方法是什么?
我发现了一个类似的问题:https://codereview.stackexchange.com/questions/186909/query-select-and-insert-if-not-exists?newreg=067063956a834327883542c3171a22d4
但解决方案不满足以下两个要求:
对重复键执行值备份,
使用标准sql
不使用存储过程,但
保持原子状态。

y4ekin9u

y4ekin9u1#

这更多的是一个sql问题/答案,而不是具体的问题/答案,因此可能的解决方案是基于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时,将丢弃该行,并且不会发生错误。忽略的错误可能会生成警告,尽管重复的键错误不会。
(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 将用于生成update语句。
要进行备份,请创建一个历史记录表(一个具有相同结构但使用列进行了修改以获取更改日期的表)并执行以下操作: INSERT ... SELECT . 要实现原子化,您可能需要使用具有正确锁定策略的事务—不确定如何为mysql正确地实现这一点。
参考文献:
https://chartio.com/resources/tutorials/how-to-insert-if-row-does-not-exist-upsert-in-mysql/ 样品
https://dev.mysql.com/doc/refman/5.5/en/insert.html
https://dev.mysql.com/doc/refman/5.5/en/replace.html
https://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html

相关问题