Liquibase — ошибка в SYSTEM.DATABASECHANGELOGLOCK при повторном выполнении миграции

Я использую Liquibase 3.0.2, задачу Ant updateDatabase и наборы изменений, определенные непосредственно в сценариях SQL, используя такие комментарии, как

--liquibase formatted sql
--changeset com.noemalife:1 dbms:oracle

и т.п.

Первый запуск работает нормально, все наборы изменений выполняются и объекты БД (оракул) развертываются. Я вижу заполненные таблицы DATABASECHANGELOG и DATABASECHANGELOGLOCK.

Затем я пытаюсь повторно запустить задачу Ant с точно такой же конфигурацией, ожидая, что Liquibase скажет что-то вроде «Хорошо, все уже развернуто, здесь делать нечего».

Но вместо этого я получаю это:

C:\Users\dmusiani\Desktop\liquibase-test>ant migrate
Buildfile: build.xml

migrate:
     [copy] Copying 1 file to C:\Users\dmusiani\Desktop\liquibase-test

BUILD FAILED
liquibase.exception.LockException: liquibase.exception.DatabaseException: Error executing SQL CREATE
 TABLE SYSTEM.DATABASECHANGELOGLOCK (ID INTEGER NOT NULL, LOCKED NUMBER(1) NOT NULL, LOCKGRANTED TIM
ESTAMP, LOCKEDBY VARCHAR2(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID)); on jdbc:oracl
e:thin:@localhost:1521:WBMDINSERT INTO SYSTEM.DATABASECHANGELOGLOCK (ID, LOCKED) VALUES (1, 0): ORA-
00955: nome giÓ utilizzato da un oggetto esistente

        at liquibase.lockservice.LockServiceImpl.acquireLock(LockServiceImpl.java:122)
        at liquibase.lockservice.LockServiceImpl.waitForLock(LockServiceImpl.java:62)
        at liquibase.Liquibase.update(Liquibase.java:123)
        at liquibase.integration.ant.DatabaseUpdateTask.executeWithLiquibaseClassloader(DatabaseUpda
teTask.java:45)
        at liquibase.integration.ant.BaseLiquibaseTask.execute(BaseLiquibaseTask.java:70)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:357)
        at org.apache.tools.ant.Target.performTasks(Target.java:385)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
        at org.apache.tools.ant.Main.runBuild(Main.java:758)
        at org.apache.tools.ant.Main.startAnt(Main.java:217)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: liquibase.exception.DatabaseException: Error executing SQL CREATE TABLE SYSTEM.DATABASECH
ANGELOGLOCK (ID INTEGER NOT NULL, LOCKED NUMBER(1) NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR
2(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID)); on jdbc:oracle:thin:@localhost:1521:W
BMDINSERT INTO SYSTEM.DATABASECHANGELOGLOCK (ID, LOCKED) VALUES (1, 0): ORA-00955: nome giÓ utilizza
to da un oggetto esistente

        at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:56)
        at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:98)
        at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:64)
        at liquibase.database.AbstractJdbcDatabase.checkDatabaseChangeLogLockTable(AbstractJdbcDatab
ase.java:771)
        at liquibase.lockservice.LockServiceImpl.acquireLock(LockServiceImpl.java:95)
        ... 21 more
Caused by: java.sql.SQLException: ORA-00955: nome giÓ utilizzato da un oggetto esistente

        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:113)
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
        at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:754)
        at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210)
        at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:963)
        at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1192)
        at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1731)
        at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1701)
        at liquibase.executor.jvm.JdbcExecutor$1ExecuteStatementCallback.doInStatement(JdbcExecutor.
java:86)
        at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:49)
        ... 25 more

Total time: 1 second
C:\Users\dmusiani\Desktop\liquibase-test>

Мне кажется, что Liquibase пытается заново создать таблицу DATABASECHANGELOGLOCK.

У меня возникает эта проблема, когда я запускаю Liquibase с «системным» пользователем Oracle (мой патч заботится о создании пары других пользователей, поэтому в целях тестирования я использую для этого непосредственно систему). Другая странная вещь заключается в том, что после успешного запуска системного патча в таблице блокировок я все еще вижу, что блокировка активна. Когда я запускаю другие исправления в других схемах (например, созданные системным исправлением), у меня успешно завершается исправление и снимается блокировка в таблице блокировок; повторный запуск этого патча ведет себя так, как ожидалось: Liquibase обнаруживает, что патч уже установлен, и ничего не делает.

Тем не менее, теперь я сомневаюсь, что у Liquibase есть проблемы в системной схеме, при обнаружении таблицы блокировки уже существует (и не удается ее развернуть) или есть какая-то проблема с блокировкой/фиксацией.

Любое предложение приветствуется

Спасибо

Давиде


person Damus    schedule 19.07.2013    source источник
comment
Та же проблема здесь, с использованием плагина Maven.   -  person fbiville    schedule 29.07.2013
comment
Вам не следует никогда, никогда, ни при каких обстоятельствах создавать пользовательские таблицы в учетной записи SYSTEM, но я уже говорил вам об этом.   -  person a_horse_with_no_name    schedule 29.07.2013
comment
(в моем случае я не создаю там таблицы, я просто сбрасываю/создаю синонимы между другими схемами)   -  person fbiville    schedule 30.07.2013


Ответы (1)


Я столкнулся с той же проблемой, что и вы. Из того, что я вижу из источников, при работе от имени SYSTEM следующее условие (DatabaseSnapshot#include) оценивается как истинное .

    if (database.isSystemObject(example)) {
        return null;
    }

Из-за этого творение всегда будет предпринято. Я буду работать над патчем и держать вас в курсе.

А вот и предложение по исправлению.

person fbiville    schedule 29.07.2013
comment
Я видел предложение об изменении, я признаю, что я не опытный разработчик Java, но звучит неплохо. Но у меня есть одно сомнение: не рискованно ли жестко закодировать имя таблицы (искомая строка DATABASECHANGELOG)? Я думаю о параметрах ant updateDatabase, позволяющих изменить версию и заблокировать имена таблиц ... что произойдет, если кто-то захочет использовать другие имена таблиц? - person Damus; 30.07.2013
comment
Ах, хорошее место, мне, вероятно, все равно придется изменить свой PR, чтобы он прошел через основной источник. Я подожду, пока ребята из Liquibase тоже это проверят. - person fbiville; 30.07.2013
comment
Я закоммитил модифицированную версию запроса на вытягивание до версии 3.0.3, которая не жестко кодирует имя таблицы. Надеюсь выпустить 3.0.3 в начале следующей недели. - person Nathan Voxland; 31.07.2013