使用 Skeema 進行模式管理

已發表: 2019-04-26

注意:這篇文章來自 SendGrid 的工程團隊。 如需更多類似的技術工程帖子,請查看我們的技術博客。

數據庫模式管理範圍從任何人都可以在生產過程中“現場實施”的狂野西部到瀑布式的多步驟、多團隊審查過程,其中只有一個受膏的個人可以接觸生產數據庫。

隨著關係數據庫中包含的數據對公司變得更有價值,並且數據庫的可用性對業務變得更加重要,潛在的破壞性模式更改的障礙就會出現。

早期,數據庫管理員 (DBA) 成為數據庫的看門人,以保護數據庫免受不良事件的影響。 但是,在開發人員和他們的應用程序數據庫之間有一個老式的 DBA 會導致應用程序的開發生命週期顯著放緩,造成開發和運營的孤島,並在團隊之間產生摩擦。

在當今面向微服務開發運維的世界中,開發人員需要能夠自行管理數據庫模式更改,因為這是他們的數據,並且他們最終對應用程序的性能和正常運行時間負責。 DBA 和運營團隊需要提供適當的工具和建議,以幫助開發團隊成為其數據庫的所有者。

我們如何管理架構

我們當前的模式管理流程使用單個 Git 存儲庫來存儲我們所有數據庫集群的初始模式,並包含在應用單個表更改/創建和刪除時對該模式的所有後續更改:

  • 開發人員在本地進行模式更改並生成更改/創建/刪除語句並將其作為拉取請求添加到集成分支。
  • 為數據運營團隊創建了一組 Jira 票證,以審查架構更改並將其應用於我們的測試/登台和生產環境。
  • 數據運營團隊的成員審查請求的更改並將更改應用到測試/登台環境並將 PR 合併到集成分支。
  • 請求開發人員在我們的測試/暫存環境中測試更改並批准將更改推送到生產環境。
  • 最後,Data Operations 將集成分支合併到 master 並將架構更改應用到生產環境。

鑑於存儲在我們數據庫中的數據的價值以及讓這些數據庫始終正常運行的願望,我們決定採用這種拜占庭式的事件序列來保護自己免受自己的傷害。

保護數據庫是一回事,但這個過程引入了幾個障礙,以可靠和有效的方式進行模式更改:

  • 每週兩次審查和進行架構更改,並且很容易脫軌,因為多個團隊在同一個 Git 存儲庫中處理不同的數據庫,並且每個人都依賴數據運營團隊中的某個人來審查和更改各種環境。
  • 為所有關係數據庫模式擁有一個存儲庫可能會導致發布過程具有挑戰性。 如果有其他模式更改尚未準備好推送到生產環境但處於暫存狀態等待額外測試,則對已準備好用於生產的一個模式的更改無法進入生產環境。
  • 數據運營團隊是一個小團隊,它成為了一個瓶頸,試圖管理哪些變更可以和不能在何時投入生產。 調度衝突和人員可用性確實會減慢新功能的發布或對當前應用程序的修復。
  • 我們正在使用拉取請求和 Jira 票證中的註釋手動將這些更改應用於生產系統; 有時復制粘貼可能會出錯。

輸入 Skeema(和一些助手)

為了消除這些流程障礙,使架構更改不易出現人為錯誤,允許開發人員管理自己的應用程序架構,並潛在地提高開發速度,數據運營團隊投入了大量精力來自動化和簡化管理數據庫架構。

我們使用我們現有的工具 Git、Buildkite CI 和 pt-online-schema-change 以及另外一個工具 Skeema,將模式更改從本地開發應用到生產環境中自動化。

這個想法是將我們的單一數據庫模式存儲庫分解為單獨的模式存儲庫,每個數據庫集群一個,並允許開發人員在他們熟悉的環境中進行自己的模式更改。 我們還希望設置合理的護欄,以幫助開發人員尋求額外的幫助,以進行大型、複雜或具有潛在破壞性的架構更改。

Skeema 是一個 CLI 工具,它使用 SQL 以聲明方式管理 MySQL 模式。

它可以為數據庫中的每個表生成數據定義語言 (DDL),並將 DDL 導出到本地文件系統,以便通過 Git 與跟踪存儲庫集成。 Skeema 可以將 Git 存儲庫中的 SQL 文件與實時 MySQL 數據庫進行比較,並將這些差異輸出為 DDL 語句。

