美文网首页
数据库脚本可重复执行的思考

数据库脚本可重复执行的思考

作者: 蓝胖子的白日梦丶 | 来源:发表于2019-07-31 16:02 被阅读0次

通常在项目升级迭代过程中会有许多操作数据库或是同项目发布需要执行的脚本,当一个全新的项目初始化部署时,可以不需要考虑脚本的重复执行问题,只需要初始脚本即可,但是随着不断的迭代,伴随着越来越多的脚本累积,就可能带来更多的问题数据,最终导致几个版本下来,预期的数据可能和我们的设想所不一致,或是因为脚本的重复执行,变更了(或是重新初始化)用户已经设定好的数据,这时候,脚本的可重复执行就尤为重要。

脚本重复执行需要考虑到的几个问题点:

  1. 多次执行是否会报错
  2. 多次执行是否会造成数据丢失/增加
  3. 多次执行是否会覆盖已有数据(初始化不需要考虑)

在迭代部署过程种常碰到的脚本类型

  • 新增表
  • 添加/修改字段
  • 修改字段名称
  • 修改字段类型
  • 新增字典类型数据
  • 新增配置类型数据

以下针对上述几点做实例演示

例表

CREATE TABLE `sys_parameter` (
    `param_code` varchar(64) NOT NULL COMMENT  '参数代码',
    `param_value` varchar(64) NOT NULL COMMENT  '参数内容',
    PRIMARY KEY (`param_code`)
)

新增数据表

在新增数据表时,经常在create之前习惯加上:

DROP TABLE IF EXISTS `sys_parameter`;

语意很简单,如果表存在,那么就删掉。但是如果是迭代版本中仍然执行了此脚本,那么会造成什么问题?
也许这个表用户已经使用,并且存在了大量的数据,那么这句话将直接导致数据被清空,造成严重损失。
在新增表的时候,应当是表存在那么就不可以再次新建,可以使用类似以下脚本:

CREATE TABLE IF NOT EXISTS `sys_parameter` (
    `param_code` varchar(64) NOT NULL COMMENT  '参数代码',
    `param_value` varchar(64) NOT NULL COMMENT  '参数内容',
    PRIMARY KEY (`param_code`)
)

区别在于create时判断表是否已经存在,如果存在就不再创建

添加修改字段

添加及修改字段同样都需要判断字段是否已存在或是已经被修改过了,不加以判断,则会执行报错,可以写一个简单的存储过程:

DROP PROCEDURE IF EXISTS alter_sys_parameter;
delimiter $$
CREATE PROCEDURE alter_sys_parameter()
BEGIN
    SELECT (SELECT DATABASE()) INTO @databaseName;
    IF EXISTS (
            SELECT 1 FROM information_schema.TABLES
            WHERE TABLE_SCHEMA = @databaseName
            AND TABLE_NAME = `sys_parameter`
        )  AND NOT EXISTS (
            SELECT 1 FROM information_schema.COLUMNS
            WHERE TABLE_SCHEMA = @databaseName
            AND TABLE_NAME = `sys_parameter`
            AND COLUMN_NAME = `param_code`
        ) THEN
    ALTER TABLE  sys_parameter ADD COLUMN `param_code` varchar(64) NOT NULL COMMENT '参数代码';
    END IF;
END $$
delimiter;
CELL alter_sys_parameter();
DROP PROCEDURE IF EXISTS alter_sys_parameter;

存储过程的主要用途在于判断表和字段是否已经存在,字段不存在的情况下进行add

修改字段名称和修改字段类型

两者同属于对某一个字段进行操作,处理方式类似

DROP PROCEDURE IF EXISTS alter_sys_parameter;
delimiter $$
CREATE PROCEDURE alter_sys_parameter()
BEGIN
    SELECT (SELECT DATABASE()) INTO @databaseName;
    IF EXISTS (
            SELECT 1 FROM information_schema.COLUMNS
            WHERE TABLE_SCHEMA = @databaseName
            AND TABLE_NAME = `sys_parameter`
            AND COLUMN_NAME = `param_code_up`
        ) THEN
    ALTER TABLE  sys_parameter MODIFY COLUMN `param_code_up` varchar(64) NOT NULL COMMENT '参数代码';
    END IF;
END $$
delimiter;
CELL alter_sys_parameter();
DROP PROCEDURE IF EXISTS alter_sys_parameter;

