MySQL安全更新之safe_updates介紹說明

對於研發而言,線上數據庫update和delete是非常頻繁的,因而經常出現update和delete時,後面忘記添加where條件的限制,導致整個表誤刪除,或者是誤更新,造成很多災難是非常常見的事情,如何徹底解決這樣的人爲的數據庫故障或者減少這種人爲的故障了,那就是從根本上控制好mysql數據庫的權限,禁止給研發人員update和delete數據庫的權限,嚴格SQL語句上線之前的審覈,減少人爲的操作mysql庫的故障。然而這種數據庫的權限的把控往往是很難嚴格意義上把控好的。只能是減少類似這樣的故障的發生。
下面咱們簡單介紹下client端mysql的safe_updates 參數的使用,它從一定程度上還是可以避免上面的update和delete時,後面忘記添加where條件而帶來的悲劇。

sql_safe_updates具體的使用方法咱們可以man 下mysql

man mysql|grep sql_safe_updates
           SET sql_safe_updates=1, sql_select_limit=1000, max_join_size=1000000;

同時也可以把參數寫入到/etc/my.cnf配置文件
在my.cnf配置文件開啓參數safe-updates就行。

[root@app1 logs]# grep  -B 5 safe-updates /etc/my.cnf
[mysql]
auto-rehash
prompt="\\u@\\h [\\d]>"
#pager="less -i -n -S"
#tee=/opt/mysql/query.log
safe-updates

查看當前mysql session會話下的sql_safe_updates

root@localhost [(none)]>select @@sql_safe_updates;
+--------------------+
| @@sql_safe_updates |
+--------------------+
|                  0 |
+--------------------+
1 row in set (0.00 sec)

查看全局的配置參數sql_safe_updates

root@localhost [(none)]>select @@global.sql_safe_updates;
+---------------------------+
| @@global.sql_safe_updates |
+---------------------------+
|                         0 |
+---------------------------+
1 row in set (0.00 sec)

創建測試表並且插入數據測試

CREATE TABLE `zx_scores` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `titles` char(15) NOT NULL,
  `icon` smallint(6) unsigned DEFAULT '0',
  `integral` int(10) NOT NULL DEFAULT '0',
  `isdefault` tinyint(1) unsigned NOT NULL DEFAULT '0',
`create_time` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`day` date NOT NULL DEFAULT '0000-00-00' COMMENT '日期',
  PRIMARY KEY (`id`),
  KEY `integral` (`integral`)
) ENGINE=Innodb AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

給表zx_sorces中的字段titles字段添加一個索引A


root@localhost [test02]>create index A on zx_scores(titles);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

查看該表存在的索引

root@localhost [test02]>show index from zx_scores;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| zx_scores |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| zx_scores |          1 | integral |            1 | integral    | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| zx_scores |          1 | A        |            1 | titles      | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

通過查看錶結構也是可以看到索引的

root@localhost [test02]>desc zx_scores;
+-------------+----------------------+------+-----+------------+----------------+
| Field       | Type                 | Null | Key | Default    | Extra          |
+-------------+----------------------+------+-----+------------+----------------+
| id          | int(11) unsigned     | NO   | PRI | NULL       | auto_increment |
| titles      | char(15)             | NO   | MUL | NULL       |                |
| icon        | smallint(6) unsigned | YES  |     | 0          |                |
| integral    | int(10)              | NO   | MUL | 0          |                |
| isdefault   | tinyint(1) unsigned  | NO   |     | 0          |                |
| create_time | varchar(20)          | NO   |     | NULL       |                |
| day         | date                 | NO   |     | 0000-00-00 |                |
+-------------+----------------------+------+-----+------------+----------------+
7 rows in set (0.00 sec)

查看當前sql的模式,0代表sql沒有開啓安全模式,1代表sql開啓了安全模式


root@localhost [test02]>select @@SQL_SAFE_UPDATES;
+--------------------+
| @@SQL_SAFE_UPDATES |
+--------------------+
|                 0  |
+--------------------+
1 row in set (0.00 sec)

設置sql爲安全模式:


root@localhost [test02]>set global sql_safe_updates=1;
Query OK, 0 rows affected (0.00 sec)

