如何使用 Liquibase 避免搬起石頭砸自己的腳

它從未發生過,而且又來了!

在下一個項目中,我們決定從一開始就使用Liquibase,以避免將來出現問題。 事實證明,並非所有年輕的團隊成員都知道如何正確使用它。 我舉辦了一次內部研討會,然後我決定將其變成一篇文章。

本文包含有用的提示和對使用關係數據庫遷移工具(尤其是 Liquibase)時可能陷入的三個最明顯陷阱的描述。 專為初級和中級 Java 開發人員設計,對於經驗豐富的開發人員來說,構建和重複最有可能已知的內容可能會很有趣。

如何使用 Liquibase 避免搬起石頭砸自己的腳

Liquibase和Flyway是Java世界中解決關係結構版本控制問題的主要競爭技術。 第一個是完全免費的,在實踐中它更常被選擇使用,這就是 Liquibase 被選為該出版物的主角的原因。 但是,所描述的一些實踐可能是通用的,具體取決於應用程序的體系結構。

關係型遷移是解決關係型數據存儲靈活性弱的被迫方式。 在 OOP 盛行的時代,使用數據庫的風格意味著我們只需描述一次模式,就不再觸及它。 但現實情況總是發生變化,並且經常需要更改表的結構。 當然,這個過程本身是痛苦和不愉快的。

我不會深入研究技術的描述和將庫添加到項目中的說明,關於這個主題已經寫了足夠的文章:

此外,已經有一篇關於有用提示主題的精彩文章:

Советы

我想分享我的建議和評論,這些建議和評論是通過解決移民問題的汗水、鮮血和痛苦而誕生的。

1. 在開始之前,您應該閱讀以下最佳實踐部分 在線 液體鹼

那裡 描述了簡單但非常重要的事情,沒有這些,圖書館的使用會讓你的生活變得複雜。 例如,變更集管理的非結構化方法遲早會導致混亂和破壞的遷移。 如果不同時推出數據庫結構和服務邏輯中相互依賴的更改,那麼很有可能會導致紅測試或環境損壞。 另外,官網上的Liquibase使用建議中除了主要的遷移腳本之外,還有一段關於回滾腳本的開發和驗證的內容。 嗯,在文章中 https://habr.com/ru/post/178665/ 有與遷移和回滾機制相關的代碼示例。

2. 如果您開始使用遷移工具,請勿允許手動更正數據庫結構

俗話說:“一旦寶瑩,永遠寶瑩”。 如果應用程序的基礎已開始由 Liquibase 工具管理,則任何手動更改都會立即導致不一致的狀態,並且對變更集的信任級別變為零。 潛在風險 - 花費幾個小時來恢復數據庫,在最壞的情況下 - 服務器死機。 如果您的團隊有一位“老派”DBA 架構師,請耐心且深思熟慮地向他解釋,如果他只是通過條件 SQL Developer 以自己的方式編輯數據庫,事情將會多麼糟糕。

3.如果變更集已經推送到存儲庫,請避免編輯

如果另一個開發人員拉取並應用了稍後要編輯的變更集,那麼當他在應用程序啟動時收到錯誤時,他肯定會用友善的話語記住您。 如果編輯變更集以某種方式洩漏到開發中,您將不得不走下修補程序的滑坡。 問題的本質在於通過散列和驗證更改——這是 Liquibase 的主要機制。 編輯變更集代碼時,哈希和會發生變化。 僅當可以從頭開始部署整個數據庫而不丟失數據時,才可以編輯變更集。 在這種情況下,重構 SQL 或 XML 代碼反而可以讓生活變得更輕鬆,使遷移更具可讀性。 一個例子是,在應用程序啟動時,源數據庫的模式在團隊內進行協調。

4. 如果可能的話,驗證數據庫備份

