MySQL不帶where條件的UPDATE和DELETE 限制操作說明


 

本文來自 網易雲社區 。

 

數據安全是業務的基石,但是DBA 總會遇到救火情況,業務誤刪除全表或者誤更新錯全表業務數據,導致服務不可用

 

sql_safe_updates參數可以限制不帶where條件的update/delete語句執行失敗,這個參數設置后,可以防止業務bug/漏洞導致把整個表都更新或者刪除(線上發生過的案例),也可以防止DBA在線誤操作更新/刪除整張表。

 

官方解釋:

If set to 1, MySQL aborts UPDATE or DELETE statements that do not use a key in the WHERE clause or a LIMIT clause. (Specifically, UPDATE statements must have a WHERE clause that uses a key or a LIMIT clause, or both. DELETE statements must have both.) This makes it possible to catch UPDATE or DELETE statements where keys are not used properly and that would probably change or delete a large number of rows. The default value is 0.

意思是說

當sql_safe_updates設置為1時,UPDATE :要有where,並查詢條件必須使用為索引字段,或者使用limit,或者兩個條件同時存在,才能正常執行。DELETE:where條件中帶有索引字段可刪除,where中查詢條件不是索引,得必須有limit。主要是防止UPDATE和DELETE 沒有使用索引導致變更及刪除大量數據。系統參數默認值為0

 

為了防止線上業務出現以下3種情況影響線上服務的正常使用和不小心全表數據刪除:

 

1:沒有加where條件的全表更新操作

 

2:加了where 條件字段,但是where 字段 沒有走索引的表更新

 

3:全表delete 沒有加where 條件 或者where 條件沒有 走索引

 

如果業務開發存在如上的操作,數據庫會出現如下錯誤:

 

MySQL 報錯如下:

 

 ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column

DDB 報錯如下:

 

Caused by: java.sql.SQLException: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:946)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)

建議: DBA 開啟此參數限制 ,可以避免線上業務數據誤刪除操作,但是需要先在測試庫開啟,這樣可以可以先在測試庫上補充短缺的表索引,測試驗證沒問題再部署到線上庫 郵件部從去年開始已經在嚴選電商線上運行。

 

 

測試案例: 全局開啟 sql_safe_updates 限制

 

[test]> show variables like 'sql_safe_updates';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| sql_safe_updates | ON    |
+------------------+-------+
CREATE TABLE `test_sql_safe` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` bigint(20) NOT NULL,
  `status` int(1) DEFAULT '0',
  `amount` int(11) NOT NULL DEFAULT '0',
  `nuid` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_uid` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
 [test]> select * from test_sql_safe;
+----+------+--------+--------+--------+
| id | uid  | status | amount | nuid   |
+----+------+--------+--------+--------+
|  1 | 1111 |      1 |    500 |  22222 |
|  2 | 2111 |      0 |    600 | 332222 |
|  3 | 3111 |      1 |    700 | 442222 |
|  4 | 4111 |      0 |    500 | 552222 |
|  5 | 5111 |      1 |    600 | 662222 |
+----+------+--------+--------+--------+
 [test]> update test_sql_safe set amount = amount +100;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
test]> update test_sql_safe set amount = amount +100 limit 2;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0
[test]> select * from test_sql_safe ;
+----+------+--------+--------+--------+
| id | uid  | status | amount | nuid   |
+----+------+--------+--------+--------+
|  1 | 1111 |      1 |    600 |  22222 |
|  2 | 2111 |      0 |    700 | 332222 |
|  3 | 3111 |      1 |    700 | 442222 |
|  4 | 4111 |      0 |    500 | 552222 |
|  5 | 5111 |      1 |    600 | 662222 |
+----+------+--------+--------+--------+
[test]> update test_sql_safe set amount = amount +100 where uid = 2111;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
[test]> delete from test_sql_safe;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
delete from test_sql_safe where status = 0;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
delete from test_sql_safe where uid =3111;
Query OK, 1 row affected (0.00 sec)
[test]> delete from test_sql_safe where amount = 500 limit 1;
Query OK, 1 row affected (0.00 sec)
[test]> delete from test_sql_safe  limit 1;
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不帶where條件的UPDATE和DELETE 限制操作說明

更多網易研發、產品、運營經驗分享請訪問網易雲社區

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM