Technologieaustausch

MySQL sql_safe_updates-Parameter

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

sql_safe_updates ist eine Systemvariable in MySQL, die steuert, ob der MySQL-Server Aktualisierungs- oder Löschvorgänge für UPDATE- oder DELETE-Anweisungen zulässt, die keine KEY- oder LIMIT-Klausel verwenden. Wenn diese Variable auf ON gesetzt ist, lehnt MySQL UPDATE- oder DELETE-Anweisungen ab, die sich auf eine große Anzahl von Zeilen in der Tabelle auswirken können, es sei denn, diese Anweisungen verwenden explizit den SCHLÜSSEL (z. B. einen Primärschlüssel oder einen eindeutigen Index) in der WHERE-Klausel oder dem LIMIT-Klausel, um die Anzahl der betroffenen Zeilen zu begrenzen.

Der Zweck besteht darin, den versehentlichen Verlust oder die Änderung großer Datenmengen durch nachlässige oder falsch geschriebene SQL-Anweisungen zu verhindern.

So legen Sie sql_safe_updates fest

Sie können sql_safe_updates auf verschiedene Arten festlegen:

Globale Ebene:

Sie können diese Variable dauerhaft festlegen, indem Sie die MySQL-Konfigurationsdatei ändern (z. B. my.cnf oder my.ini, je nach Betriebssystem und MySQL-Version). Bitte beachten Sie jedoch, dass die direkte Einstellung von sql_safe_updates in der Konfigurationsdatei möglicherweise nicht von allen MySQL-Versionen unterstützt wird oder möglicherweise anders konfiguriert werden muss (z. B. über ein Plug-in oder andere Systemvariablen).
Ein üblicherer Ansatz besteht darin, es zur Laufzeit mit der SET GLOBAL-Anweisung von MySQL festzulegen. Dies betrifft jedoch nur neue Verbindungen. Zum Beispiel:

SET GLOBAL sql_safe_updates = 1;
  • 1

Bitte beachten Sie jedoch, dass das direkte Setzen globaler Variablen möglicherweise Administratorrechte erfordert und diese Änderung keine Auswirkungen auf bestehende Sitzungen hat.

Sitzungsebene:

Sie können sql_safe_updates festlegen, indem Sie die folgende SQL-Anweisung in Ihrer MySQL-Sitzung ausführen:

SET SESSION sql_safe_updates = 1;

或者登录时加上--safe-updates 

mysql -uroot -p --safe-updates 
  • 1
  • 2
  • 3
  • 4
  • 5

Dies wirkt sich auf nachfolgende Aktionen in der aktuellen Sitzung aus, nicht jedoch auf andere Sitzungen oder globale Einstellungen.

Vorsichtsmaßnahmen

  • Wenn sql_safe_updates aktiviert ist und Sie versuchen, eine UPDATE- oder DELETE-Anweisung ohne KEY oder LIMIT auszuführen, lehnt MySQL den Vorgang ab und gibt einen Fehler zurück.
(root@localhost)[superdb]> show index from dept;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| dept  |          0 | PRIMARY  |            1 | deptno      | A         |           4 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.13 sec)

(root@localhost)[superdb]> update dept set loc='sz';
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • Nicht alle MySQL-Bereitstellungen aktivieren sql_safe_updates standardmäßig. Es wird normalerweise von einem Datenbankadministrator oder Entwickler basierend auf spezifischen Sicherheitsanforderungen konfiguriert.

  • In einigen Fällen müssen Sie sql_safe_updates möglicherweise vorübergehend deaktivieren, um bestimmte Massenaktualisierungs- oder Löschvorgänge durchzuführen. In diesem Fall können Sie sql_safe_updates = 0 auf Sitzungsebene festlegen. Achten Sie jedoch darauf, dass Ihre SQL-Anweisungen sicher sind und nicht versehentlich große Datenmengen beeinträchtigen.

Zusammenfassend ist sql_safe_updates eine nützliche Sicherheitsfunktion, die dazu beitragen kann, Datenverluste aufgrund von Unachtsamkeit oder Fehlern zu verhindern. Allerdings müssen Entwickler und Datenbankadministratoren ihren SQL-Anweisungen mehr Aufmerksamkeit schenken, um deren Sicherheit und Genauigkeit zu gewährleisten.

offizielle Erklärung

