對於研發而言,線上數據庫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)不能沒有索引!