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.mzph.cn/news/240792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[node]node内置模块path

[node]node内置模块path 模块的导入路径值__filename__dirname path 方法path.resolve([from ...], to)path.parse()path.format()path.basename(path[, ext])path.extname(p)path.dirname(p)path.relative(from, to)path.normalize(p)path.isAbsolute(path)path.join([path1][…

css@media媒体查询

Media所有参数汇总 width:浏览器可视宽度。 height:浏览器可视高度。 device-width:设备屏幕的宽度。 device-height:设备屏幕的高度。 orientation:检测设备目前处于横向还是纵向状态。 aspect-ratio:检测浏览器可视宽度和高度的比例。(例如:aspect-ratio:16/9) de…

Java研学-Servlet 基础

一 概述 1 介绍 Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动…

会员管理怎么做?

会员管理是企业运营的重要组成部分,它涉及到会员的招募、维护、激励、保留、转化等多个环节。下面,我们将结合具体的案例,详细介绍会员管理的具体做法。 首先,会员的招募是会员管理的第一步 企业需要通过各种方式吸引消费者成为会…

3D数字化系统建设

以3D可视化、数字化技术为基础,其实,很多传统的系统软件都可以重新做一下。 比如:以下这个使用场景:零售门店陈列; 还有,数字化仓储系统,3D数字化供应链系统,3D数字化的生产系统&a…

redis常见数据类型

目录 1.基本全局命令 2.数据结构和内部编码 3.单线程架构 1.基本全局命令 Redis有5种数据结构,但它们都是键值对种的值,对于键来说有一些通用的命令。 KEYS 返回所有满足样式(pattern) 的key。支持如下统配样式。 h?llo 匹配 hello, hallo和hxllo h*llo匹配h…

Linux系统基础知识3

现在主要有以下几种Linux系统: Debian Gentoo Ubuntu Damn Vulnerable Linux 红帽企业级Linux CentOS Fedora Kali Linux Arch Linux 以下是以上Linux系统的特点: Debian:稳定性和安全性高,适用于生产环境和服务器等关键应用场景…

基于SpringBoot实现的前后端分离书店项目,功能:注册登录、浏览商品、热门商品、购物车、购买、地址管理、密码管理等

一、项目简介 本项目主要基于SpringBoot、Mybatis-plus、MySQL、Redis实现的书店管理系统。 本系统是前后端分离的,分别由三个子项目构成:java服务端、用户浏览与购买的前端、管理员管理商品的前端 环境 java 1.8mysql8.0redisvue2.x 管理员子系统功…

Ubuntu 常用命令之 ps 命令用法介绍

📑Linux/Ubuntu 常用命令归类整理 ps命令是Linux下的一个非常重要的命令,它用于查看系统中的进程状态。ps是Process Status的缩写,可以显示系统中当前运行的进程的状态。 以下是一些常用的参数 a:显示所有进程(包括…

textile 语法

1、文字修饰 修饰行内文字 字体样式textile 语法对应的 XHTML 语法实际显示效果加强*strong*<strong>strong</strong>strong强调_emphasis_<em>emphasis</em>emphasis加粗**bold**<b>bold</b>bold斜体__italics__<i>italics</i…

string的库函数reserve、resize

系列文章 http://t.csdnimg.cn/u80hL 目录 系列文章[TOC](目录) 一、reserve——请求容量的变化二、resize——操作对象使用的空间 一、reserve——请求容量的变化 改变对象的capacity——他会请求开辟和缩小对象所占的空间&#xff0c;reserve只能操作对象未使用的空间&…

通过bbeat播放器控制吉他效果器

在这个视频中&#xff0c;我们学习如何使用bbeat播放器来控制Fractal FXIII/FM3吉他效果器切换 有了bbeat&#xff0c;我们就可以播放伴奏和视频&#xff0c;控制 midi 设备&#xff0c;而无需在舞台上携带电脑和声卡。bbeat 可播放音频、midi、视频、图像和多轨文件。 它可读…

单例模式实现

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;JavaEE &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 单例模式 1. 什么是单例模式2. 饿汉模式3.…

C语言实现对数组去重算法详解

介绍 在编程中&#xff0c;经常会遇到需要对数组进行去重的情况&#xff0c;即去除数组中重复的元素&#xff0c;使得每个元素都是唯一的。本文将详细解释一个用于去重的C语言函数&#xff0c;并逐步解释其中的每一部分。 代码解析 下面是用于去重的C语言函数&#xff1a; …

C语言易错知识点九(指针(part three))

❀❀❀ 文章由不准备秃的大伟原创 ❀❀❀ ♪♪♪ 若有转载&#xff0c;请联系博主哦~ ♪♪♪ ❤❤❤ 致力学好编程的宝藏博主&#xff0c;代码兴国&#xff01;❤❤❤ 许久不见&#xff0c;甚是想念&#xff0c;本大忙人已经很久没有更新博客了&#xff0c;我想大概我的粉丝们早…

Linux的/proc/self/学习

文章目录 /proc目录/proc/self的使用 在做SSTI模板注入的CTF题中&#xff0c;发现有师傅提到可以用/proc/self这个目录获取flag&#xff0c;所以也来学习一波主要参考. (我才知道&#x1f601;&#x1f601;&#x1f601;)可以通过/proc/$pid/来获取指定进程的信息&#xff0c…

Kioptrix-3

靶场下载地址 https://download.vulnhub.com/kioptrix/KVM3.rar 信息收集 # Nmap 7.94 scan initiated Thu Dec 21 21:52:25 2023 as: nmap -sn -oN live.nmap 192.168.1.0/24 Nmap scan report for 192.168.1.1 (192.168.1.1) Host is up (0.00048s latency). MAC Address:…

[了解]DOS命令相对路径绝对路径

DOS: 磁盘操作系统 操作原理&#xff1a;在cmd控制台输入指令后--->交给DOS系统(接收\解析\执行)--->操作windows系统文件夹目录 dos指令: md d:\\temp md test100 test200 在d盘创建了一个文件夹目录叫temp。 在当前文件夹目录下创建了两个目录test100 test200。 r…

AI绘画中VAE压缩图像

介绍 在Stable Diffusion中,所有的去噪和加噪过程并非在图像空间直接进行,而是通过VAE模块将图像编码到一个低维空间。 这个低维空间的“分辨率”低于原始图像空间,有利于快速地完成加噪和去噪过程。 最后再将编码空间中的噪声表示解码恢复为图像空间,完成去噪或加噪操作。 …

【Element】el-table 使用 el-table-infinite-scroll 插件实现滚动加载

虽然 el 官方提供了 Infinite Scroll 无限滚动 组件 但是却不支持 el-table 组件&#xff0c;这就很难受了&#xff0c;还好已经有大佬写好了插件&#xff0c;并且支持 element-plus/infinite-scroll 组件的所有选项。 el-table-infinite-scroll el-table-infinite-scroll 看…