【问题标题】:MySQL - Why is Safe Update Mode blocking this UPDATE command?MySQL - 为什么安全更新模式会阻止此 UPDATE 命令?
【发布时间】:2019-10-18 10:20:35
【问题描述】:

我有一个 actor 表,如下所示:

| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
| 1        | Jack       | Nicholson | 2019-06-02 00:00:00 |

actor_id 列是自动递增的主键。

当我尝试像这样更新表格时:

UPDATE actor
SET last_name = 'foo'
WHERE last_update > '2019-06-02 00:00:00';

我被 MySQL 的安全更新模式阻止并出现此错误:

错误代码:1175。您正在使用安全更新模式,并且您尝试更新没有使用 KEY 列的 WHERE 的表。要禁用安全模式,请切换 Preferences -> SQL Editor 中的选项并重新连接。

确实last_update 列不是KEY 列,所以基于this SO answer 我想出了以下解决方法:

CREATE TEMPORARY TABLE IF NOT EXISTS ids AS (SELECT actor_id FROM actor WHERE last_update > '2019-06-02 00:00:00');

UPDATE actor
SET last_name = 'foo'
WHERE actor_id IN (SELECT actor_id FROM ids);

但我再次被 1175 错误阻止。

为什么安全更新模式在这里阻止了我?我可以在不禁用安全更新模式的情况下解决它吗?

【问题讨论】:

  • 如果您知道该声明是正确的做法,只需禁用安全模式?如果你想要它,你可以在之后重新启用它。
  • 谢谢。你这很务实,但不能完全回答我的问题:)
  • why 他们是否认为他们需要“保护”您免于执行错误(或缓慢)的 sql 语句?
  • @Luuk,因为初学者犯这种错误很常见,从错误中恢复可能需要很多工作。
  • 我还要评论说,真正的专家并不讨厌这种事情,因为他们知道这有助于避免错误。 “专家是知道在他的学科中可能犯的一些最严重的错误以及如何避免这些错误的人。” ——维尔纳·海森堡

标签: mysql locking


【解决方案1】:

您可以通过将该列设置为 KEY 列来解决此错误。换句话说,在列上创建一个索引(又名键)。

mysql> set sql_safe_updates=ON;

mysql> UPDATE actor SET last_name = 'foo' WHERE last_update > '2019-06-02 00:00:00';
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column

mysql> alter table actor add key (last_update);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> UPDATE actor SET last_name = 'foo' WHERE last_update > '2019-06-02 00:00:00';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0

错误的重点是防止您在非索引列上有条件时无意锁定表中的每一行。

锁定的工作方式是锁定查询检查以测试条件的所有行,而不仅仅是满足条件的所有行。如果您使用测试未索引查询的条件运行查询,则它必须检查表中的每一行,这可能比您预期的要锁定更多。

【讨论】:

  • 膨胀解释,谢谢!虽然解决方法对于任务来说有点繁重,但您不会说吗? :)
  • 您可能会发现在该列上建立索引很有帮助。此外,您可以在会话中关闭sql_safe_updates,而无需更改选项的全局设置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多