多个项目平替升级表结构不统一咋办?数据库mysql幂等性终结

本本分分做人,踏踏实实做事!!!

前言

  • 随着项目分支越来越多,对于年久失修的项目每一次的升级都是伤筋动骨的。因为年久失修的项目是很难准确描述出缺少的必要条件。比如说距离上次发布至今我们数据库发生的变动。我们在发布期间需要将这些变动的数据库更新上来才能保证新版本正常的运行。
  • 针对上面的数据库版本太老的原因,我们可以通过对比工具和新数据库进行对比生成差集 sql 。然后我们将这个 sql 到就数据库上执行一遍就行了。但是这个过程还是有缺陷的,比对的过程需要我们认为参与,且针对非必填字段改为必填字段就很难解决。
  • liqui-base 是一个对数据库进行版本管理的一个框架。我们通过 liqui-base 能够将我们数据库的变更进行记录下来。你可以简单理解我们准备了一份基础数据。随着项目不断的迭代,我们将每次迭代的 sql 文件本地化存储下来。然后 liqui-base 将每个本地化文件进行 MD5 加密。每次通过 MD5 进行确认是否执行过该迭代版本。这样就能够保证数据库的最新。该功能我们只需要保证我们每次提供的 sql 的正确性。
  • 今天我们针对 sql 来展开谈谈如何保证 sql 的正确性。

场景

  • liqui-base 技术已经很成熟了,理论上我们只需要提供正确的 sql 即可。但是因为我们公司的独特性,导致 liqui-base 无法正确的执行,某种场景下会发生 1 个 sql 重复执行。虽然重复执行问题不大,但是部分 sql 是无法忍受的。
  • sql 文件中存在 insert ,重复执行就会导致数据 Double (假设没有触发唯一建约束!)。
  • 这个肯定是我们改造 liqui-base 导致的,我们后续也修复了。但是今天我想讲的不是修复的问题,而是如何保证我们提供的 sql 的幂等性!!!

具体案例

data 幂等

  • 现在我们有一张 business 表。迭代的 sql 中需要向这张表中添加一份数据。
CREATE TABLE nanshan.business (
	id INT auto_increment NOT NULL COMMENT '主键',
	name varchar(100) NULL COMMENT '名称',
	CONSTRAINT main_pk PRIMARY KEY (id)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci
COMMENT='业务名称';

insert business(name) values('zxhtom');
  • 这种情况我每执行一次就会生成一个 name=zxhtom 的数据。虽说 name 字段设计的本身可以重复,但是 insert 作为基础数据因为重复执行导致数据重复了,总感觉是乖乖的。
  • 经过一番摸索,我发现可以借助 existsl 关键字来实现判断是否 INSERT
insert business(name) select 'zxhtom' from dual where not exists (select 1 from business where name='zxhtom');

20230517-145434635.png

  • 通过上面截图我们也能够发现第一次插入 zxhtom 数据后,第二次插入也成功了但是影响的是 0rows . 说明 mysql 已经成功执行了这条 sql。但是这条 sql 并没有产生任何数据。
  • 这样就保证了该 sql 的幂等性。

DDL 幂等

  • 迭代过程提供的 sql 很大可能都是 DDL 的修改。INSERT 反而是很少的情况。那么关于 DDL 我们如何实现幂等呢?
  • 首先就是我们建表语句。
create table test01(id int , name varchar(255))

20230517-152746850.png

  • 建表是我们通过 NOT EXISTS 关键字判断。但是在新增或者修改字段是好想无法使用这个关键字。

20230517-153328693.png

  • 为了能够实现和建表相同的逻辑。我们这里接住存储过程来解决这个问题。
DROP PROCEDURE IF EXISTS proc_tempPro;
delimiter ;;
CREATE PROCEDURE proc_tempPro()
BEGIN
SELECT count(*) into @count FROM INFORMATION_SCHEMA.Columns 
WHERE table_schema= DATABASE() AND table_name="t_assets" AND column_name="repository_id4";
if(@count=0) THEN
 ALTER TABLE t_assets add repository_id4 VARCHAR(255)  NULL COMMENT '所属仓库';
end if;
end;;
delimiter ;
call proc_tempPro;
DROP PROCEDURE IF EXISTS proc_tempPro;
  • 这样编写我们的 sql 就能保证幂等性了。再也不怕重复执行了。

总结

  • 幂等性对于开发程序来说还是很重要的。因为客户很有可能因为客户端卡顿不停的点击。或者因为客户端的 BUG 导致不停的重复调用接口。再或者别人恶意攻击我们。这个时候幂等性就尤其重要。本文主要介绍了 sql 的幂等性。后面我们在了解下接口如何实现幂等性。

放松一刻

It is not fair to ask of others what you are unwilling to do yourself. — Eleanor Roosevelt

photo by Halley Tian on Unsplash

全部评论

相关推荐

xdm 早上喝奶茶差点喷出来。事情是这样的,我们班有个哥们儿,简称 L,去年秋招拿了字节sp,专业方向是后端。我们当时都震惊:这哥们儿平时课上从来不发言,期末小组作业基本是划水的那种,刷题平台 commit记录我点进去看过,绿格子稀稀拉拉。但他面试一路绿灯。一面二面三面 hr 面,全过,给的还是sp。当时班级群里恭喜他的、问他经验的、约饭的,热闹了一周。他说自己"运气好,准备充分"。我们都信了,直到三月初他入职。入职第二周开始,班里另一个进字节的同学W(在隔壁组的)开始跟我他的不对劲。一开始是写代码慢,后来写不出来,再后来是组里 mentor 让他fix 一个简单 bug 都搞了一下午没动静。最离谱的是上周。W 说他们大部门搞了个新人分享会,让新人讲一下自己负责模块的设计思路。L 上去讲了 20分钟,全程念稿子,问答环节别人随便问一个"那你这里为什么用 Redis 不用 Memcached",他直接卡 30秒说"这个我回去再确认一下"。会后他 mentor 直接找 leader 谈,leader 找 hr 谈,hr调出了他面试录像,全程对比口型和回答节奏,发现他二三面有大量时长在偷偷看屏幕外(推测开了双机位 AI 答题)。(这段是 W后来转述给我的,他自己也是听他组里同事八卦来的)昨天下班前,W 告诉我L 被辞退了,让他自己走,不走就走仲裁但会发函到学校。L 现在已经回学校了,朋友圈仅三天可见。我说真的,我不是个心眼小的人,但是我看到这个消息的时候真的有种"嗯,挺好"的感觉。去年秋招我投字节后端,简历挂。我准备了八个月,背 八股 + 刷 500 题 +项目改了三版,连面试机会都没拿到。班里这哥们儿凭着一个外挂上岸,最后还是被甩出来了。不是说作弊就一定会被发现,但是当面试拿到的 offer远远超出真实能力的时候,迟早会有这一天。试用期三个月不是给你过家家的,是真的要写代码、要在会议上回答问题、要扛需求的。我现在反而有点同情他。同情他相信"上岸就是终点"。发出来不是为了嘲笑谁,就是想说给那些正在被身边作弊上岸的同学搞得很 emo 的 uu 们听——别急,回旋镖很长,但它一定会回来。你继续刷你的题,写你的项目,背你的八股。该是你的迟早是你的,不是你的早晚还得还回去。xdm 共勉。
牛客12588360...:我不想评论面试方式,作弊是绝对不对的,但是你八股加刷题也不过是个做题小子,他穿帮纯粹是他菜,你也没有高明到哪里去
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务