SQL变更评审常见问题分享

SQL变更评审分享

概述

SQL变更,是我们在开发迭代中不可避免的场景,SQL变更通常是指DDL和DML语句变更,这些sql会影响到数据库表结构或具体数据,变更时如果执行到存在问题的sql脚本,会对实际应用操作难以评估的损失,比如咱们常挂在嘴边的删库跑路。

通常情况下程序员并发故意想“删库跑路”,而是因为种种原因,将存在问题的sql脚本放到了生产环境执行,导致最终出现生产环境数据异常。我们避免异常SQL在生产环境执行的一个有效方式,就是进行SQL变更评审,在评审过程中,我们能将一些有明显缺陷的SQL语句及时拦截,也能凭借评审人的sql经验,把一些不容易发现的问题在评审过程中暴露,进而优化。

sql变更不能完全依赖于评审发现问题,评审只是变更流程中不可获取的一环,评审可以一定程度上防止变更人的疏忽大意以及惯性思维,另外将sql暴露在多个评审人眼前,也容易让问题更容易被发现。sql评审比较依赖于评审人的相关经验,我参与过一些sql评审,故在这里对评审总结的一些经验进行分析,共勉。

一、常见的一些DML操作

以表t_user为例

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `password` varchar(32) DEFAULT NULL,
  `role` int(11) DEFAULT NULL,
  `creation_date` datetime DEFAULT NULL,
  `last_update_date` datetime DEFAULT NULL,
  `is_deleted` tinyint(4) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1486021 DEFAULT CHARSET=latin1;

数据样式
在这里插入图片描述

1、执行语句是否有加 where条件,或者where后面的条件是符合预期

update t_user set `password` = 222 -- 变更人遗忘了where条件

delete from t_user where is_deleted = 'Y';  -- 变更人希望清除标记为已删除的数据

上述update语句,由于“where”条件缺失,将对整张表进行字段“password”字段修改

上述delete语句,变更人希望清除标记为已删除的数据,is_deleted为int类型,值1表示已删除,值0表示未删除,由于变更人把枚举理解为“Y”表示已删除,数值类型与字符串比较时,会进行隐式转换,字符串开头不为数字,会被转换成0,结果执行sql,t_user表将所有未标记删除的数据进行删除。

2、执行语句覆盖的数据量是否过大

当执行dml语句,如果表数据量大,同时执行语句覆盖的数据量大,会导致执行时间较长,执行语句行锁时间长,结果导致其他业务操作受到影响。

常见的导致覆盖数据太大的情况有如下几种

1)where条件中,索引失效或未使用到包含索引的字段

由于索引失效,where条件查询满足条件的行,会对全表进行扫描,导致数据库锁表

语句一:

update t_user set `password` = 222 where id + 1 = 2; -- id为主键,但是表达式左侧进行运算导致主键索引失效,查询更新数据时进行了全表扫描

在这里插入图片描述

语句二:

update t_user set `password` = 222 where name = "ck"; -- name未添加索引,查询更新数据时全表扫描

在这里插入图片描述

语句一,将索引失效问题处理,即可解决锁表问题
在这里插入图片描述

语句二,如果实际要修改的数据量不多,几个或者几十个,可将数据先提前查出,记录行数据主键或其中一个具有唯一值且有索引的字段,在原查询条件中添加索引字段条件,可有效缩小范围;实际要修改的数据量较大,可通过建立临时表,临时表存储需要修改数据的唯一索引字段,再通过联表的方式进行索引字段关联,缩小范围。

临时表 t_user_id 保存name为“ck” 的id
在这里插入图片描述

2)索引未失效,但仍进行了全表扫描

update t_user set `password` = 222 where id in (select id from t_user_id); -- 全表扫描,update时,每行数据都会进行in select操作

在查询时,这种写法会用到索引,select id from t_user_id 也只会执行1次
在这里插入图片描述

但是在update或delete语句中
在这里插入图片描述

每次每行语句都会执行 select id from t_user_id,因此进行了全表扫描,可将语句改为联表操作,数据范围即可缩小

修改后:

update t_user u join t_user_id ui on u.id = ui.id set `password` = 222;

在这里插入图片描述

3)exist 引入的异常sql

delete from t_user where EXISTS (select 1 from t_user_id ui where ui.id = id); --将进行全表数据删除

t_user 与t_user_id表中都有id字段,exists中就近取t_user_id表的id字段,ui.id = id 恒成立

在删除sql中,exists中的语句不能医用被删除表的中字段,最终写出来能执行的sql,但是却是全表删除
在这里插入图片描述

建议delete语句和update语句使用exists时不要使用这类写法。

修改为联表方式

delete t_user, t_user_id from t_user join t_user_id on t_user.id = t_user_id.id

在这里插入图片描述

二、常见的DDL操作

1、修改字段备注

修改备注时不会进行锁表,无需担心锁表

2、修改字段名称、字段类型、字段长度、字段默认值以及新增字段、添加索引,删除索引