退出當前的MySQL的session會話層,重新登錄mysql查看當前的sql_safe_updates爲1,代表開啓了sql的安全模式

root@localhost [test02]>select @@SQL_SAFE_UPDATES;
+--------------------+
| @@SQL_SAFE_UPDATES |
+--------------------+
|                  1 |
+--------------------+
1 row in set (0.00 sec)

給表中插入測試數據:

insert into zx_scores values(1,'列兵',1,0,1,now(),curdate());
insert into zx_scores values(2,'班長',2,1000,1,now(),curdate());
insert into zx_scores values(3,'少尉',3,2000,1,now(),curdate());
insert into zx_scores values(4,'中尉',4,3000,1,now(),curdate());
insert into zx_scores values(5,'上尉',5,4000,1,now(),curdate());
insert into zx_scores values(6,'少校',6,5000,1,now(),curdate());
insert into zx_scores values(7,'中校',7,6000,1,now(),curdate());
insert into zx_scores values(8,'上校',8,7000,1,now(),curdate());
insert into zx_scores values(9,'少將',9,12000,1,now(),curdate());
insert into zx_scores values(10,'中將',10,17000,1,now(),curdate());
insert into zx_scores values(11,'上將',11,22000,1,now(),curdate());
insert into zx_scores values(12,'大將',12,27000,1,now(),curdate());

演示一:

root@localhost [test02]>update zx_scores set titles='班長' where icon=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. 
root@localhost [test02]>

簡單翻譯一下:你正在使用 安全更新模式(safe upate mode)並且你在嘗試 update 一個表時 沒有用帶有鍵的列 作爲where條件。

初學者在修改一個值時可能會用以下語句:

update table_name set column='new_value'
而這正是很多人常犯的錯誤。因爲他沒有限定條件,會將表中所有的記錄都修改一遍。
爲了防止這種錯誤出現,我們可以開啓安全更新模式(safe update mode):
set [global] SQL_SAFE_UPDATES = 1;

在update操作中:

1.當update table 時,後面沒有where條件,是會拒絕更新的。

root@localhost [test02]>update zx_scores set titles='班長' ;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. 
root@localhost [test02]>

2.當where條件中列(column)沒有索引可用且無limit限制時會拒絕更新。

root@localhost [test02]>update zx_scores set titles='班長' where icon=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. 
root@localhost [test02]>

一旦加上limit限制是可以更新的:

root@localhost [test02]>update zx_scores set titles='班長' where icon=1 limit 1;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

3.當where條件爲常量且無limit限制時會拒絕更新。

root@localhost [test02]>update zx_scores set integral='1000' where 1=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. 
root@localhost [test02]>

例如:update zx_scores set titles='班長' where icon=1;是會拒絕跟新的

一旦加上limit限制是可以更新的:


root@localhost [test02]>update zx_scores set integral='1000' where icon=1 limit 1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

當where條件爲常量且有limit限制時是可以更新的:

root@localhost [test02]>update zx_scores set titles='少將' where 1=1 limit 2;
Query OK, 1 row affected (0.10 sec)
Rows matched: 2  Changed: 1  Warnings: 0

在delete操作中:

1.當①where條件爲常量,且無limit限制時拒絕刪除。

root@localhost [test02]>delete from zx_scores where 1=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. 
root@localhost [test02]>

當①where條件爲常量,且有limit限制是可以刪除的。

root@localhost [test02]>delete from zx_scores where 1=1 limit 5;
Query OK, 5 rows affected (0.06 sec)

2.當②或where條件爲空,且無limit限制時拒絕刪除

root@localhost [test02]>delete from zx_scores;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. 
root@localhost [test02]>

3.當③或where條件中 列(column)沒有索引可用且無limit限制時拒絕刪除。

root@localhost [test02]>delete from zx_scores where icon =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. 
root@localhost [test02]>

但是titles字段上創建了索引A,所以可以刪除

root@localhost [test02]>delete from zx_scores where titles='班長';
Query OK, 2 rows affected (0.03 sec)
root@localhost [test02]>

需要注意的是:

update操作中,where可以爲常量 ,where條件中列(column)可以沒有索引,但是需要有limit限制。
然而delete要嚴格一些:where不能爲常量,且where條件中列(column)不能沒有索引!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章