我想,到這裡,一切就都清楚了。 如果突然遷移不成功,一切都可以退回來。 Liquibase有一個回滾工具,但回滾腳本也是由開發人員自己編寫的,它們可能與主變更集腳本中相同的概率出現問題。 這意味著在任何情況下,安全地進行備份都是有用的。

5. 如果可能,在開發中使用經過驗證的數據庫備份

如果這不違背合同和隱私,數據庫中沒有個人數據,它的重量也不像兩個太陽那麼重——在將其應用到實時遷移服務器上之前,您可以檢查它在開發人員的機器上如何工作併計算出幾乎100%遷移過程中的潛在問題。

6. 與團隊中的其他開發人員聊天

在組織良好的開發過程中,團隊中的每個人都知道誰在做什麼。 事實上,情況通常並非如此,因此,如果您準備更改數據庫結構作為任務的一部分,建議您額外通知整個團隊。 如果有人同時進行更改,您應該仔細組織。 即使在工作結束時也值得與同事溝通,而不僅僅是在開始時。 變更集的許多潛在問題可以在代碼審查階段得到解決。

7.想想你在做什麼!

看似不言而喻的建議適用於任何情況。 然而,如果開發人員再次分析他所做的事情以及可能產生的影響,許多問題是可以避免的。 處理遷移總是需要額外的關注和準確性。

陷阱

現在讓我們看看如果不遵循上述建議可能會陷入的典型陷阱,以及實際上應該做什麼?

情況 1. 兩個開發人員正在嘗試同時添加新的變更集

如何使用 Liquibase 避免搬起石頭砸自己的腳
Vasya 和 Petya 想要在彼此不知情的情況下創建版本 4 變更集。 他們對數據庫結構進行了更改,並使用不同的變更集文件推出了拉取請求。 下面提出以下機制:

如何決定

  1. 不知何故,同事們必須就他們的變更集的執行順序達成一致,假設應該首先應用 Petin。
  2. 一個人應該將另一個人倒入其中,並用版本 5 標記 Vasya 的變更集。這可以通過 Cherry Pick 或巧妙的合併來完成。
  3. 更改後,請務必檢查所採取操作的有效性。
    事實上,Liquibase 機制將允許您在存儲庫中擁有兩個版本 4 變更集,因此您可以保持一切不變。 也就是說,您將擁有版本 4 的兩個修訂版,但名稱不同。 通過這種方法,以後導航數據庫版本變得非常困難。

此外,Liquibase就像霍比特人的家園一樣,保守著很多秘密。 其中之一是 validCheckSum 鍵,它從 1.7 版本開始出現,允許您為特定變更集指定有效的哈希值,無論數據庫中存儲什麼。 文檔 https://www.liquibase.org/documentation/changeset.html 說如下:

添加一個被認為對此變更集有效的校驗和,無論數據庫中存儲了什麼。 主要在您需要更改變更集並且不希望在已運行變更集的數據庫上引發錯誤時使用(不是推薦的過程)

是的,不建議這樣做。 但有時候,強大的光系魔法師也掌握著暗系魔法。

案例2:數據驅動遷移

如何使用 Liquibase 避免搬起石頭砸自己的腳

假設您無法使用實時服務器的數據庫備份。 Petya 創建了一個變更集,在本地進行了測試,並完全相信自己是對的,向開發人員提出了拉取請求。 為了以防萬一,項目負責人澄清了Petya是否檢查過,然後倒了進去。 但是開發服務器上的部署已經下降了。

事實上,這是可能的,沒有人能倖免。 如果對錶結構的修改以某種方式與數據庫中的特定數據相關聯,就會發生這種情況。 顯然,如果Petya的數據庫只填充測試數據,那麼它可能無法覆蓋所有問題案例。 例如,當刪除一張表時,發現其他表中的記錄通過外鍵與被刪除的表中的記錄相關聯。 或者當更改列類型時,結果發現並不是100%的數據可以轉換為新類型。

