mysql中保险开关防止UPDATE,DELETE误删除

有的时候,线上容易不小心UPDATE,DELETE的时候,无加限制条件,从而引起灾难,
但其实MYSQL有开关可以防止误操作,一定程度上减少发生机会。
可以设置:
sql_safe_updates
其中 :
当sql_safe_updates设置为1时,update:要有where,并查询条件必须使用为索引字段,或者使用limit,或者两个条件同时存在,才能正常执行。delete:where条件中带有索引字段可删除,where中查询条件不是索引,得必须有limit。主要是防止update和deLete没有使用索引导致变更及删除大量数据。参数默认值为0

更多参考来自:
http://www.itopers.com/blog/posts/database/mysql/sql_safe_updates.html

如下例子:

CREATE TABLE `sql_safe` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `balance` decimal(12,2) unsigned NOT NULL DEFAULT '0.00',
  `uid` bigint(20) NOT NULL,
  `nuid` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_uid` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8
mysql> select * from sql_safe;
+----+---------+-----+------+
| id | balance | uid | nuid |
+----+---------+-----+------+
|  1 |    0.10 | 123 |  123 |
|  2 |  212.00 | 124 |  124 |
|  3 |    1.01 | 150 |  150 |
|  4 |    2.00 | 129 |  129 |
|  5 |   23.10 | 130 |  130 |
|  6 |  236.00 | 126 |  126 |
|  7 |   26.01 | 127 |  127 |
|  8 |   31.00 | 131 |  131 |
+----+---------+-----+------+
8 rows in set (0.00 sec)
mysql> show variables like 'sql_safe_updates';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| sql_safe_updates | ON    |
+------------------+-------+
#语句A:
mysql> update sql_safe set balance = balance - 10;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column

#语句B:
mysql> update sql_safe set balance = balance - 10 where nuid = 123;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column

#语句C:
mysql> update sql_safe set balance = balance - 10 where uid = 123;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

#语句D:
mysql> update sql_safe set balance = balance - 10 limit 1;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 1
语句A和语句B一个是没有使用where,一个是没有用到索引,都提示执行失败,报ERROR 1175

语句C和语句D一个是where中使用了索引字段,一个是使用了limit,都是精确到了部分数据。

关于Warnings: 1这个,是out of range的原因,这个后续再说明下各个数值字段类型超范围的处理。

Delete会不一样些,条件更为严格:

#语句E:
mysql> delete from 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

#语句F:
mysql> delete from sql_safe where nuid = 123;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column

#语句G:
mysql> delete from sql_safe where uid = 123;
Query OK, 1 row affected (0.00 sec)

#语句H:
mysql> delete from sql_safe where nuid = 124 limit 1;
Query OK, 1 row affected, 1 warning (0.00 sec)

#语句I:
mysql> delete from 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
delete只有使用where条件带索引,或者where +limit可以正常执行,其它都会有问题。

所以说,启用这个参数,需要详细了解业务中的sql,是否都通过索引进行update/delete,如果没有,会出现sql执行报错。

另外,sql_safe_updates这个参数在各版本之间的功能都一样,唯一的区别是作用域不一样。

5.0,5.1都是session级别的,5.5,5.6是global&session级别。

正因为这个作用域的限制,在低版本中无法在线在数据库中直接开启这个功能,高版本中可在线开启,但也需要中断现有连接才能生效。

那么如果才能让这个sql_safe_updates这个功能生效?

1、低版本数据库只能程序端直接在创建session时,带上set sql_safe_updates = 1

2、高版本数据库可以set global sql_safe_updates = 1;然后让前端程序重新创建连接。也可在创建session时,set sql_safe_updates = 1;

猜你喜欢

转载自jackyrong.iteye.com/blog/2293631