处理方式相对简单,修改字段名需要判断新的字段名是否存在,而修改字段类型或是其他只需要判断当前字段是否存在

新增字典类型数据

字典类型的数据相对来说较为稳定,基本设定一次不会发生变化,处理方式也相对简单

DELETE FROM sys_parameter WHERE param_code = 'test_code';
INSERT INTO sys_parameter (param_code, param_value) VALUES ('test_code', 'test_value');

删除重新插入即可

新增配置类型数据

配置类型数据和字段类似,不同点在于配置内容会交由用户自己更改,这时候再采用字典的处理方式,就会将用户设置的内容覆盖,严重的甚至会发生“生产事故”
处理方式需要变通一下,但是万变不离其宗,如果数据存在,则不修改

INSERT INTO sys_parameter (param_code, param_value) 
  SELECT  'test_code', 'test_value'  WHERE NOT EXISTS (
    SELECT 1 FROM sys_parameter WHERE param_code = 'test_code' AND param_value= 'test_value');

将需要插入的值作为select查询出来,在查询的时候做判断,如果存在就不会再次插入了

多脚本执行前后的重复数据

通过以上方式添加新的配置参数,当后续的脚本修改对应数据的param_code之后,再次执行插入语句仍然会正常执行,那么继续执行后续修改脚本同样修改param_code,如果param_code字段为主键,那么将会报错,这样即使一个脚本完成了可重复执行,但是不能避免多脚本重复执行造成不必要的麻烦

INSERT INTO sys_parameter (param_code, param_value) 
  SELECT  'test_code', 'test_value'  WHERE NOT EXISTS (
    SELECT 1 FROM sys_parameter WHERE param_code = 'test_code' AND param_value= 'test_value');
UPDATE sys_parameter SET param_code="test_value_tmpl" WHERE param_code="test_value";

上述两句重复执行将会报错,主键冲突

更正方法,在修改数据之前确认一下是否库里同时含有param_code="test_value_tmpl" 和param_code="test_value"的数据,如果同时存在则删除param_code="test_value"的数据

DELETE p1 FROM sys_parameter p1 
LEFT JOIN sys_parameter p2 
ON P1.module_code = p2.module_code 
WHERE p1.param_code="test_value" AND p2.param_code="test_value_tmpl";

相关文章

  • 数据库脚本可重复执行的思考

    通常在项目升级迭代过程中会有许多操作数据库或是同项目发布需要执行的脚本,当一个全新的项目初始化部署时,可以不需要考...

  • iOS自动化打包脚本

    iOS打包的时候需要每次手动点击xcode进行打包,繁琐与重复的步骤。但幸运的是通过shell脚本可以自动执行...

  • 一文教你快速理解 MySQL 事务隔离级别

    当数据库上有多个事务同时执行的时候,就可能出现问题: 脏读(dirty read) 不可重复读(non-repea...

  • 思考、执行与反思

    思考后去执行,执行后要学会总结。在不断重复的日子里慢慢对自己产生新的认知,逐渐了解自己。 思想就像是飘在天空中的云...

  • 高手的自我修养

    在我眼里,所谓执行力差的表现,就是事情重复的次数不够。执行力强的人,就是把需要理性思维思考的问题,通过直觉就能够做...

  • 三、事务隔离:为什么你改了我还看不见

    老生常谈的问题,当数据库上有多个事务同时执行的时候,就可能出现脏读(dirty read)、不可重复读(non-r...

  • 10、循环

    程序由算法加数据构成 算法流程:顺序执行,重复执行,选择执行 顺序执行:从上而下一步步执行 重复执行:while循...

  • 2020-03-29 16:55 配置数据库连接复原(执行策略)

    提纲 设置失败重试(自动重试失败的数据库命令) 自定义执行策略 使用执行策略执行数据库操作 在配置数据库类型\数据...

  • Excel数据导入到SQLServer

    一、准备工作,Excel数据表,sql导入数据脚本文件; 二、双击脚本文件,在本地数据库中打开,执行; 三、生成脚...

  • 12.1KOA mysql 数据库

    mysql 数据库 安装 mysql 模块 使用数据库连接执行 SQL 语句 使用数据库连接池执行 SQL 语句

网友评论

      本文标题:数据库脚本可重复执行的思考

      本文链接:https://www.haomeiwen.com/subject/stttdctx.html