1)此类操作,需考虑表数据量大小,若数据量小于百万级别

执行数据较快,一般不影响业务

2)在百万级别以上,这类修改字段设计到表结构变化,会导致表锁定,应避免在高负载时进行此类操作,以免影响系统性能

3)百万级别以上建议用一下方式修改表字段

a、创建一个新的临时表

b、执行修改表字段操作

c、将原始数据插入临时表,并记录此时时间

b、原始表表名修改,临时表修改为原始表名

e、检查在复制数据阶段,原来的原始表是否有数据更新和插入(根据记录的时间查询),有更新则在新表中同步更新

三、数据备份及数据清理

我们都希望变更执行成功,不会有回退的时候,但为了避免回退时数据丢失难以恢复,有必要进行数据的备份处理;另外长期使用数据库,数据库中难免会有一些空间碎片,为避免存储空间浪费,需要定期进行数据清理;

1、数据备份

1)数据更新或数据删除

将需要修改或需要删除的数据,复制到临时表进行备份,备份表名最好统一格式,便于区分用途和备份时间

2)新增数据无需备份

2、数据清理

1)OPTIMIZE TABLE

OPTIMIZE TABLE 进行碎片整理,由于会锁表,应避免在高负载时进行此类操作,以免影响系统性能
在这里插入图片描述

默认会记录binlog,如果不想记录binlog,添加local参数,即 OPTIMIZE local TABLE

在这里插入图片描述

2)其他清理表方式

OPTIMIZE TABLE执行时间较长时,不可避免影响业务,此时可以参考修改表字段时的操作

a、创建一个新的临时表

b、执行修改表字段操作

c、将原始数据插入临时表,并记录此时时间

b、原始表表名修改,临时表修改为原始表名

e、检查在复制数据阶段,原来的原始表是否有数据更新和插入(根据记录的时间查询),有更新则在新表中同步更新

f、原来需要清理数据的表,进行表删除

最后

sql变更,不可能全靠sql评审规避所有问题,变更人仍需遵守规范,同时重视sql,在上生产前,充分做好测试,测试环境执行测试几乎能规避全部问题,数据写操作时,修改为查询语句,可检测数据范围,让sql在有充分把握,再去生产执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/269456.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Tg5032smn:高稳定性105℃高温

TG5032SMN是一款频率范围10MHz ~ 54MHz,具有高稳定的TCXO晶振,可与CMOS或限幅正弦输出。外部尺寸5.0 3.2 1.45mm,超小型,质地轻。该系列晶振的额定工作范围-40℃~﹢105C内可高稳定性工作,使得信号频率的误差很小。TG5032SMN与其他…

使用 Postman 进行并发请求:实用教程与最佳实践

背景介绍 最近,我们发起了一个在线图书管理系统的项目。我负责的一个关键模块包括三个主要后台接口: 实现对books数据的检索。实施对likes数据的获取。通过collections端点访问数据。 应对高流量的挑战 在设计并部署接口时,我们不可避免地…

Unity网格篇Mesh(一)

Unity网格篇Mesh(一) 本文的目标1.渲染仔细看下面的图你会发现,锯齿状 2.创建网格顶点4 x 2网格网格的顶点 3.创建网格网格只在Play模式下显示逆时针和顺时针三角形第一个三角面一个四边形由两个三角面组成第一个四边形填充剩余网格 接下一篇…

linux运行可执行文件,通过c语言调用java的main方法

前言&#xff1a;以前一直在做Android开发&#xff0c;在某本书上看过一句话“Android上面不只有App类的程序可以运行&#xff0c;能在linux下运行的程序&#xff0c;也可以在Android上面运行” 一.编写C语言部分代码 1.定义java.h头文件 #include <jni.h>#ifndef _JAV…

CSS新手入门笔记整理:动画

在CSS3中&#xff0c;我们可以使用animation属性来实现元素的动画效果。animation属性和transition属性的区别。 transition属性只能将元素的某一个属性从一个属性值过渡到另一个属性值。只能实现一次性的动画效果。animation属性来可以将元素的某一个属性从第1个属性值过渡到…

ubuntu18.04下安装vue

1、更新源 sudo apt update 2、安装nodejs sudo apt install nodejs 查看node版本 nodejs -v 但是此处要的版本是v16.14.2版本&#xff0c;所以要更新 # 查看当前node版本 node -v# 清除npm缓存 npm cache clean -f# 全局安装n npm install -g n# 升级到最新稳定版 n sta…

适用于车载电动升窗器的解决方案

升窗器是指避免车主忘记关窗的自动关窗装置&#xff0c;主要通过电子模块加认组合&#xff0c;利用主机上的芯片里面设定的程序完成检测功能&#xff0c;使自动升窗步骤顺利完成。 ■ 基于ACM32F403系列MCU ■ 高性价比软件控制方案&#xff0c;高算力 ■ MCU内置2路CAN总线&a…

