数据库物理隔离 (schema级别) 之 Liquibase入门实践

目录

[toc]

背景

由于SaaS项目需要提供多租户之间物理隔离的数据库实现方案, 为了标准化操作, 所以采用了Liquibase这样一款数据库同步备份工具, 从一个模板文件中动态的在一个新schema中创建与模板库中相同的表结构以及数据的初始化操作


思考

  • 如何有效的管理schema与数据库账户, 特别是防止数据泄露?
  • 如何在服务运行期间卸载和装载数据源?
  • 如何在项目中有效的完成动态数据源功能, 数据源加载太多是否有坑?

实践

前言: 我也是首次使用Liquibase, 如果有使用不对的地方还请留言指正, 网络上能参考的文章实在有限, 我也是问了之前实践过的同事, 才慢慢整理出一个使用实践. 记录一下为了以防自己在将来忘记的时候可以回过来看看, 另外也希望能帮助到新入坑的小伙伴


官方文档

官方文档
在看官方文档的时候也有很多不明白的地方, 都是一点一点慢慢摸索过来的


项目选型

  • JDK8
  • SpringBoot
  • Bootstrap
  • mysql

Maven依赖与pom配置

由于我的目标是完成一个web项目, 所以我的pom文件里面至少会引入如下几个依赖 (由于直接贴全部pom内容太长. 为了不影响阅读, 我只贴出关键的几个依赖):

  • druid
  • mysql-connector-java
  • spring-boot-starter-web
  • mybatis-plus
  • guava
3.6.3

    org.liquibase
    liquibase-maven-plugin
    ${liquibase.version}
    
        
        ${basedir}/src/main/resources/liquibase.properties
    

上面配置文件的属性在哪里看呢? 请看下面
官方文档 -> documentation -> maven
传送门, 虽然很有创造力. 但是告诉你进入路径也许比直接给你要更好


    org.liquibase
    liquibase-core
    ${liquibase.version}


配置文件编写

属性编写来源:
官方文档 -> documentation -> maven -> liquibase:generateChangeLog
传送门

outputChangeLogFile=src/main/resources/changeLog.xml
url=jdbc:mysql://host:port/schema?useUnicode=true&characterEncoding=UTF-8&useSSL=true
driver=com.mysql.jdbc.Driver
username=root
password=root
# 默认没有最后的data, 看需求, 我们需要导出默认数据, 如果仅仅要表结构, 注释掉即可
diffTypes=tables,views,columns,indexes,foreignkeys,primarykeys,uniqueconstraints,data
# 输出默认的schema名称关闭掉
outputDefaultCatalog=false

mvn命令生成changeLog

一般我们都是用IDEA, 所以我就直接从idea中执行mvn命令了:


数据库物理隔离 (schema级别) 之 Liquibase入门实践_第1张图片
image.png

结果:


数据库物理隔离 (schema级别) 之 Liquibase入门实践_第2张图片
image.png

在代码中完成changeLog.xml的使用

如果不是必要, 改一下配置文件, 使用update命令即可. 但是为了演示一下项目中的使用方法. 所以在写一个简单的Demo参考:

public static void main(String[] args) throws Exception {
        ClassLoaderResourceAccessor classLoaderResourceAccessor = new ClassLoaderResourceAccessor(MainClass.class.getClassLoader());
        String changeLogFilePath = "changeLog.xml";
        String username = "root";
        String password = "root";
        String url = "jdbc:mysql://host:port/schema?useUnicode=true&characterEncoding=UTF-8&useSSL=true";
        Properties properties = new Properties();
        properties.setProperty("username", username);
        properties.setProperty("password", password);
        properties.setProperty("url", url);
        Connection connection = DruidDataSourceFactory.createDataSource(properties).getConnection();
        JdbcConnection jdbcConnection = new JdbcConnection(connection);
        Liquibase liquibase = new Liquibase(changeLogFilePath, classLoaderResourceAccessor, jdbcConnection);
        liquibase.update(new Contexts());
    }

执行结果:

...
02:20:30.747 [main] INFO liquibase.executor.jvm.JdbcExecutor - INSERT INTO pw_test.DATABASECHANGELOG (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, `DESCRIPTION`, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE, DEPLOYMENT_ID) VALUES ('1573236305687-36', 'wuyujia (generated)', 'changeLog.xml', NOW(), 36, '8:c810b4f042f26f841b90130d43f54642', 'createIndex indexName=idx_user_id, tableName=t_task', '', 'EXECUTED', NULL, NULL, '3.6.3', '3237223574')
02:20:30.765 [main] DEBUG liquibase.executor.jvm.JdbcExecutor - 1 row(s) affected
02:20:30.785 [main] DEBUG liquibase.executor.jvm.JdbcExecutor - Release Database Lock
02:20:30.791 [main] DEBUG liquibase.executor.jvm.JdbcExecutor - UPDATE pw_test.DATABASECHANGELOGLOCK SET `LOCKED` = 0, LOCKEDBY = NULL, LOCKGRANTED = NULL WHERE ID = 1
02:20:30.823 [main] INFO liquibase.lockservice.StandardLockService - Successfully released change log lock
...

到数据库中查看, 可以看到数据表以及数据已经被完整的迁移完成


后续待完善设计思考

  1. 后续会和SpringBoot项目进行完整的的结合, 预计为通过接口传入参数即可完成schema的创建. 并维护数据库连接信息.
  2. 业务项目初始化时通过接口来获取数据库连接信息
  3. 在业务项目中集成动态数据源模块. 由此来完成动态数据源的加载, 卸载, 以及访问数据库时的动态路由
  4. 给一张大致的设计图.


    数据库物理隔离 (schema级别) 之 Liquibase入门实践_第3张图片
    image.png

结语

目前项目刚开始, 我也是刚刚接到要做的任务. 所以先自己实践一下. 为后面的项目开发做好准备.
希望本文能简单的帮助到入坑同学. 若本文有误请帮忙指正.
愿我们越来越棒
本文为原创, 转赞请注明出处.

你可能感兴趣的:(数据库物理隔离 (schema级别) 之 Liquibase入门实践)