sql_safe_updates
1.官方文档
首先我们来看一下官方文档(5.6)对该参数的解释:
sql_safe_updates | Yes | Both | Yes |
##因为sql_safe_updates是SYSTEM VAR,所以我们无法直接在mysql启动命令行和控制文件中添加该参数,只能在等能mysql实例后执行 set global/session sql_safe_updates=1;来设置。
但是我们可以通过init_connect参数来实现在控制文件中设置sql_safe_updates的目的,我们可以在控制文件中添加如下记录(注意init_connect对于有super权限的用户是无效的)
init_connect=‘SET SQL_SAFE_UPDATES=1‘
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.
##官方文档上的解释和我实际测试的结果有些出入,还是以实际测试结果为准
2.测试
2.1 测试库版本
mysql> select version(); +------------+ | version() | +------------+ | 5.6.26-log | +------------+
2.2 update及delete测试
2.2.1 测试表结构如下
CREATE TABLE `insure_user_info` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `order_id` varchar(100) DEFAULT NULL, `insure_name` varchar(50) DEFAULT NULL', `insure_id_type` varchar(20) DEFAULT NULL, `insure_idcard` varchar(50) DEFAULT NULL, `insure_birthdate` date DEFAULT NULL, `insure_sex` varchar(10) DEFAULT, `insure_phone` decimal(20,0) DEFAULT, `insure_mail` varchar(100) DEFAULT NULL, `insure_province` varchar(100) DEFAULT, `insure_city` varchar(100) DEFAULT NULL, `insure_address` varchar(100) DEFAULT NULL, `invitation_code` varchar(100) DEFAULT NULL, `create_time` varchar(100) DEFAULT NULL, `is_Policy_send` varchar(10) DEFAULT '不寄送', PRIMARY KEY (`id`), KEY `idx_orderid` (`order_id`), KEY `ind_test_1` (`insure_idcard`,`insure_mail`) ) ENGINE=InnoDB AUTO_INCREMENT=66720 DEFAULT CHARSET=utf8
2.2.2 设置 sql_safe_updates参数为on
set session sql_safe_updates=1;
2.2.3 update测试
mysql> update insure_user_info set insure_name='fei'; ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column ##直接update,不加where条件及limit,update语句执行失败 mysql> update insure_user_info set insure_name='fei' where id<10; Query OK, 9 rows affected (0.01 sec) Rows matched: 9 Changed: 9 Warnings: 0 ##update 加上where 条件 并且id列为主键,update执行成功 mysql> update insure_user_info set insure_name='fei' limit 10; Query OK, 10 rows affected (0.00 sec) Rows matched: 10 Changed: 10 Warnings: 0 ##update不加where条件,仅适用limit,update执行成功 mysql> update insure_user_info set insure_name='fei' where create_time <'2015-12-11 16:01:54'; ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column ##update的加where条件,但是create_time列未建索引,update语句执行失败 mysql> update insure_user_info set insure_name='fei' where create_time <'2015-12-11 16:01:54' limit 10; Query OK, 9 rows affected (0.21 sec) Rows matched: 9 Changed: 9 Warnings: 0 ##update加where条件,create_time列为非索引列,同时使用limit,update语句执行成功 mysql> update insure_user_info set insure_name='fei' where insure_idcard < '110000197609260652'; Query OK, 0 rows affected (0.00 sec) Rows matched: 0 Changed: 0 Warnings: 0 ##update 加where子句,where子句中列为组合索引的prefix列,update执行成功 mysql> update insure_user_info set insure_name='fei' where insure_mail < '[email protected]'; ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column ##update 加where子句,where子句中列为组合索引的非prefix列,update执行失败
2.2.4 delete测试
mysql> delete from insure_user_info; 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某张表,不加任何条件,delete语句执行失败 mysql> delete from insure_user_info limit 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 ##delete 不加where字句,仅使用limit,delete语句失败 mysql> delete from insure_user_info where create_time <'2015-12-11 16:01:54'; 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子句中create_time列不是索引列,delete执行失败 mysql> delete from insure_user_info where id <10; Query OK, 9 rows affected (0.01 sec) ##delete 加where子句,where子句中 id 为主键索引,delete执行成功 mysql> delete from insure_user_info where create_time <'2015-12-11 16:01:54' limit 10; Query OK, 9 rows affected (0.18 sec) ##delete 加where子句,但是where子句中create_time不是索引列,同时使用limit,delete执行成功 mysql> delete from insure_user_info where id <20 limit 10; Query OK, 10 rows affected (0.00 sec) ##delete 加where子句,where子句中id列是主键,同时使用limit,delete执行成功 mysql> delete from insure_user_info where insure_idcard <'110000197609260652'; Query OK, 10 rows affected (0.00 sec) ##delete 加where子句,where子句中insure_phone列为组合索引的prefix列,delete执行成功 mysql> delete from insure_user_info where insure_mail<'[email protected]'; 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子句中insure_mail为组合索引的非prefix列,delete执行成功
3.总结
3. 总结 如果设置了sql_safe_updates=1,那么update语句必须满足如下条件之一才能执行成功 1)使用where子句,并且where子句中列必须为prefix索引列 2)使用limit 3)同时使用where子句和limit(此时where子句中列可以不是索引列) delete语句必须满足如下条件之一才能执行成功 1)使用where子句,并且where子句中列必须为prefix索引列 2)同时使用where子句和limit(此时where子句中列可以不是索引列)