C#/WPF 播放音频文件

C#播放音频文件的方式&#xff1a; 播放系统事件声音使用System.Media.SoundPlayer播放wav使用MCI Command String多媒体设备程序接口播放mp3&#xff0c;wav&#xff0c;avi等使用WindowsMediaPlayer的COM组件来播放(可视化)使用DirectX播放音频文件使用Speech播放(朗读器&am…

鞋服用户运营策略如何实现有效闭环?

实现长期价值和业务闭环是企业经营的关键。对于鞋服行业来说&#xff0c;如何基于客户旅程编排&#xff08;Customer Journey Orchestration&#xff0c;简称 CJO&#xff09;实现用户运营策略的有效闭环&#xff0c;提升长期价值呢&#xff1f; 本文围绕该主题&#xff0c;从鞋…

天呐,我找到财务报表开发的通关密码了!

要问我们IT最不愿做的报表开发有哪些&#xff0c;首当其冲的一定是财务分析。我对开发财务报表这事就一个态度&#xff1a;只要不谈开发财务报表&#xff0c;我们就还是好朋友&#xff0c;谈了会怎样&#xff1f;不好意思&#xff0c;我会破大防。 1、财务的分析逻辑和需求&am…

【c++、数据结构课设】哈夫曼树

时间过的真快&#xff0c;转眼之间一个学期即将结束&#xff0c;想必这个时候大家都在准备各科的课设作业&#xff0c;本期内容是我的数据结构课设&#xff0c;希望能给大家带来帮助&#xff0c;如果有任何不足或需要改进的地方&#xff0c;欢迎各位提出宝贵的意见。 屏幕录制2…

【GoLang】Go语言几种标准库介绍(一)

你见过哪些令你膛目结舌的代码技巧&#xff1f; 文章目录 你见过哪些令你膛目结舌的代码技巧&#xff1f;前言几种库bufio&#xff08;带缓冲的 I/O 操作&#xff09;特性示例 bytes (实现字节操作)特性示例 总结专栏集锦写在最后 前言 随着计算机科学的迅猛发展&#xff0c;编…

前端---vscode 的基本使用

1. vscode 的基本介绍 全拼是 Visual Studio Code (简称 VS Code) 是由微软研发的一款免费、开源的跨平台代码编辑器&#xff0c;目前是前端(网页)开发使用最多的一款软件开发工具。 2. vscode 的安装 下载网址: Download Visual Studio Code - Mac, Linux, Windows选择对应…

(企业 / 公司项目)如何使用分布式任务调度框架Quartz集成 和 SpringBoot自带的定时任务集成?

SpringBoot自带的定时任务 首先在你的微服务项目中创建一个新的模块&#xff0c;定时调度模块 pom.xml里面关联公共模块common的依赖其他不需要改变 然后启动类别删&#xff0c;启动项目是否报错&#xff0c;写一个简单的测试类访问路径是否成功 package com.jiawa.train.bat…

C语言:字符串字面量及其保存位置

相关阅读 C语言https://blog.csdn.net/weixin_45791458/category_12423166.html?spm1001.2014.3001.5482 虽然C语言中不存在字符串类型&#xff0c;但依然可以通过数组或指针的方式保存字符串&#xff0c;但字符串字面量却没有想象的这么简单&#xff0c;本文就将对此进行讨论…

【Linux】僵尸与孤儿 进程等待

目录 一&#xff0c;僵尸进程 1&#xff0c;僵尸进程 2&#xff0c;僵尸进程的危害 二&#xff0c;孤儿进程 1&#xff0c;孤儿进程 三&#xff0c;进程等待 1&#xff0c;进程等待的必要性 2&#xff0c;wait 方法 3&#xff0c;waitpid 方法 4&#xff0c;回收小结…

华为OD机试 - 学生方阵 - 矩阵(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出 四、解题思路1、题目解析2、解体思路 五、Java算法源码再重新读一遍题目&#xff0c;看看能否优化一下~ 六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导…

阶段十-物业项目

可能遇到的错误&#xff1a; 解决jdk17javax.xml.bind.DatatypeConverter错误 <!--解决jdk17javax.xml.bind.DatatypeConverter错误--><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>…

使用 fixture 机制重构 appium_helloworld

一、前置说明 在 pytest 基础讲解 章节,介绍了 pytest 的特性和基本用法,现在我们可以使用 pytest 的一些机制,来重构 appium_helloworld 。 appium_helloworld 链接: 编写第一个APP自动化脚本 appium_helloworld ,将脚本跑起来 代码目录结构: pytest.ini 设置: [pyt…

IntelliJ IDEA插件

插件安装目录&#xff1a;C:\Users\<username>\AppData\Roaming\JetBrains\IntelliJIdea2021.2\plugins aiXcoder Code Completer&#xff1a;代码补全 Bookmark-X&#xff1a;书签分类 使用方法&#xff1a;鼠标移动到某一行&#xff0c;按ALT SHIFT D