如何无需通读全量PHP代码即可定位前端操作涉及的MySQL表
原生PHP项目定位前端操作对应数据库表影响的方案
不用通读全量代码,按落地成本从低到高选下面的方案就行,准确率最高的是第一种数据库层抓日志的方式:
方案1:数据库层开启查询日志(零代码侵入,优先选)
全程在测试环境操作,不要连生产库:
- 先把旧PHP应用的数据库连接指向测试数据库,确认前端操作能正常跑通
- 登录测试库MySQL执行命令,临时开启通用查询日志,把日志存在系统表里方便查询:
SET GLOBAL general_log = 'ON'; SET GLOBAL log_output = 'TABLE';
- 清空浏览器无关请求,只在前端触发你要排查的那一个特定操作,等所有接口返回、页面加载完成后再等30秒,覆盖可能存在的延迟执行逻辑
- 查数据库日志表,过滤对应时间段的查询记录,直接提取所有
SELECT/INSERT/UPDATE/DELETE语句涉及的表名即可,查询参考:
SELECT argument FROM mysql.general_log WHERE event_time >= '你触发操作的开始时间' AND command_type = 'Query';
- 排查完成后记得关闭日志,避免占用数据库性能:
SET GLOBAL general_log = 'OFF';
这个方案能抓到所有执行过的SQL,包括动态拼接表名、公共钩子隐式触发的写操作,不会漏逻辑,准确率100%
方案2:全局拦截PHP数据库请求(仅改1处初始化代码)
如果没有数据库管理员权限开不了查询日志,就用这个方法:
- 原生PHP项目的数据库连接初始化一般都在单独的公共配置文件里,找到全局创建数据库连接的位置
- 如果用PDO连接,就继承原生PDO类重写
query、exec、prepare相关方法,在方法执行前把SQL语句、当前请求地址写到本地日志文件;如果用mysqli或者老的mysql扩展,同理封装一层查询方法,替换全局的查询调用即可 - 改完后同样单独触发目标前端操作,拉取日志解析SQL里的表名就行,整个过程不用翻业务代码
方案3:静态正则扫描做初筛(最快出初步清单)
如果只是要快速拿个初步清单,可以直接用命令行做正则匹配,不用读代码细节:
- 在项目根目录执行grep命令,匹配所有SQL关键字关联的表名:
grep -r -i -n -E "(INSERT\s+INTO|UPDATE|FROM|JOIN)\s+[`']?[a-zA-Z0-9_]+[`']?" ./
- 把匹配结果里的表名去重就能得到初步清单,注意这个方法会漏掉动态拼接的表名、条件触发的SQL,只能做初筛,要以动态抓日志的结果为准
注意:如果你的旧项目有异步消费、定时任务关联触发逻辑,触发前端操作后多等1-2分钟再拉日志,避免漏掉异步执行的数据库操作。
内容的提问来源于stack exchange,提问作者Moaz Maalik
相关产品推荐
相关产品推荐