它還可以配置為使用 Percona 的 pt-online-schema-change 工具並格式化必要的 pt-online-schema-change 命令,以將正在運行的 MySQL 數據庫的模式與 Git 存儲庫中定義的模式相匹配。

Skeema 還能夠在多個環境中管理模式,例如本地、測試和生產環境,每個環境具有不同的配置。 最後,它可以很容易地適應基於拉取請求的工作流程。

創建單獨的 MySQL 數據庫模式存儲庫將打破我們當前的單一 db-schema Git 存儲庫,並允許不同團隊的開發人員在他們自己的存儲庫中管理其應用程序的 MySQL 模式,而不是共享存儲庫 (db-schema)。

為每個數據庫模式擁有一個單獨的存儲庫將為應用程序開發團隊提供更大的自主權。 這消除了將所有模式更改協調到嚴格的時間表的需要,並允許根據應用程序團隊的需要將更改轉移到生產中。

自動化這個過程的一個重要組成部分是 Buildkite 的 CI 管道。 我們創建了一個管道:

  • 檢查 SQL 語法錯誤
  • 使用數據庫模式的當前主分支創建測試 MySQL 服務器,並測試拉取請求 (PR) 中更改的應用
  • 檢查差異並將 PR 更改應用到我們的測試 MySQL 環境
  • 檢查差異並將 PR 更改應用到我們的暫存環境,並從生產環境輸出一些表統計信息

生產輸出統計數據是磁盤上的表大小和估計的行數。 這些統計信息可以幫助確定架構更改是否會導致某種程度的服務中斷並可能需要特殊處理。 將 PR 合併到 master 後,buildkite 管道會檢查 master 分支與生產中運行的內容之間的差異。

如果差異是 PR 的預期更改,開發人員可以取消阻止最後一步,Skeema 將更改應用到生產 MySQL 數據庫集群。 這些步驟中的每一個都是一個阻止步驟,需要負責所請求更改的工程團隊的批准,然後才能進入下一步。

就護欄而言,我們已將 Skeema 配置為默認情況下不允許在生產中進行破壞性架構更改。

在我們的測試和暫存環境中允許進行破壞性更改。

我們還將 Skeema 配置為使用 pt-online-schema-change 進行架構更改。 這是 DataOps 團隊熟悉的模式更改工具,並且已在 SendGrid 中使用多年。 我們為 pt-online-schema-change 開發了一組合理的選項,以在復制落後或數據庫中的活動線程過多時回滾其更改。

以這種方式配置 Skeema 消除了 DataOps 團隊成員對應用程序手動步驟和手動編碼 pt-online-schema-change 命令的潛在錯誤。

通過添加程序化護欄,各個團隊可以負責管理他們的 MySQL 數據庫模式,並將這些更改應用到具有相對安全性的預生產和生產環境中。 如果防護欄被擊中,架構更改將失敗並回滾。 架構更改失敗的原因將輸出到構建日誌以供進一步審查。

允許開發人員將他們的更改從筆記本電腦上的本地測試引導到生產環境,極大地增強了開發人員的自主權和支持其應用程序的數據庫的所有權。 Skeema 的自動化和集成到我們的 MySQL 數據庫管理流程中輕鬆涵蓋了我們大約 90% 的一般模式更改管理任務。

大多數架構更改用於添加列、更改枚舉字段、更改默認值和添加索引。 其餘 10% 的模式更改處理大型表、非常活躍的數據庫或分區表的特殊情況。 在這篇文章中,Skeema 還沒有處理對分區表進行模式更改,但我聽說這是一個經常被要求添加的內容,並且 Skeema 的開發人員正在積極尋求幫助來實現該功能。

將 Git、pt-online-schema-change、Skeema 和 Buildkite CI 管道相結合,為 MySQL 數據庫模式更改帶來了可靠、可重複的編程過程。 它使開發人員能夠安全地管理其數據庫的架構並控制將功能和修復部署到生產環境的速度。

在 Skeema 和 pt-online-schema 更改的配置文件中包含適當的護欄,為開發人員實施模式更改提供了一種信心度量,並在這些護欄被擊中時就繼續進行模式更改的可能方式提供有價值的反饋。

數據運營團隊仍然可以幫助那些無法應用此流程的剩餘 10% 的案例,並將致力於開發其他工具以在未來增強此流程。