sql 索引 sql_safe_updates

时间:2023-03-09 10:03:40
sql 索引 sql_safe_updates

为了数据的安全性,mysql有一个安全性设置,sql_safe_updates ,当把这个值设置成1的时候,当程序要对数据进行修改删除操作的时候条件必须要走索引。

刚好现在也碰到了此类问题:网上找了相关文章查看,了解到了有些时候虽然设置了索引列,但是在有些情况下他是不走索引的

1,字段类型不匹配 比如int类型和varchar  比如当code是索引时

Select * from table where code=123  这样是不会走索引的

必须

Select * from table where code=”123” 这样才会走索引

2,not in ,!=,is not null 不会走,网上说的是not in会分索引的类型有的走,有的不走,但是我在下面执行的结果是不走的

3,如果函数对索引列进行操作后是不会走的 如

SELECT * FROM box_org WHERE LENGTH(CODE)= "100001032"

这些都是一些比较明显的,还有一种特殊的情况,隐藏的比较深,我有个功能被这个坑了几天

就是当你sql解释器里面有多条解释,只要有一条没走索引,那么你这条语句就不能更新和删除,比较奇怪的是我13开发环境中测试程序能直接删除,但是test就是删除不了,就是这样原因不得不去解决,所以才有了以下的猜测。

(ps:13上的安全设置开启没有?我以前测是开启了,没加索引的不能删除,加了的就能删,按理说这样就证明已经开启了,而且13组织这个功能也能删,但是在test上就删不了,这个比较奇怪,一哥你可以去看下,看test和13环境有什么不同,肯定不是数据库版本不同导致的,因为我把sql拿出来仔细测了n边,手动set后,在mysql客户端执行13也是不行的,但是在商家后台执行却能成功- -)

下面是我测试截图

sql 索引 sql_safe_updates

这个是解释器,里面只有一条走了索引

看看删除结果

sql 索引 sql_safe_updates

提示删除失败,更新表必须要用到索引列

在看看下面一张图

sql 索引 sql_safe_updates

这里的shop_id 是索引列,但是他还是没走索引 ,这样就让我不的不猜测是不是sql有问题,因为box_org 这个相当于一个临时表(这个理解肯定有有问题,它不是临时表,但是当时测的时候我是这样想的),而当作为临时表的时候,他里面所有的索引是不是都被隐式给转掉了,不让走索引了

下图执行删除结果

sql 索引 sql_safe_updates

为了验证上面猜测,函数包含不走索引,及临时表不走索引,下面我也做了一下实验

sql 索引 sql_safe_updates

这条sql我用了inner join 连接查询 条件都用函数或者是is not 结果是没走索引,下面是执行更新情况

sql 索引 sql_safe_updates

然后我重新加了一个索引 is_active

sql 索引 sql_safe_updates

很明显,is_active 走了索引,然后来执行更新操作

sql 索引 sql_safe_updates

结果成功

为了验证我上面说的所谓的临时表不走索引我又做了一下实验

sql 索引 sql_safe_updates

很明显,我上面的临时表结论是错误的,box_org不是一张临时表,所以我理解错误了下面是执行结果

sql 索引 sql_safe_updates

执行成功

但是为什么这句会失败呢,同样的写法

sql 索引 sql_safe_updates

结果

sql 索引 sql_safe_updates

从上面对比可以知道就是当解释器里面有没走索引时,是不会删除成功的

测试的时候我还发现了一个坑爹的问题,那就是当没有数据的时候他执行是不会报错的,因为没有数据执行sql时数据库里面没有数据给他操作,如下

sql 索引 sql_safe_updates

有数据的结果

sql 索引 sql_safe_updates

这也就导致了为什么在两个环境中时好时坏,测试的时候也会出现不同的结果

所以写此类sql的时候最好还是用连接查询,这样避免此类问题,下面是连接查询执行结果

sql 索引 sql_safe_updates

执行成功

总结:当与到此类问题最好是走连接查询吧,不然sql写的有问题,测的时候会时好时坏,把人搞懵,费时费力费脑。。。以上就是我的结论,因为研究的不深,可能会有出入或者是错误的地方,仅供给大家一个参考。但是连接查询还有上面不走索引的我是测试了的,可以保证

猜测解释器只要有一条不走索引,那么更新就更新不了,至少我上面测试的结论是这样的,还有那个所谓的临时表猜测,因为理解有误所以测的有点乱,好像有点牛头不对马嘴。

仔细看了下

sql 索引 sql_safe_updates

sql 索引 sql_safe_updates

为什么code走索引,而shop_id不走呢?难道是前面走了索引后面就不走了?显然看一图就不成立,猜测2,难道索引后面只能跟具体值?看一图和二图也不成立。到现在这个问题我也没能搞明白- -