如何決定

  • 編寫將在遷移時應用一次的特殊腳本,並將數據轉換為正確的形式。 這是解決應用遷移後將數據傳輸到新結構問題的通用方法,但在特殊情況下,之前也可以應用類似的方法。 當然,這條道路並不總是可行,因為在實時服務器上編輯數據可能是危險的,甚至是致命的。
  • 另一個棘手的方法是編輯現有的變更集。 困難在於,所有已經以現有形式應用該技術的數據庫都必須恢復。 整個後端團隊很可能被迫從頭開始本地匯總數據庫。
  • 最通用的方法是將數據問題轉移到開發人員的環境中,重新創建相同的情況並向損壞的變更集添加新的變更集,這將繞過該問題。
    如何使用 Liquibase 避免搬起石頭砸自己的腳

一般來說,數據庫的組成與生產服務器數據庫越相似,遷移問題出現嚴重問題的可能性就越小。 當然,在將變更集發送到存儲庫之前,您應該多次考慮它是否會破壞某些內容。

情況三、Liquibase投產後開始使用

假設團隊負責人要求 Petya 將 Liquibase 包含在項目中,但該項目已經投入生產,並且已經存在一個數據庫結構。

因此,問題在於,在任何新服務器或開發人員計算機上,必須從頭開始重新創建表數據,並且現有環境必須保持一致狀態,準備好接受新的變更集。

如何決定

還有幾種方法:

  • 第一個也是最明顯的是有一個單獨的腳本,在初始化新環境時必須手動應用該腳本。
  • 第二個不太明顯的方法是在不同的 Liquibase 上下文中進行 Liquibase 遷移並應用它。 您可以在此處閱讀有關 Liquibase Context 的更多信息: https://www.liquibase.org/documentation/contexts.html。 一般來說,這是一個有趣的機制,可以成功應用於例如測試。
  • 第三條路徑由幾個步驟組成。 首先,必須為現有表創建遷移。 然後必須將其應用於某個環境,從而獲得其哈希和。 下一步是在我們的非空服務器上初始化空 Liquibase 表,您可以手動將數據庫中已有更改的“如同已應用”變更集記錄放入具有應用變更集歷史記錄的表中。 因此,在現有服務器上,歷史記錄將從版本 2 開始,並且所有新環境都將表現相同。
    如何使用 Liquibase 避免搬起石頭砸自己的腳

場景 4:遷移規模巨大且無法跟上

在服務開發之初,通常使用 Liquibase 作為外部依賴項,所有遷移都在應用程序啟動時處理。 然而,隨著時間的推移,您可能會偶然發現以下情況:

  • 遷移變得巨大並且需要很長時間才能完成。
  • 需要在分佈式環境中進行遷移,例如同時在多個數據庫服務器實例上進行遷移。
    在這種情況下,應用遷移時間過長將導致應用程序啟動時超時。 此外,基於每個應用程序實例應用遷移可能會導致不同的服務器處於不同步狀態。

如何決定

在這種情況下,您的項目已經很大,甚至可能是一個成熟的項目,Liquibase 開始充當單獨的外部工具。 事實上,Liquibase 作為一個庫,被組裝成一個 jar 文件,並且可以作為項目內的依賴項工作,也可以獨立工作。

離線時,您可以將遷移應用程序留給 CI/CD 環境或系統管理員/部署人員來負責。 為此,您需要 Liquibase 命令行 https://www.liquibase.org/documentation/command_line.html。 在此模式下,可以在完成所有必要的遷移後啟動應用程序。

產量

事實上,在進行數據庫遷移時還有更多的陷阱,其中許多都需要創造性的方法。 重要的是要了解,如果正確使用該工具,那麼大多數陷阱都是可以避免的。 具體來說,我必鬚麵對以不同形式列出的所有問題,其中一些問題是我的門框造成的。 基本上,這種情況的發生當然是由於疏忽,但有時是由於犯罪分子無法使用該工具。

來源: www.habr.com

添加評論