Liquibase 数据库管理与迁移
·
关于数据库迁移
什么是数据库迁移
数据库迁移(Database Migration)是指对数据库结构进行版本控制的过程,它允许开发团队跟踪数据库模式的变更,并确保在不同环境(开发、测试、生产)中数据库结构的一致性。
为什么需要数据库迁移
在传统的软件开发中,数据库变更通常通过手动执行SQL脚本完成,这种方式存在诸多问题:
版本不一致:不同环境的数据库结构可能不一致
协作困难:多人开发时容易产生冲突
回滚复杂:出现问题时难以快速回滚到之前的版本
缺乏历史记录:无法追踪数据库结构的变更历史
Liquibase
Liquibase 是一个开源的数据库迁移工具,它通过 changelog 文件来管理数据库的变更,支持多种格式(XML、JSON、YAML、SQL)的变更定义,能够与多种数据库系统协同工作。
主要特性:
支持多种数据库(MySQL、PostgreSQL、Oracle等)
多种变更定义格式
回滚支持
与Spring Boot无缝集成
丰富的变更类型支持
Spring Boot 集成 Liquibase
添加依赖
首先,在 pom.xml 中添加 Liquibase 依赖:
<!-- Liquibase Database Migration -->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
Liquibase比起Flyway,对Springboot的支持更好。使用Springboot3也可以运行,Flyway则在Springboot3里面无法使用。
YML配置
# Liquibase Configuration
liquibase:
enabled: true
change-log: classpath:db/changelog/db.changelog-master.xml
drop-first: false
default-schema: mqtt
定义Liquibase的XML
创建主变更日志文件
在 src/main/resources/db/changelog 目录下创建主变更日志文件 db.changelog-master.yaml:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">
<!-- Include all changelog files -->
<include file="db/changelog/changes/v1.0-initial-schema.xml"/>
<include file="db/changelog/changes/v1.1-sample-data.xml"/>
</databaseChangeLog>
v1.0-initial-schema.xml 初始化数据库结构
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">
<!-- Create mqtt_connection table -->
<changeSet id="1" author="mqtt-websocket-bridge">
<createTable tableName="mqtt_connection" remarks="MQTT Connection Table">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="client_id" type="VARCHAR(255)" remarks="MQTT Client ID">
<constraints nullable="false" unique="true"/>
</column>
<column name="broker_url" type="VARCHAR(255)" remarks="MQTT Broker URL">
<constraints nullable="false"/>
</column>
<column name="username" type="VARCHAR(255)" remarks="Username"/>
<column name="password" type="VARCHAR(255)" remarks="Password"/>
<column name="keep_alive" type="INT" defaultValue="60" remarks="Keep Alive Interval (seconds)"/>
<column name="clean_session" type="TINYINT(1)" defaultValue="1" remarks="Clean Session Flag"/>
<column name="protocol_version" type="VARCHAR(50)" defaultValue="MQTT 3.1.1" remarks="Protocol Version"/>
<column name="tls_enabled" type="TINYINT(1)" defaultValue="0" remarks="TLS Enabled"/>
<column name="status" type="INT" defaultValue="0" remarks="Connection Status (0: disconnected, 1: connected)"/>
<column name="connected_at" type="DATETIME" remarks="Connection Timestamp"/>
<column name="disconnected_at" type="DATETIME" remarks="Disconnection Timestamp"/>
<column name="created_at" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP" remarks="Create Time"/>
<column name="updated_at" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" remarks="Update Time"/>
<column name="deleted" type="INT" defaultValue="0" remarks="Logical Delete Flag"/>
</createTable>
<!-- Create indexes for mqtt_connection -->
<createIndex indexName="idx_client_id" tableName="mqtt_connection">
<column name="client_id"/>
</createIndex>
<createIndex indexName="idx_status" tableName="mqtt_connection">
<column name="status"/>
</createIndex>
<createIndex indexName="idx_created_at" tableName="mqtt_connection">
<column name="created_at"/>
</createIndex>
</changeSet>
<!-- Create mqtt_subscription table -->
<changeSet id="2" author="mqtt-websocket-bridge">
<createTable tableName="mqtt_subscription" remarks="MQTT Subscription Table">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="client_id" type="VARCHAR(255)" remarks="MQTT Client ID">
<constraints nullable="false"/>
</column>
<column name="topic" type="VARCHAR(500)" remarks="MQTT Topic">
<constraints nullable="false"/>
</column>
<column name="qos" type="INT" defaultValue="0" remarks="Quality of Service (0, 1, 2)"/>
<column name="subscribed_at" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP" remarks="Subscription Timestamp"/>
<column name="created_at" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP" remarks="Create Time"/>
<column name="updated_at" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" remarks="Update Time"/>
<column name="deleted" type="INT" defaultValue="0" remarks="Logical Delete Flag"/>
</createTable>
<!-- Create indexes for mqtt_subscription -->
<createIndex indexName="idx_client_id" tableName="mqtt_subscription">
<column name="client_id"/>
</createIndex>
<createIndex indexName="idx_topic" tableName="mqtt_subscription">
<column name="topic"/>
</createIndex>
<createIndex indexName="idx_subscribed_at" tableName="mqtt_subscription">
<column name="subscribed_at"/>
</createIndex>
<!-- Create unique constraint -->
<addUniqueConstraint tableName="mqtt_subscription"
columnNames="client_id, topic"
constraintName="uk_client_topic"/>
</changeSet>
<!-- Create mqtt_message table -->
<changeSet id="3" author="mqtt-websocket-bridge">
<createTable tableName="mqtt_message" remarks="MQTT Message Table">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="client_id" type="VARCHAR(255)" remarks="MQTT Client ID">
<constraints nullable="false"/>
</column>
<column name="topic" type="VARCHAR(500)" remarks="MQTT Topic">
<constraints nullable="false"/>
</column>
<column name="payload" type="TEXT" remarks="Message Payload"/>
<column name="qos" type="INT" defaultValue="0" remarks="Quality of Service (0, 1, 2)"/>
<column name="retained" type="TINYINT(1)" defaultValue="0" remarks="Retained Message Flag"/>
<column name="direction" type="VARCHAR(50)" remarks="Message Direction (INBOUND, OUTBOUND)">
<constraints nullable="false"/>
</column>
<column name="created_at" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP" remarks="Create Time"/>
<column name="deleted" type="INT" defaultValue="0" remarks="Logical Delete Flag"/>
</createTable>
<!-- Create indexes for mqtt_message -->
<createIndex indexName="idx_client_id" tableName="mqtt_message">
<column name="client_id"/>
</createIndex>
<createIndex indexName="idx_topic" tableName="mqtt_message">
<column name="topic"/>
</createIndex>
<createIndex indexName="idx_direction" tableName="mqtt_message">
<column name="direction"/>
</createIndex>
<createIndex indexName="idx_created_at" tableName="mqtt_message">
<column name="created_at"/>
</createIndex>
</changeSet>
</databaseChangeLog>
v1.1-sample-data.xml 初始化数据
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">
<!-- Insert sample connection data -->
<changeSet id="4" author="mqtt-websocket-bridge">
<insert tableName="mqtt_connection">
<column name="client_id" value="emqx_NJEONID"/>
<column name="broker_url" value="tcp://localhost:1883"/>
<column name="username" value=""/>
<column name="password" value=""/>
<column name="keep_alive" valueNumeric="60"/>
<column name="clean_session" valueNumeric="1"/>
<column name="protocol_version" value="MQTT 5"/>
<column name="status" valueNumeric="0"/>
</insert>
</changeSet>
</databaseChangeLog>
更多推荐

所有评论(0)