目录
[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
<liquibase.version>3.6.3</liquibase.version>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>${liquibase.version}</version>
<configuration>
<!--引用配置文件-->
<propertyFile>${basedir}/src/main/resources/liquibase.properties</propertyFile>
</configuration>
</plugin>
上面配置文件的属性在哪里看呢? 请看下面
官方文档 -> documentation -> maven
传送门, 懒
虽然很有创造力. 但是告诉你进入路径也许比直接给你要更好
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>${liquibase.version}</version>
</dependency>
配置文件编写
属性编写来源:
官方文档 -> 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命令了:
image.png
结果:
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
...
到数据库中查看, 可以看到数据表以及数据已经被完整的迁移完成
后续待完善设计思考
- 后续会和SpringBoot项目进行完整的的结合, 预计为通过接口传入参数即可完成schema的创建. 并维护数据库连接信息.
- 业务项目初始化时通过接口来获取数据库连接信息
- 在业务项目中集成动态数据源模块. 由此来完成动态数据源的加载, 卸载, 以及访问数据库时的动态路由
-
给一张大致的设计图.
image.png
结语
目前项目刚开始, 我也是刚刚接到要做的任务. 所以先自己实践一下. 为后面的项目开发做好准备.
希望本文能简单的帮助到入坑同学. 若本文有误请帮忙指正.
愿我们越来越棒
本文为原创, 转赞请注明出处.
网友评论