zoukankan      html  css  js  c++  java
  • 自动化数据库更新

    简介

    在我们的开发和运维过程中,通常会维护不同的数据库。由于在某个时间点,各个数据库的结构和状态是不一样的,所以我们开发人员需要在不同的数据库中运行相同的数据库脚本(SQL),比如我们修改了某个字段的长度并编写了一段SQL语句,我们需要在开发数据库、测试数据库、客户测试数据库、生产数据库中运行这段相同的SQL脚本。重复的工作不仅增加我们的工作量同时还增加我们出错的机会。

    为了让我们的工作更加轻松,我们需要通过某种自动化的手段来解决这个问题。本文就我在工作中的做法进行阐述。

    解决方案

    自动化编译服务器+自动化数据库脚本。 在这种方案下,每个数据库都知道它自己已经运行了什么样的数据库脚本。通过在数据库中维护表DB_SCRIPT来解决,如下面表所示

    SQL> desc DB_SCRIPT;
    Name     Type          Nullable Default Comments 
    -------- ------------- -------- ------- -------- 
    ID       NUMBER(9)                               
    EXE_DATE DATE          Y        sysdate          
    VERSION  VARCHAR2(20)  Y                         
    REMARK   VARCHAR2(800) Y   

    在build-all工程里,我们按照日期加编号的形式添加数据库脚本。

    QQ截图未命名2

    然后DbScript.groovy将查询数据库,根据当前数据库所运行的SQL语句来决定在build-all功能中哪些数据库SQL语句应该运行。具体的Groovy脚本请看下节。

    QQ截图未命名

    Groovy脚本
    import groovy.sql.*;
    
    def sql = Sql.newInstance("jdbc:oracle:thin:@192.168.141.128:1521:orcl", "root",
    
    "111111", "oracle.jdbc.driver.OracleDriver")
    
    sql.withTransaction { 
    
    	def createDBScriptTableClosure = {
    
    		row -> 
    
    		if (row[0] == 0){
    
    			//如果找不到表'DB_SCRIPT', 那么就建立一个表
    
    			println '数据库没有表DB_SCRIPT, 现在建立一个表' 
    
    			def createSeq = "CREATE SEQUENCE DB_SCRIPTSEQ INCREMENT BY 1 START WITH 1 MAXVALUE 99999"
    
    			sql.execute createSeq
    
    			def creatTableSql = "create table DB_SCRIPT(ID number(9) primary key not null, EXE_DATE date default sysdate, VERSION varchar2(20), REMARK varchar2(800))";
    
    			sql.execute creatTableSql
    
    		}
    
    	}
    
    	sql.eachRow("select count(*) from tab where tname ='DB_SCRIPT'", createDBScriptTableClosure)
    
    }
    
    //最后执行的SQL语句
    
    def lastExecutedSql
    
    sql.withTransaction {
    
    	def firstRow = sql.firstRow("SELECT VERSION FROM DB_SCRIPT WHERE ID = (SELECT MAX(ID) FROM DB_SCRIPT)")
    
    	
    
    	if (firstRow !=null ){
    
    		lastExecutedSql = firstRow.getAt(0)
    
    	}
    
    }
    
    //把dbscript目录中的脚本缓存起来下来
    
    def scripts = [:]
    
    def maxFile = ''
    
    Thread.currentThread().getContextClassLoader().getResource("").each {
    
    	it ->  
    
    	new File(it.getPath()+"\\dbscript").eachFile { 
    
    		//把所有SQL文件放到MAP中
    
    		file -> 
    
    		def currentFileName = file.getName()
    
    		scripts.put currentFileName, file
    
    		if (currentFileName > maxFile){
    
    			maxFile = currentFileName
    
    		}
    
    	}
    
    }
    
    def insertSql = "INSERT INTO DB_SCRIPT(ID, VERSION, REMARK) values(DB_SCRIPTSEQ.NEXTVAL, ?, ?)"
    
    def keys = scripts.keySet().sort()
    
    def sqlExecutionClosure = {
    
    	key -> 
    
    	println key
    
    	def sqlFile = scripts.get(key)
    
    	def sqlCommand = sqlFile.text
    
    	def sqlCds = sqlCommand.split(';')
    
    	sqlCds.each {
    
    		sqlCd ->
    
    		println 'executing ' + sqlCd
    
    		sql.execute sqlCd
    
    	}						
    
    	sql.execute insertSql, [key, sqlCommand]
    
    }
    
    //如果还没有语句执行
    
    sql.withTransaction{
    
    	if (lastExecutedSql == null) {
    
    		println '在这个数据库中还没有任何数据库补丁脚本运行,将依次运行如下脚本'
    
    		keys.each {
    
    			key -> 
    
    			sqlExecutionClosure(key)
    
    		}
    
    	}else{
    
    		keys.each {
    
    			key ->
    
    			println lastExecutedSql
    
    			if (key > lastExecutedSql){
    
    				sqlExecutionClosure(key)
    
    			}
    
    		}
    
    	}
    
    }
  • 相关阅读:
    应用系统数据缓存设计
    解密SVM系列(二):SVM的理论基础(转载)
    机器学习6—SVM学习笔记
    机器学习5—logistic回归学习笔记
    Win7 64bit+Anaconda(3-5.0.1,Python3.6)+Pycharm(community-2017.3.3)+OpenCV(python‑3.4.0‑cp36‑cp36m)(转载)
    AI关注的网址
    机器学习4—朴素贝叶斯学习笔记
    机器学习3—决策树学习笔记
    机器学习2—K近邻算法学习笔记
    windows_64下python下载安装Numpy、Scipy、matplotlib模块
  • 原文地址:https://www.cnblogs.com/cando/p/2393659.html
Copyright © 2011-2022 走看看