2013-05-04 176 views
21

我試圖解決一個問題,那一次,我沒有創建。在SQL數據庫之間共享數據

我在一個環境中工作,許多Web應用程序都支持不同的服務器上的不同數據庫。

每個數據庫在其設計和應用程序中都是相當獨特的,但我仍然想要抽象出每個數據庫中的常見數據。每個數據庫,例如有一個供應商表,一個用戶表等...

我想抽象出這個公共數據到單個數據庫,但仍然讓其他數據庫加入這些表,甚至有鍵強制約束等......我在MsSql環境中。

enter image description here

哪些可供選擇?就我看到它,我有以下選擇:

  • 鏈接服務器
  • 只讀登錄授予訪問權限的意見

還有什麼考慮?

+0

您打算如何使用這些信息?您可以創建一個數據庫來保存其他數據庫的公共信息。使用mySQL ETL工具將數據從應用程序數據庫位置移動到一個集中式數據庫。我認爲Pentaho水壺應該允許你對你的應用數據庫的影響很小。 – Zane 2013-05-06 19:35:05

+0

對不起,我誤讀了你沒有使用mySQL的標籤。這使事情變得更容易。 – Zane 2013-05-06 19:43:44

+0

您對使用SSIS有多熟悉? – Zane 2013-05-06 19:44:04

回答

21

有很多方法可以解決這個問題。我強烈建議,要麼取決於您的業務解決方案,1,2,或3需要:

  1. Transactional Replication:如果公共數據庫帳戶的記錄,並要提供只讀版本來分隔數據應用程序,那麼您可以將核心表(可能甚至是核心列表)複製到每個單獨的服務器。這種方法的一個優點是,您可以根據需要複製到任意數量的訂戶數據庫。這也意味着您可以根據用戶的需求自定義哪些表格和字段可供用戶使用。因此,如果一個應用程序需要用戶表而不需要供應商表,那麼您只需訂閱用戶表。如果另一個只需要供應商表而不需要用戶表,那麼您只能訂閱供應商表。另一個好處是複製保持自己同步,並且如果出現問題,您可以始終重新初始化訂閱。

    我已經使用事務複製從數據倉庫中推出了超過100個表來分隔需要訪問來自多個系統的聚合數據的下游應用程序。由於我們的數據倉庫是根據鏡像和日誌傳送數據源每小時進行更新的,因此生產應用程序在每小時20到80分鐘的滑動窗口內有多個系統的數據。

    Peer-to-Peer transactional replication作爲發佈類型可能更適合您提供的用例。如果您想逐個節點地部署模式或複製更改,這可能非常有用。標準事務複製在這方面有一些限制。

    快照複製發佈類型比事務發佈具有更多延遲,但如果延遲程度可以接受,您可能需要考慮它。

    雖然您提到您是Microsoft SQL Server商店,但請記住其他RDBM具有相似的技術。由於您專門討論了MS SQL Server,請注意,事務性複製也允許您複製到Oracle數據庫。所以如果你的組織中有一些這樣的解決方案,這個解決方案仍然可以工作。

    使用事務複製的缺點是,如果您的中央服務器出現故障,您可能會開始感受到複製對象下游副本中的數據延遲。如果複製的對象(文章)真的很大,並且需要重新初始化表格,那麼這也需要很長時間。

  2. Mirrors如果您想讓數據庫在下游服務器上以近實時方式訪問,最多可以設置兩個異步鏡像。我用這種方式將數據與CRM應用程序集成在一起。所有讀取都來自鏡像的連接。所有寫入都被推送到消息隊列,然後將更改應用到中央生產服務器。這種方法的缺點是你不能創建2個以上的異步鏡像。除非您計劃使用鏡像進行災難恢復,否則您不想爲此使用同步鏡像。如果您希望有多個單獨的應用程序需要來自單箇中央數據庫的數據,那麼您可能需要考慮像IBM Web Sphere,Microsoft BizTalk,Vitria,TIBCO等企業消息傳遞系統。這些應用程序是專爲解決這個問題而打造。他們往往是昂貴和繁瑣的實施和維護,但他們可以擴大如果你有全球分佈式系統或幾十個單獨的應用程序,都需要在一定程度上共享數據。

  3. Linked Servers:這聽起來像你已經想到這一個。您可以通過鏈接服務器公開數據。我不相信這是一個好的解決方案。如果你真的想走這條路線,那麼考慮從中央數據庫到另一臺服務器建立一個異步鏡像,然後建立鏈接服務器連接到鏡像。這至少可以緩解來自Web應用程序的查詢將導致中央生產數據庫出現阻塞或性能問題的風險。

    IMO,鏈接的服務器往往是共享應用程序數據的危險方法。這種方法仍然將數據視爲數據庫中的二等公民。它會導致一些非常糟糕的編碼習慣,尤其是因爲您的開發人員可能使用不同的連接方法在不同語言的不同服務器上工作。你不知道是否有人會針對你的核心數據寫出一個真正的痛恨查詢。如果您設置了一個標準,要求將共享數據的完整副本向下推送到非核心服務器,那麼您不必擔心開發人員是否編寫錯誤的代碼。至少從他們糟糕的代碼不會使其他寫得好的系統的性能變差的角度來看。

    有很多很多的資源解釋了爲什麼在這種情況下使用鏈接服務器可能會很糟糕。一個非詳盡的原因列表包括:(a)the account used for the linked server must have DBCC SHOW STATISTICS permissions or the queries will not be able to make use of existing statistics,(b)查詢提示不能使用,除非作爲OPENQUERY提交,(c)與OPENQUERY一起使用時不能傳遞參數,(d)服務器不能(e)網絡連接問題可能導致故障,(f)any one of these five performance issues和(g)the dreaded SSPI context error when trying to authenticate windows active directory credentials in a double hop scenario沒有足夠的關於鏈接服務器的統計信息,因此會產生非常糟糕的查詢計劃。鏈接服務器對於某些特定場景可能很有用,但建議圍繞此功能構建對中央數據庫的訪問權限,儘管技術上可行,但不推薦使用。

  4. 批量ETL過程:如果Web應用程序的延遲時間很長,則可以使用SSIS (lots of good links in this StackOverflow question)編寫批量ETL過程,這些過程由SQL Server代理作業執行以在服務器之間移動數據。還有其他替代ETL工具,如Informatica,Pentaho等,因此請使用最適合您的工具。

    如果您需要低延遲,這不是一個好的解決方案。在與第三方託管的CRM解決方案同步以處理可能容忍高延遲的字段時,我使用了此解決方案。對於無法容忍高延遲的域(基本帳戶創建數據),我們依靠在帳戶生成點通過Web服務調用在CRM中創建重複記錄。

  5. 每晚備份和恢復:如果您的數據可以承受高度延遲(最多一天)和不可用時間段,則可以跨環境備份和恢復數據庫。對於需要100%運行時間的Web應用程序,這不是一個好的解決方案。這個想法是,您需要執行基準備份,將其還原爲單獨的還原名稱,然後在新準備就緒後立即重命名原始數據庫和新數據庫。我已經看到一些內部網站應用程序已完成,但我通常不推薦這種方法。這更適合於較低的開發環境,而不適用於生產環境。

  6. Log Shipping Secondaries:您可以在主服務器和任意數量的次服務器之間設置日誌傳送。這與夜間備份和恢復過程類似,不同之處在於您可以更頻繁地更新數據庫。在一個實例中,該解決方案用於通過在兩個日誌傳送收件人之間切換來向來自下游用戶的我們的主要核心系統之一公開數據。有另一臺服務器指向這兩個數據庫,並在新的數據庫可用時進行切換。我真的很討厭這個解決方案,但是有一次我看到這個實現它確實滿足了業務的需求。

