Mysql:如果行不安全地存在且具有键和唯一属性,则插入

Mysql: Insert if row doesnt exist safely with key and unique attribute

背景:

我在 python 中构建了一个抓取工具(不确定这是否重要)。我抓取网站并更新我的 html table。主要table存放autogenerated_id、url、raw_html、date_it_was_scrapped、last_date_the_page_was_updated(网站提供)。我的 table 有许多不应该重复的 url,因此我计划使 url 在数据库中唯一。

期望的结果:

我只想在 url 不存在时插入一行,并在 last_date_the_page_was_updated > date_it_was_scrapped 时更新 html。

解决方案:

以下 Whosebug post 显示如何。
我还没有测试它,因为选择的答案警告: INSERT ... ON DUPLICATE KEY UPDATE statement against a table having more than one unique or primary key is also marked as unsafe.

根据Whosebug的问题我打算做什么。

INSERT INTO html_table (url, raw_html, date_it_was_scrapped, last_date_the_page_was_updated)
VALUES (the data)
ON DUPLICATE KEY UPDATE
    url = VALUES(url), 
    raw_html = VALUES(raw_html),
    date_it_was_scrapped = VALUES(date_it_was_scrapped),
    last_date_the_page_was_updated=VALUES(last_date_the_page_was_updated)
WHERE last_date_page_was_update > date_it_was_scrapped

问题:

它有什么不安全的地方,有什么安全的方法吗?

来自 description of bug 58637,链接在 MySQL 文档页面中,将 INSERT ... ON DUPLICATE KEY UPDATE 标记为不安全:

When the table has more than one unique or primary key, this statement is sensitive to the order in which the storage engines checks the keys. Depending on this order, the storage engine may determine different rows to mysql, and hence mysql can update different rows [...] The order that the storage engine checks keys is not deterministic.

我了解到您的 table 有一个自动递增的主键,并且您打算在 url 列上添加一个唯一键。因为主键是自动递增的,所以您不会将其作为 INSERT 命令的参数传递,如 SQL 命令所示。因此 MySQL 不需要检查此列的重复项;它只会检查 url 上的重复项。因此,这个 INSERT 应该是安全的。

关于您的问题的其他说明。

  • 您不需要更新重复键上的 url 命令(我们知道它是一样的)

  • 您查询中 WHERE 子句的用途不明确,您确定需要它吗?

  • 在 URL 上启用唯一约束之前,您需要删除重复项。