2008-08-08 80 views
154

我很難找到如何在開發,測試和生產服務器之間管理數據庫模式和數據的好例子。如何在開發,測試和生產中管理數據庫?

這是我們的設置。每個開發人員都有一臺運行我們的應用和MySQL數據庫的虛擬機。做他們想做的事是他們個人的沙箱。目前,開發人員將對SQL模式進行更改,並將數據庫轉儲到他們提交到SVN的文本文件中。

我們希望部署持續集成開發服務器,該服務器始終運行最新的提交代碼。如果我們現在這樣做,它會爲每個構建從SVN重新加載數據庫。

我們有一個運行「發佈候選」的測試(虛擬)服務器。部署到測試服務器目前是一個非常手動的過程,通常需要從SVN加載最新的SQL並對其進行調整。另外,測試服務器上的數據不一致。您最終得到最後一名開發人員在其沙箱服務器上提供的任何測試數據。

凡是發生故障的部分都是生產部署。由於我們無法用測試數據覆蓋實時數據,因此需要手動重新創建所有模式更改。如果有大量的模式更改或轉換腳本來操縱數據,這可能會變得非常多毛。

如果問題只是模式,它會是一個更容易的問題,但是在開發過程中還會更新數據庫中的「基礎」數據,例如安全和權限表中的元數據。

這是我在邁向持續集成和一步構建時遇到的最大障礙。 解決了嗎?


後續問題:如何跟蹤數據庫版本,以便知道要運行哪些腳本以升級給定的數據庫實例?像蘭斯這樣的版本表是否在標準程序下方提到?


感謝您參考塔倫蒂諾。我不在.NET環境中,但我發現它們的DataBaseChangeMangement wiki page非常有幫助。特別是這Powerpoint Presentation (.ppt)

我打算編寫一個Python腳本,檢查給定目錄中*.sql腳本的名稱與數據庫中的表的名稱,並根據表單形式運行那些不存在的名稱文件名的第一部分。如果這是一個非常簡單的解決方案,正如我懷疑的那樣,那麼我會在這裏發佈它。


我有一個工作腳本。它處理初始化數據庫,如果它不存在並根據需要運行升級腳本。還有用於擦除現有數據庫並從文件導入測試數據的開關。它大約有200行,所以我不會發布它(儘管如果有興趣,我可能會把它放在pastebin上)。

+0

相關:HTTP:// stackoverflow.com/questions/52583/best-tool-for-synchronizing-mysql-databases – 2012-08-21 09:31:36

回答

46

有幾個很好的選擇。我不會使用「恢復備份」策略。

  1. 腳本所有模式更改,並讓您的CI服務器在數據庫上運行這些腳本。有一個版本表來跟蹤當前的數據庫版本,並且只有在針對新版本時才執行腳本。

  2. 使用遷移解決方案。這些解決方案因語言而異,但對於.NET,我使用Migrator.NET。這使您可以對數據庫進行版本升級並在版本之間上下移動。您的模式在C#代碼中指定。

26

你的開發人員編寫的每一個錯誤/功能上他們的工作變化的腳本(架構和數據的變化),不只是單純的轉儲整個數據庫源代碼控制。這些腳本會將當前生產數據庫升級到開發中的新版本。

您的構建過程可以將生產數據庫的副本恢復到適當的環境中,並在其上運行源代碼管理中的所有腳本,從而將數據庫更新爲當前版本。我們每天都會這樣做,以確保所有腳本正確運行。

1

如果您在.NET環境中,那麼解決方案是Tarantino。它在NANT構建中處理所有這些(包括要安裝的SQL腳本)。

+1

死鏈接。該項目現在似乎在這裏:https://bitbucket.org/headspringlabs/tarantino/wiki/Home或這裏:https://github.com/HeadspringLabs/Tarantino – 2014-03-18 21:50:22

12

看看Ruby on Rails如何做到這一點。

首先存在所謂的遷移文件,它基本上將數據庫模式和數據從版本N轉換到版本N + 1(或者從版本N + 1降級到N)。數據庫有告訴當前版本的表格。

測試數據庫總是在單元測試之前擦除乾淨,並使用文件中的固定數據填充。

3

這是我一直不滿意的東西 - 我們解決這個問題的方法。幾年來,我們爲每個版本保留一個單獨的更改腳本。該腳本將包含上一個產品版本的變更。隨着應用程序的每個版本,版本號會增加,給類似如下:

  • dbChanges_1.sql
  • dbChanges_2.sql
  • ...
  • dbChanges_n.sql

直到我們開始維護兩條線的開發之前,這種方法運行得很好:新的開發中的Trunk/Mainline,以及bug修復,短期增強等的維護分支。不可避免地, ges到分支中的模式。在這一點上,我們已經有了在樹幹dbChanges_n + 1.SQL,所以我們結束了類似下面的方案去:

  • dbChanges_n.1.sql
  • dbChanges_n.2.sql
  • ...
  • dbChanges_n.3.sql

同樣,這已經足夠好了,直到我們有一天,我們一擡頭,看見在主線和42個三角洲腳本10支。哎呀!

現在我們簡單地維護一個delta腳本並讓SVN版本 - 即我們用每個版本覆蓋腳本。我們避免在分支機構中進行模式更改。

所以,我對此也不滿意。我非常喜歡Rails遷移的概念。我對LiquiBase非常着迷。它支持增量數據庫重構的概念。值得一看,我會很快詳細的看看它。任何人都有使用它的經驗?我很想知道你的結果。

1

查看dbdeploy,已經有Java和.net工具可用,您可以按照他們的SQL文件佈局和模式版本表標準來編寫您的Python版本。