+0

所有這些偉大的作品。我會進一步討論爲什麼鏈接服務器是討厭的:http://stackoverflow.com/a/4091984/2424 – NotMe 2013-05-06 20:33:25

2

您還可以考慮在常用數據存儲和應用程序數據庫之間使用內置SQL Server複製。從我的經驗來看,它非常適合雙向數據傳輸,並且每個數據庫中都有一個實例可以使用外鍵(我不認爲FK可以通過鏈接服務器)。

1

看看Microsoft Sync Framework。您將不得不編寫同步應用程序,但它可能會爲您提供所需的靈活性。

2

可能還有其他選擇,但認爲你是最佳選項的正確軌道,並且具有鏈接的服務器和視圖的組合。這可能與創建新數據庫,添加兩臺鏈接的服務器,設置權限並創建必要的視圖一樣簡單。

如果你的目標是abstract out this common data to a single database but still let the other databases join on these tables, even have keys to enforce constraints那麼這個解決方案應該可以正常工作。

在不利的一面,你可能會遇到鏈接服務器的性能問題,所以如果你預見數據庫獲得了大量的流量,那麼你可能需要考慮使用Doug或mwebber建議的方法實際移動數據。

如果你去鏈接服務器的路線,我會建議reading upOPENQUERY。在OPENQUERY vs 4部分標識here上有一篇很好的文章。

1

我想你應該有在複製一個很好看,因爲很多答案都表示,特別是在高TPS環境或你想這對很多表。但是,我將提供一些關於如何在使用鏈接服務器,同義詞和檢查約束的系統中達到您的既定目標的代碼。

我想抽象出這個共同數據到一個單一的數據庫,但還是讓其他數據庫這些表連接,甚至有鍵強制約束等

你可以設置一個視圖或您的數據庫中的synonym到鏈接服務器(或其他本地數據庫)中的公用表。無論如何,如果視圖只是select * from table,我更喜歡同義詞。

如果您有權限,則表同義詞將允許您在遠程項目上運行DML。

儘管如此,你不能爲你的視圖或同義詞使用外鍵,但是我們可以用一個檢查約束來完成類似的事情。

讓我們來看看一些代碼:

create synonym MyCentralTable for MyLinkedServer.MyCentralDB.dbo.MyCentralTable 
go 

create function dbo.MyLocalTableFkConstraint (
    @PK int 
) 
returns bit 
as begin 
    declare @retVal bit 
    select @retVal = case when exists (
          select null from MyCentralTable where PK = @PK 
         ) then 1 else 0 end 
    return @retVal 
end 
go 

create table MyLocalTable (
    FK int check (dbo.MyLocalTableFKConstraint(FK) = 1) 
) 
go 

-- Will fail: -1 not in MyLinkedServer.MyRemoteDatabase.dbo.MyCentralTable 
insert into MyLocalTable select -1 
-- Will succeed: RI on a remote table w/o triggers 
insert into MyLocalTable select FK from MyCentralTable 

當然,需要注意的是,如果你在中央表中刪除引用的記錄,你不會得到一個錯誤是很重要的。