MySQL-为什么安全更新模式会阻止此UPDATE命令?

时间:2019-06-02 17:54:01

标签: mysql locking

我有一个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的情况下更新表。要禁用安全模式,请在“首选项”->“ SQL编辑器”中切换选项,然后重新连接。

独立列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错误。

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

1 个答案:

答案 0 :(得分:2)

您可以通过将该列设置为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

错误的要点是,当您对非索引列有条件时,防止您无意中锁定表中的每一行。

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