事情原由:
先大致说下事情的缘由,前几天有开发找到我(运维),说测试数据库里面的某张表被更新为同样的值了。什么?
我一会,一身冷汗,感觉看了下线上,还好没事。当即觉得不能再上线任何代码。
技术栈背景:某云RDS, php,larave
年初(2020春节后,疫情期间)就在测试环境出现过一次,一条SQL没加where条件把所有的字段都更新了。
而且是用户的余额字段。后来找到源头改掉了,还好没上线。
又出现这样的情况,第一时间找源头。仔细搜索代码和新上到测试线的功能,找到了。
一个没加where条件的更新的语句执行更新了。(而且已经在测试环境放了3天了)
天呀,测试的同学只看自己操作的单条数据没问题,并没有发现都更新了。又一次差点技术部被干掉。
寻找规避方法
1、通过jenkins拉取代码后,对代码用sonarqube进行扫描
2、通过jenkins拉取代码后,自己写Python脚本扫描(看看某行代码有update,但没有where的就报错)网上找的前半段代码,自己加了后半段。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
#递归遍历目录
def getAlldirInDiGui( path):
filesList=os.listdir(path)
#print(filesList)
for fileName in filesList:
fileAbpath=os.path.join(path,fileName)
if os.path.isdir(fileAbpath):
# print("目录:" ,fileName)
getAlldirInDiGui(fileAbpath)
else:
if (fileAbpath.find('.php')>1):
checkFileContents(fileAbpath)
#传递参数的时候,注意需要写上(r)表明传递的是路径
#getAlldirInDiGui(r"D:\test")
def checkFileContents(fileName):
fo = open(fileName, "r")
#print ("文件名为: ", fo.name)
flag = 'false'
for line in fo.readlines(): #依次读取每行
line = line.strip() #去掉每行头尾空白
line = line.lower()
if line.find('update(') > 0:
flag = 'true'
if line.find('where') < 1 :
print(fileName+' error')
sys.exit(1)
# 关闭文件
fo.close()
getAlldirInDiGui(r"/work/")
3、限定条数
经过实践后
方法1,折腾起来动静有些大,没具体深入研究【继续研究中】,想着搞通后不一定能符合自己的需求。
方法2,自己写的脚本兼容性太差,有的方法名里面就有update。或者where没在同一行。
方法3,业务场景太复杂,不可行。
发现新大陆
于是搜索到了mysql 的 sql_safe_updates,原来mysql人家料到了会有程序员犯错误。
MySQL参数sql_safe_updates
设置之后,会限制update delete 中不带 where 条件的SQL 执行,update 时,在没有 where 条件或者where 后不是索引字段时,必须使用 limit ;在有 where 条件时,为索引字段
太棒了,这不就是梦寐以求的功能吗?简单粗暴。
然后改mysql的里面的计划任务(event),把没有用到索引的更新sql改掉。
然后改数据库设置。
mysql> set GLOBAL sql_safe_updates = 1;
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation
卡,root账号,告诉我没权限。。。。
于是 提交工单,
对方答复了:
原来我一直用的是假的root呀。
崩溃中。。。。。。
在破灭的希望找到一些光明,
虽然不能全局修改,但可以在larave每次启动的时候设置会话级别的
DB::select('set sql_safe_updates = 1');
虽然几十个项目都需要改,但至少能防止数据的误操作。
防止无脑update和delete的方法
1、对开发人员进行警钟长鸣
2、测试用例的健全
3、有更新和删除操作时,主管或者结对进行代码review
说下你们是怎么防止无脑update和delete的
如果你感觉本文对你有帮助,请转发,说不定你的朋友也需要它。