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

2023年 8月 22日 41.3k 0

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

前言

  • 随着项目分支越来越多,对于年久失修的项目每一次的升级都是伤筋动骨的。因为年久失修的项目是很难准确描述出缺少的必要条件。比如说距离上次发布至今我们数据库发生的变动。我们在发布期间需要将这些变动的数据库更新上来才能保证新版本正常的运行。
  • 针对上面的数据库版本太老的原因,我们可以通过对比工具和新数据库进行对比生成差集 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

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论