2

我們有一個非常類似於OP的設置。

開發人員使用私有數據庫開發VM。

[開發商將很快提交到私有分支]

測試是(在虛擬機的服務器上託管的實際) 在不同的機器上運行

測試[很快就會被哈德森CI服務器運行]通過加載參考轉儲到數據庫。 應用開發者架構補丁 然後應用開發者數據補丁

然後運行單元和系統測試。

生產作爲安裝者部署給客戶。

我們做什麼:

我們把我們的沙箱數據庫的模式轉儲。 然後一個sql數據轉儲。 我們將其與之前的基準進行比較。 那對deltas是將n-1升級到n的。

我們配置轉儲和增量。

因此,要安裝版本N CLEAN,我們運行轉儲到一個空的數據庫。 要進行修補,請應用中間修補程序。

(尤哈提及具有表記錄當前DB版本的軌道的想法是好的,應該使安裝更新少誤人子弟。)

三角洲和堆放有beta測試之前進行審查。 我看不到任何解決方法,因爲我已經看到開發人員將測試帳戶插入到數據庫中。

1

恐怕我同意其他海報。開發人員需要編寫腳本。

在許多情況下,一個簡單的ALTER TABLE將不起作用,您還需要修改現有數據 - 開發人員需要了解需要什麼遷移並確保它們正確編寫腳本(當然,您需要仔細測試在發佈週期的某個時間點)。此外,如果您有任何意義,您可以讓開發人員對其更改進行腳本回滾,以便在需要時還原它們。這也應該進行測試,以確保它們的回滾不僅沒有錯誤地執行,而且使數據庫保持與先前相同的狀態(這並非總是可行或可取的,但大多數情況下是一個很好的規則) 。

如何將其掛接到CI服務器,我不知道。也許你的CI服務器需要有一個已知的構建快照,它會在每天晚上恢復,然後應用所有更改。這可能是最好的,否則破壞的遷移腳本不僅會打破當晚的構建,而且會破壞所有後續構建。

3

你也可以看看使用像SQL Compare工具腳本數據庫的各個版本之間的區別,讓您在版本之間

+1

SQLCompare是用於SQL Server。 Red Gate的MySQL工具是調用MySQL Compare和cam在這裏找到的:http://mysql-compare.com/ – 2011-08-18 21:45:29

0

我寫了一個工具(掛接到Open DBDiff)快速遷移比較數據庫模式,並向您建議遷移腳本。如果你做了一個刪除或修改數據的改變,它會拋出一個錯誤,但是爲腳本提供一個建議(例如,當一個列在新模式中丟失時,它將檢查列是否已被重命名並創建xx - 生成包含重命名語句的script.sql.suggestion)。

http://code.google.com/p/migrationscriptgenerator/ SQL Server只恐怕:(這也是很不成熟,但它是非常低的摩擦

我用它是有一個SQL的方式(特別是如果你有塔倫蒂諾或http://code.google.com/p/simplescriptrunner/結合起來)腳本項目在你的.sln中,你也可以在本地做一個db_next數據庫(使用Management Studio或NHibernate Schema ExportLinqToSql CreateDatabase或其他),然後用_dev和_next數據庫執行migrationscriptgenerator,創建SQL更新腳本

7

Refactoring Databases: Evolutionary Database Design可能會給你一些想法,如何管理e數據庫。短版本也可讀http://martinfowler.com/articles/evodb.html

在一個PHP + MySQL項目中,我已經將數據庫修訂號存儲在數據庫中,並且當程序連接到數據庫時,它將首先檢查修訂版。如果程序需要不同的版本,它將打開一個頁面來升級數據庫。每次升級都在PHP代碼中指定,這將更改數據庫模式並遷移所有現有數據。

4
  • 名稱的數據庫如下 - db_dev,db_test,db_qa,db_prod(很顯然,你永遠不應該硬編碼DB名
  • 因此,你將能夠部署甚至不同類型的同一物理服務器上數據庫的的(我做但是你可能不得不......如果資源緊張的話)
  • 確保你能夠在這些數據之間自動移動數據
  • 將數據庫創建腳本與總體分開=應該總是可以重新創建db從頭開始並填充它(從舊的db版本或外部數據源
  • 不要在代碼中使用硬編碼連接字符串(即使不在配置文件中) - 在配置文件中使用連接字符串模板,您可以動態填充它,需要重新編譯的application_layer的每個重新配置都是壞BAD
  • 使用數據庫版本和版本數據庫對象 - 如果你能負擔得起使用現成的產品,如果每個DDL變化對自己的
  • 軌跡不發展的東西,並保存到一些歷史表(example here
  • 每日備份!測試你能夠以多快的速度恢復備份丟失的東西(使用自動恢復腳本即使你的DEV數據庫和PROD具有完全相同的創建腳本,你也會遇到數據問題,因此開發人員可以創建準確的(我知道我會接受這個問題的缺點,但是當思念和業務流程發生變化時,如果狗屎碰上粉絲,那麼你的成本就會降低很多 - 所以強制編碼人員合法地標明它所做的任何事情,但是確保這一
0

我們使用命令行mysql-diff:它輸出兩個數據庫架構之間的差異(從活DB或腳本)作爲ALTER腳本的mysql-DIFF在應用程序啓動時運行,如果模式改變,它報告s給開發者。因此開發人員不需要手動編寫ALTER,模式更新會半自動發生。

0

對於oracle數據庫,我們使用oracle-ddl2svn工具。

這個工具自動下道工序

  1. ,每分貝方案GET方案的DDL
  2. 把它放在版本控逆變實例之間

改變手動解決