2008-09-08 17 views
2

在我們當前的數據庫開發環境中,我們使用自動構建過程檢查svn create database腳本中的所有sql代碼,並將它們應用於各種開發/ qa數據庫。重新運行數據庫開發腳本

這是一切都很好,是一個tremdous改善了我們過去一樣,但我們有一個問題,重新運行的腳本。很顯然,這對於像改變程序這樣的一些腳本來說不是問題,因爲你可以一遍又一遍地運行它們而不會不利地影響系統。現在添加元數據並運行像create/alter table語句之類的語句,我們添加代碼來檢查並查看對象是否存在,如果存在,請不要運行它們。

我們的問題是,我們真的只有一次機會來運行腳本,因爲一旦腳本已經運行時,物體在環境中,系統不會再次運行該腳本。如果一旦部署後需要更改某些內容,我們就有一個難以運行更新腳本的過程,即更新腳本,希望所有內容都按照正確的順序排列,並且所有的PK都在環境之間排隊(數據庫是,我們應該說,「特別」)。

短刪除數據庫和從頭開始的過程(最後一個最新版本)的,沒有任何人有一個更優雅的解決方案呢?

回答

1

你保留現有的數據庫中的數據?如果沒有,你可能想看看類似於馬特提到的.NET一些所謂RikMigrations

http://www.rikware.com/RikMigrations.html 

我用我的項目更新我的飛行數據庫,同時跟蹤修訂。此外,它對數據庫架構移動到不同的服務器,它很簡單,等

如果你想擁有重新流動性在腳本
0

,那麼你不能讓他們爲定義......我的意思是這個是你需要關注更改腳本而不是這裏是我的表腳本。

讓我們假設你有一個表的客戶:

create table Customers (
    id int identity(1,1) primary key, 
    first_name varchar(255) not null, 
    last_name varchar(255) not null 
) 

,以後你要添加一個狀態欄。不要修改原始表腳本,該腳本已經運行(並且可以使用if(!exists)語法來防止它在再次運行時導致錯誤)。

相反,有一個新的腳本,在這個腳本調用add_customer_status.sql

你必須是這樣的:(!存在)

alter table Customers 
add column status varchar(50) null 

update Customers set status = 'Silver' where status is null 

alter table Customers 
alter column status varchar(50) not null 

同樣,你可以用,如果這個包起來,以阻止允許重新運行,但在這裏我們已經利用了這是一個改變腳本的概念,並且我們相應地調整了數據庫。如果客戶表中已有數據,那麼我們仍然可以,因爲我們添加了列,使用數據對其進行種子處理,然後添加非空約束。

上述兩種遷移框架都很好,我也有很好的經驗與MigratorDotNet

0

Scott命名了幾個其他SQL tools,這解決了變更管理的問題。但我仍然在搖擺我自己。

我想回答這個問題,並添加我的困惑,仍然沒有免費的,基於社區的工具來解決這個問題。顯然,腳本並不是維護數據庫模式的令人滿意的方式;也不是實例。那麼,爲什麼我們不要將元數據保存在單獨的(而我們處於這個平臺中的情況下)格式呢?

這就是我現在要做的。我的主數據庫模式是一個版本控制的XML文件,最初由一個簡單的Web服務創建。一個簡單的javascript程序將實例與它進行比較,而簡單的XSL轉換就會產生CREATE或ALTER語句。它有限制,如RikMigrations;例如它並不總是正確地對順從的對象進行排序。 (但是猜猜也不是Microsoft's SQL Server Database Publication tool。)真的,這太簡單了。我根本沒有包含我沒有使用的對象(角色,用戶等)。

所以,我認爲這個問題確實沒有得到充分的解決,遲早我們必須聚在一起解決惡魔般的細節問題。

2

我們解決這個問題 - 或至少相似的問題這一點 - 如下:

  1. 架構的版本號 - 這是由具有每個版本一列一個表,其除了作爲代表版本號,攜帶枯燥的東西,如該版本出現時的日期/時間戳。
  2. 通過讓模式創建/修改包含在代碼中的DDL來爲我們執行更改。

在上面的上下文中,將構建模式更改代碼作爲構建過程的一部分,然後運行它,它只會應用尚未應用的模式更改。在大多數情況下,模式變化足夠小/快,以致它們可以安全地在事務中運行,這意味着如果失敗,我們會得到一個回滾,而數據庫是「安全」 - 儘管在可行的情況下總是建議在應用模式更新之前進行備份。

我從惡劣的痛苦經歷中發展而來。它不是一個完美的系統(或一個原始的想法),但是作爲這種工作方式的結果,我們有很高的信心,如果我們的一個數據庫有兩個相同版本的實例,那麼這兩個數據庫的模式將會在幾乎所有方面都是一樣的,我們可以安全地將任何db帶到該應用程序的當前模式,而不會產生不良影響。 (不幸的是,最後並不是100%真的 - 總是有一個例外 - 但是它的真相併不太遠!)

0

我們進行了「刪除並重新創建模式」路線。我們在JUnit測試包中有一些類,它們將腳本參數化,以便爲執行代碼的開發人員在模式中創建所有對象。這使得所有開發人員可以共享一個測試數據庫,每個人都可以同時創建/測試/丟棄他們的測試表而不會發生衝突

運行需要很長時間嗎?是。起初,我們使用了這種設置方法,這意味着每個測試都會丟棄/創建表,並且這個過程太長了。然後我們創建了一個TestSuite,它可以在所有類的測試之前運行一次,然後在所有類測試完成後清理乾淨。這仍然意味着當我們運行包含我們所有軟件包中的所有測試的'AllTests'類時,db安裝程序運行很多次。我解決這個問題的方法是在OracleTestSuite代碼中添加一個信號量,因此當第一次測試請求數據庫進行安裝時,它會這樣做,但後續任何調用只會增加一個計數器。當每個tearDown()方法被調用時,計數器將遞減計數器直到它達到0,並且OracleTestSuite代碼將丟棄所有內容。留下的一個問題是測試是否假定數據庫是空的。讓數據庫測試知道它們的運行順序是很方便的,這樣可以利用數據庫的狀態,因爲它可以減少數據庫設置的重複。

我們使用ObjectMothers的概念解決了創建複雜域對象以用於測試目的的類似問題。模擬對象可能是更好的答案,但我們當時沒有聽說過它們。畢竟這一次,我建議創建測試助手方法,可以爲典型場景創建標準化數據集。此外,這將有助於從數據角度記錄重要的邊緣案例。