簡體   English   中英

liquibase 檢查變更集是否未被更改,但不檢查它們是否已被刪除:是否有解決此問題的設置?

[英]liquibase checks that changesets have not been changed, but doesn't check that they've not been removed: is there a setting to fix this?

Liquibase 在保持應用的變更集與其源文件夾一致方面做得非常好。
如果您修改已應用於數據庫的變更集,Liquibase 將拒絕執行任何操作,即使是與修改后的變更集無關的操作。
這里強制執行的規則是:任何已應用到數據庫的東西在更改之前都必須取消應用(這是開發過程中的常規工作流程)。

“孤立”變更集的問題

不幸的是,如果您只是完全刪除變更集,則此規則不適用。
在這種情況下,會有我所說的“孤立”變更集,即 DATABASECHANGELOG 表(當然還有數據庫 object)上的記錄,liquibase 根本不抱怨源中缺少變更集。
我預計至少當你“撞”到丟失的變更集時會出現錯誤,即當你試圖回滾它時,但 liquibase 似乎只是忽略它的存在,它跳過它並回滾下一個。 這可能是個問題。

問題是:我們可以通過設置改變這種 liquibase 行為嗎? 某些我沒有想到的用例是否需要這種設計?

我想我問的應該足夠清楚了,但是這里有一個例子作為演示。

例子

<databaseChangeLog ... >
        <include relativeToChangelogFile="true" file="CS1.sql"/>            
        <include relativeToChangelogFile="true" file="CS2.sql"/>    
</databaseChangeLog>

我的變更集是基於 SQL 的文件,如下所示:

-- liquibase formatted sql
-- changeset agostinox:-1
CREATE TABLE T1 (
    X INT
)
-- rollback DROP TABLE T1

而CS2.sql對於T2表也是一樣的。

現在我可以像這樣應用我的變更集:

PS > liquibase update
...
Liquibase Version: 4.19.0
Liquibase Open Source 4.19.0 by Liquibase
...
Running Changeset: CS1.sql::-1::agostinox
Running Changeset: CS2.sql::-1::agostinox
Liquibase command 'update' was executed successfully.

在我的數據庫中,DATABASECHANGELOG 具有以下內容:

ID 作者 文檔名稱 執行日期 已執行訂單 執行類型 MD5SUM
-1 阿羅替尼 CS1.sql 2023-01-18 18:52:08.476689 1個 已執行 8:d966f9ba2b90eaea9b917a6d93962eff
-1 阿羅替尼 CS2.sql 2023-01-18 18:52:08.666667 2個 已執行 8:7f2a735fa83b196a0c72885c95362b81

到目前為止,一切都很好。 現在,我進入正題了。

讓我們通過添加評論來弄亂 CS1.sql:

-- liquibase formatted sql
-- changeset agostinox:-1

CREATE TABLE T1 (
    X INT --Added comment, very harmless but enough to annoy liquibase :-)
)
-- rollback DROP TABLE T1

現在,我嘗試回滾最后一個變更集。

PS > liquibase rollbackcount 1
...
Unexpected error running Liquibase: Validation Failed:
    1 changesets check sum
        CS1.sql::-1::agostinox was: 8:d966f9ba2b90eaea9b917a6d93962eff but is now: 
8:2cea5484e81eb542fa94bb67ba2ffdf5

For more information, please use the --log-level flag

您可以看到 liquibase 抱怨 CS1.sql 已更改,即使我們甚至沒有回滾 CS1.sql 而是回滾 CS2.sql。 實際上,此更改會阻止任何進一步的操作,因此必須將其還原才能打破僵局。
但是,如果您只是刪除變更集,liquibase 就不會再抱怨了:

<databaseChangeLog ... >
        <!--REMOVED <include relativeToChangelogFile="true" file="CS1.sql"/> -->
        <include relativeToChangelogFile="true" file="CS2.sql"/>    
</databaseChangeLog>

PS > liquibase rollbackcount 1 
...
Rolling Back Changeset: CS2.sql::-1::agostinox
Liquibase command 'rollbackCount' was executed successfully.

但即使 liquibase 說一切都成功了,但事實並非如此,事實上,表 DATABASECHANGELOG 現在包含“孤立的”變更集(並且數據庫包含 T1 表,因為回滾代碼也消失了)。

ID 作者 文檔名稱 執行日期 已執行訂單 執行類型 MD5SUM
-1 阿羅替尼 CS1.sql 2023-01-18 18:52:08.476689 1個 已執行 8:d966f9ba2b90eaea9b917a6d93962eff

對於 db 人員,liquibase 似乎在變更集源文件夾和 DATABASECHANGELOG 中的記錄之間進行了左連接(即:左側集合中的所有項目都被獲取並與右側集合中的匹配項目相關聯); 這樣 liquibase 就可以看到應用的遷移並檢查它們的校驗和是否匹配。 它還可以看到尚未應用的遷移(源文件夾中的變更集沒有關聯的 DATABASECHANGELOG 記錄),以便在下一個“更新”調用中應用它們。 但它看不到來自 DATABASECHANGELOG(右集)的記錄,這些記錄在源文件夾中沒有關聯的變更集。 這種與 join 操作的並行很好地解釋了 liquibase 行為,所以讓我們用它來描述更好的行為可能是什么。

Liquibase 應該進行全連接,即:還考慮了右側沒有關聯源變更集的項目。 這些記錄表明異常可能只是您在校驗和不匹配時所擁有的異常的“主要版本”。 實際上,您可以很容易地將 null 文件視為校驗和的特殊情況,null 的校驗和必然與表中的不同。 因此,那些非關聯記錄的存在應該給出相同類型的錯誤。 這是我希望真正確保源和 DATABASECHANGELOG 之間的一致性。

我也一直很好奇這個。 我建議打開一個 github 問題,以便 Liquibase 員工可以解決他們為什么不進行此檢查的原因。 我猜這是故意的。

https://github.com/liquibase/liquibase/issues

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM