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就行。
[[email protected] logs]# grep -B 5 safe-updates /etc/my.cnf
[mysql]
auto-rehash
prompt="\\[email protected] \\h [\\d]>"
#pager="less -i -n -S"
#tee=/opt/mysql/query.log
safe-updates
檢視當前mysql session會話下的sql_safe_updates
[email protected] [(none)]>select @@sql_safe_updates; +--------------------+ | @@sql_safe_updates | +--------------------+ | 0 | +--------------------+ 1 row in set (0.00 sec)
檢視全域性的配置引數sql_safe_updates
[email protected] [(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
[email protected] [test02]>create index A on zx_scores(titles);
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
檢視該表存在的索引
[email protected] [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)
通過查看錶結構也是可以看到索引的
[email protected] [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開啟了安全模式
[email protected] [test02]>select @@SQL_SAFE_UPDATES;
+--------------------+
| @@SQL_SAFE_UPDATES |
+--------------------+
| 0 |
+--------------------+
1 row in set (0.00 sec)
設定sql為安全模式:
[email protected] [test02]>set global sql_safe_updates=1;
Query OK, 0 rows affected (0.00 sec)
退出當前的MySQL的session會話層,重新登入mysql檢視當前的sql_safe_updates為1,代表開啟了sql的安全模式
[email protected] [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());
演示一:
[email protected] [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.
[email protected] [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條件,是會拒絕更新的。
[email protected] [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.
[email protected] [test02]>
2.當where條件中列(column)沒有索引可用且無limit限制時會拒絕更新。
[email protected] [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.
[email protected] [test02]>
一旦加上limit限制是可以更新的:
[email protected] [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限制時會拒絕更新。
[email protected] [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.
[email protected] [test02]>
例如:update zx_scores set titles='班長' where icon=1;是會拒絕跟新的
一旦加上limit限制是可以更新的:
[email protected] [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限制時是可以更新的:
[email protected] [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限制時拒絕刪除。
[email protected] [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.
[email protected] [test02]>
當①where條件為常量,且有limit限制是可以刪除的。
[email protected] [test02]>delete from zx_scores where 1=1 limit 5;
Query OK, 5 rows affected (0.06 sec)
2.當②或where條件為空,且無limit限制時拒絕刪除。
[email protected] [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.
[email protected] [test02]>
3.當③或where條件中 列(column)沒有索引可用且無limit限制時拒絕刪除。
[email protected] [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.
[email protected] [test02]>
但是titles欄位上建立了索引A,所以可以刪除
[email protected] [test02]>delete from zx_scores where titles='班長';
Query OK, 2 rows affected (0.03 sec)
[email protected] [test02]>
需要注意的是:
update操作中,where可以為常量 ,where條件中列(column)可以沒有索引,但是需要有limit限制。
然而delete要嚴格一些:where不能為常量,且where條件中列(column)不能沒有索引!