Wenn dieser Wert auf 1 gesetzt ist, bricht MySQL UPDATE- oder DELETE-Anweisungen ab, die keinen Schlüssel in der WHERE-Klausel oder einer LIMIT-Klausel verwenden. (Insbesondere müssen UPDATE-Anweisungen eine WHERE-Klausel haben, die einen Schlüssel oder eine LIMIT-Klausel oder beides verwendet. DELETE-Anweisungen müssen beides haben.) Dadurch können UPDATE- oder DELETE-Anweisungen abgefangen werden, bei denen Schlüssel nicht richtig verwendet werden und die wahrscheinlich eine große Anzahl von Zeilen ändern oder löschen würden. Der Standardwert ist 0.

Wenn sql_safe_updates auf 1 gesetzt ist.

  • Die Update-Anweisung muss eine der folgenden Bedingungen erfüllen, um erfolgreich ausgeführt zu werden:
    • Die Update-Anweisung verwendet where und die Where-Bedingung muss eine Indexspalte enthalten.
    • Die Update-Anweisung verwendet limit;
    • Die Update-Anweisung verwendet gleichzeitig where und limit. Zu diesem Zeitpunkt muss die where-Bedingung keine Indexspalte haben.
(root@localhost)[superdb]> update dept set loc='sz' limit 1;
Query OK, 1 row affected (0.10 sec)
Rows matched: 1  Changed: 1  Warnings: 0

(root@localhost)[superdb]> select * from dept;
+--------+------------+---------+
| deptno | dname      | loc     |
+--------+------------+---------+
|     10 | ACCOUNTING | sz      |
|     20 | RESEARCH   | DALLAS  |
|     30 | SALES      | CHICAGO |
|     40 | OPERATIONS | BOSTON  |
+--------+------------+---------+
4 rows in set (0.00 sec)

(root@localhost)[superdb]> update dept set loc='NEW YORK' limit 1;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

(root@localhost)[superdb]> update dept set loc='NEW YORK' where deptno=10;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

(root@localhost)[superdb]> select * from dept;
+--------+------------+----------+
| deptno | dname      | loc      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
4 rows in set (0.00 sec)

(root@localhost)[superdb]> update dept set loc='NEW YORK' where deptno=10 limit 2;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

(root@localhost)[superdb]> select * from dept;
+--------+------------+----------+
| deptno | dname      | loc      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
4 rows in set (0.00 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • Die Löschanweisung muss die folgenden Bedingungen erfüllen, um erfolgreich ausgeführt zu werden:
    • Die Löschanweisung verwendet auch Indexspalten in der Where-Bedingung.
    • Die Löschanweisung verwendet sowohl die Indexspalte als auch den Grenzwert in der Where-Bedingung.
    • Die Löschanweisung verwendet gleichzeitig „Where“ und „Limit“. Zu diesem Zeitpunkt muss die „Where“-Bedingung keine Indexspalte haben.
(root@localhost)[superdb]> insert into dept values(50,'sz','hk');
Query OK, 1 row affected (0.01 sec)

-- 同时使用 where 和 limit,此时 where 条件中可以有索引列
(root@localhost)[superdb]> delete from dept where deptno=50 limit 1;
Query OK, 1 row affected (0.00 sec)

(root@localhost)[superdb]> insert into dept values(50,'sz','hk');
Query OK, 1 row affected (0.00 sec)

-- 仅使用 where条件中是索引列
(root@localhost)[superdb]> delete from dept where deptno=50;
Query OK, 1 row affected (0.01 sec)

(root@localhost)[superdb]> insert into dept values(50,'sz','hk');
Query OK, 1 row affected (0.00 sec)

-- dname不是索引列,因此无法删除操作
(root@localhost)[superdb]> delete from dept where dname='sz';
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. 

-- 同时使用 where 和 limit,此时 where 条件中没有索引列
(root@localhost)[superdb]> delete from dept where dname='sz' limit 1;
Query OK, 1 row affected (0.05 sec)

(root@localhost)[superdb]> select * from dept;
+--------+------------+----------+
| deptno | dname      | loc      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
4 rows in set (0.00 sec)

(root@localhost)[superdb]> show index from dept;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| dept  |          0 | PRIMARY  |            1 | deptno      | A         |           4 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.13 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

Wenn die Where-Bedingung eine Indexspalte mit sich bringt, der Optimierer aber letztendlich die gesamte Tabelle scannt und anstelle des Index auswählt, können wir „force index([index_name])“ verwenden, um dem Optimierer mitzuteilen, welcher Index verwendet werden soll, um die Möglichkeit einer Sperrung der gesamten Tabelle zu vermeiden Tabelle. Versteckte Gefahren, die durch die Tabelle verursacht werden.