Liquibase 应该处理并发初始化吗?

Should Liquibase cope with concurrent initialisation?

我正在运行同时针对一个干净的 HSQLDB 实例进行 Liquibase 迁移,虽然其中一个更新成功,但另一个失败:

Exception in thread "Thread-7" liquibase.exception.LockException: liquibase.exception.DatabaseException: object name already exists: DATABASECHANGELOGLOCK in statement [CREATE TABLE PUBLIC.DATABASECHANGELOGLOCK (ID INT NOT NULL, LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID))] [Failed SQL: CREATE TABLE PUBLIC.DATABASECHANGELOGLOCK (ID INT NOT NULL, LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID))]
    at liquibase.lockservice.StandardLockService.acquireLock(StandardLockService.java:216)
    at liquibase.lockservice.StandardLockService.waitForLock(StandardLockService.java:155)
    at liquibase.Liquibase.update(Liquibase.java:194)
    at liquibase.Liquibase.update(Liquibase.java:190)
    at liquibase.Liquibase.update(Liquibase.java:186)
    at liquibase.Liquibase.update(Liquibase.java:179)
Caused by: liquibase.exception.DatabaseException: object name already exists: DATABASECHANGELOGLOCK in statement [CREATE TABLE PUBLIC.DATABASECHANGELOGLOCK (ID INT NOT NULL, LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID))] [Failed SQL: CREATE TABLE PUBLIC.DATABASECHANGELOGLOCK (ID INT NOT NULL, LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID))]
    at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement(JdbcExecutor.java:316)
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:55)
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:122)
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:112)
    at liquibase.lockservice.StandardLockService.init(StandardLockService.java:87)
    at liquibase.lockservice.StandardLockService.acquireLock(StandardLockService.java:189)

这是预期的行为吗?使用 Liquibase 3.4.1.

(原因是它是一个自动测试,启动一个干净的环境,有两个应用程序节点以强制代码处理多个节点,我 运行 Liquibase 在应用程序节点启动时。)

感谢您指出问题。目标是同时安全 运行,如果 DATABASECHANGELOGLOCK table 存在应该很好,但是检查 table 是否存在和尝试创建它之间存在时间间隔如果时间只是 right/wrong.

,那不会导致您看到的错误

我创建了 https://liquibase.jira.com/browse/CORE-2596 来跟踪问题并添加了 3.4.2 的修复程序,这将使 Liquibase 从 "table already exists" 异常中恢复。这将避免您的问题,稍后插入 table 的代码才是分布式锁定的真正作用,因此您仍然可以避免并发更新。