Teknologian jakaminen

MySQL sql_safe_updates -parametri

2024-07-12

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

sql_safe_updates on MySQL:n järjestelmämuuttuja, joka määrää, salliiko MySQL-palvelin päivittää tai poistaa UPDATE- tai DELETE-käskyjä, jotka eivät käytä KEY- tai LIMIT-lausetta. Kun tämä muuttuja on ON, MySQL hylkää UPDATE- tai DELETE-käskyt, jotka voivat vaikuttaa suureen määrään taulukon rivejä, elleivät nämä käskyt nimenomaisesti käytä KEY:tä (kuten ensisijaista avainta tai yksilöllistä indeksiä) WHERE-lauseessa tai LIMIT-lauseke rajoittaa vaikuttavien rivien määrää.

Tämän tarkoituksena on estää suurten tietomäärien tahaton menetys tai muuttaminen huolimattomien tai väärin kirjoitettujen SQL-käskyjen vuoksi.

Kuinka asettaa sql_safe_updates

Voit asettaa sql_safe_updates useilla tavoilla:

Globaali taso:

Voit asettaa tämän muuttujan pysyvästi muokkaamalla MySQL-määritystiedostoa (kuten my.cnf tai my.ini käyttöjärjestelmästäsi ja MySQL-versiosta riippuen). Huomaa kuitenkin, että kaikki MySQL-versiot eivät välttämättä tue sql_safe_updates-asetusta suoraan määritystiedostossa tai se on ehkä määritettävä eri tavalla (esimerkiksi laajennuksen tai muiden järjestelmämuuttujien kautta).
Yleisempi tapa on asettaa se ajon aikana MySQL:n SET GLOBAL -käskyllä, mutta tämä vaikuttaa vain uusiin yhteyksiin. Esimerkiksi:

SET GLOBAL sql_safe_updates = 1;
  • 1

Huomaa kuitenkin, että globaalien muuttujien määrittäminen suoraan voi edellyttää järjestelmänvalvojan oikeuksia, eikä tämä muutos vaikuta olemassa oleviin istuntoihin.

Istuntotaso:

Voit asettaa sql_safe_updates suorittamalla seuraavan SQL-käskyn MySQL-istunnossasi:

SET SESSION sql_safe_updates = 1;

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

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

Tämä vaikuttaa myöhempiin toimintoihin nykyisessä istunnossa, mutta ei muihin istuntoihin tai yleisiin asetuksiin.

Varotoimenpiteet

  • Kun sql_safe_updates on käytössä, jos yrität suorittaa UPDATE- tai DELETE-käskyn ilman KEY- tai LIMIT-käskyä, MySQL hylkää toiminnon ja palauttaa virheen.
(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
  • Kaikki MySQL-asennukset eivät ota oletusarvoisesti käyttöön sql_safe_updates. Sen määrittää yleensä tietokannan ylläpitäjä tai kehittäjä tiettyjen suojausvaatimusten perusteella.

  • Joissakin tapauksissa saatat joutua poistamaan sql_safe_updates tilapäisesti käytöstä tiettyjen joukkopäivitys- tai poistotoimintojen suorittamiseksi. Tässä tapauksessa voit asettaa sql_safe_updates = 0 istuntotasolla, mutta varmista, että SQL-käskyt ovat turvallisia eivätkä vahingossa vaikuta suuriin tietomääriin.

Yhteenvetona voidaan todeta, että sql_safe_updates on hyödyllinen suojausominaisuus, joka voi auttaa estämään tahattomasta tai virheestä johtuvan tietojen katoamisen. Se edellyttää kuitenkin myös, että kehittäjät ja tietokannan ylläpitäjät kiinnittävät enemmän huomiota SQL-lauseisiinsa varmistaakseen niiden turvallisuuden ja tarkkuuden.

virallinen selitys

Jos arvo on 1, MySQL keskeyttää UPDATE- tai DELETE-käskyt, jotka eivät käytä avainta WHERE- tai LIMIT-lauseessa. (Erityisesti UPDATE-käskyissä on oltava WHERE-lause, joka käyttää avainta tai LIMIT-lausetta tai molempia. DELETE-käskyissä on oltava molemmat.) Tämä mahdollistaa UPDATE- tai DELETE-käskyjen saamisen, joissa avaimia ei käytetä oikein ja jotka todennäköisesti muuttuisivat. tai poista suuri määrä rivejä. Oletusarvo on 0.

Kun sql_safe_updates on 1.

  • Päivityskäskyn on täytettävä jokin seuraavista ehdoista, jotta se voidaan suorittaa onnistuneesti:
    • Päivityskäsky käyttää missä, ja jos-ehdossa on oltava indeksisarake;
    • Päivityskäsky käyttää rajaa;
    • Päivityskäsky käyttää missä ja rajaa samanaikaisesti. Tällä hetkellä where-ehdolla ei tarvitse olla indeksisaraketta.
(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
  • Poista-käskyn on täytettävä seuraavat ehdot, jotta se voidaan suorittaa onnistuneesti:
    • Poista-käsky käyttää myös hakemistosarakkeita where-ehdossa.
    • Poista-käsky käyttää sekä indeksisaraketta että rajaa where-ehdossa.
    • Poista-käsky käyttää samanaikaisesti missä ja rajaa. Tällä hetkellä where-ehdolla ei tarvitse olla indeksisaraketta.
(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

Jos where-ehto tuo indeksisarakkeen, mutta optimoija lopulta skannaa ja valitsee koko taulukon indeksin sijaan, voimme käyttää pakottaa indeksiä ([index_name]) kertoaksemme optimoijalle, mitä indeksiä käyttää, jotta vältytään mahdolliselta koko taulukon lukitsemiselta. pöydän aiheuttamat piilotetut vaarat.