Connection String 中的 Failover Partner Parameter

相信大家都知道Connection String可以設定Failover Partner在有Mirroring的環境上。當主體伺服器發生問題時,能夠Failover連線到另外一台鏡像伺服器。

但是大家對於鏡像環境建立Connection String的Failover Partner Parameter通常都有不太清楚的理解。

理論上來說,當成功連接Principle SQL Server,data access provider 會向目前已連線的SQL Server下載Failover Partner在Client端並Cache,之後,.NET Framework Data Provider for SQL Server 就不會更新Failover Partner。 然而,假設Principle SQL Server突然掛了,Client連線不到Principle SQL Server,後續則會透過Connection String中的Failover Partner Parameter連接SQL Server,假如此時和Failover Partner Parameter中的SQL Server連線順利建立,SQL Server則會傳遞【新】的Failover Partner給Client端並Cache。

所以其實有兩種情況

  1. 當連線順利建立,data access provider 會向目前已連線的SQL Server下載Failover Partner
  2. 若第一次連線無法建立成功,則 data access provider tries透過Connection String中的Failover Partner Parameter試著連線,若是連線成功,則會向目前已連線的SQL Server下載Failover Partner

下圖說明Client端連接到名為 Db_1 Principal Partner_A 此圖將顯示Client端可正確識別目前Principal SQL Server Partner_A 初始連線嘗試成功,而且data access provider 將mirroirng Server (Partner_B) 當作Failover Partner 儲存在本機快取中。 如同上述所說的第一種情況。


https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms366348(v=sql.105)

因此是否有成功與SQL Server連線則會決定使用Connection String中的Failover Partner Parameter。

如果經由上述還是有一點模糊,下面這篇文章會用幾個例子來介紹真實環境是如何去運作的。

 


Case 1

ServerA 為 Principal (Principal, Synchronized)
ServerB 為 Mirror (Mirror, Synchronized / Restoring …)
Connectionstring 為 “Data Source=ServerA;Failover Partner=ServerB;Initial Catalog=DB“;

當我們對connection call open(),此時因為SeverA是Principal,因此我們能夠成功與ServerA的SQL SERVER建立連線,接著Client端會從ServerA下載ServerB為Failover Partner並Cache。代表Connection String中的 Failover Partner Parameter 在這裡被沒有被使用到。

因此這個例子說明 Failover Partner 是 ServerB (從Server A的 SQL Server下載)


Case 2

ServerA 為 Principal (Principal, Synchronized)
ServerB 為 Mirror (Mirror, Synchronized / Restoring …)
Connectionstring 為 “Data Source=ServerA;Failover Partner=ServeX;Initial Catalog=DB“;

Connectionstring 為 “Data Source=ServerA;Initial Catalog=DB“;

Case2中的Failover Partner Parameter其實不存在或是沒有作用(ServerX),但是我們來看看對這條connection call open()會發生什麼事情。此時因為SeverA是Principal,因此我們能夠成功與ServerA的SQL SERVER建立連線,接著Client端會從ServerA下載ServerB為Failover Partner並Cache。如同Case1一樣。Connection String中的 Failover Partner Parameter 在這裡被依舊沒有被使用到。

因此這個例子說明無論Connection String中的 Failover Partner Parameter 是否存在或有效用並不影響SQL Server的連接,且會成功下載 Failover Partner 。其中Failover Partner為 ServerB (從Server A的 SQL Server下載),


Case 3

ServerA 為 Mirror (Mirror, Synchronized / Restoring …)
ServerB 為 Principal (Principal, Synchronized)
Connectionstring 為 “Data Source=ServerA;Failover Partner=ServerB;Initial Catalog=DB“;

當我們對connection call open(),Client會企圖連接ServerA,因為在ConnectionString中ServerA為Data Source,不過此時連線會失敗,因為ServerA為Mirroring狀態且無法存取。此時data access provider會使用ConnectionString中的Failover Partner Parameter,因此會企圖連線到ServerB,這條連線會建立成功,因為目前ServerB為Principal。

此時因為與ServerB建立連線成功,因此Client從ServerB的SQL Server下載Failover Partner為ServerA並Cache在Client端。

因此這個例子說明 Failover Partner 是 ServerA (從Server B的 SQL Server下載),縱使Connectionstring寫的Partner是ServerB。

容易被誤解的部分,從ConnectionString我們以為Failover Partner為ServerB,但是事實上Case 3的Failover Partner為ServerA (in the cache)


Case 4

ServerA 為 Mirror (Mirror, Synchronized / Restoring …)
ServerB 為 Principal (Principal, Synchronized)
Connectionstring 為 “Data Source=ServerA;Failover Partner=ServeX;Initial Catalog=DB“;

Connectionstring 為 “Data Source=ServerA;Initial Catalog=DB“;

當我們對connection call open(),Client會企圖連接ServerA,因為在ConnectionString中ServerA為Data Source,此時連線會失敗,因為ServerA為Mirroring狀態且無法存取。此時data access provider會使用ConnectionString中的Failover Partner Parameter,因此會企圖連線到ServerX或是無法連線。(假設ServerX不存在),因此會出現以下錯誤

System.Data.SqlClient.SqlException (0x80131904):
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible.
Verify that the instance name is correct and that SQL Server is configured to allow remote connections.

假設此時Failover發生了,因此ServerA變為Principal ,ServerB變為Mirror ,此時Connection又能夠成功繼續建立連線,如同Case1。


Case 5

ServerA 為 Principal (Principal, Synchronized)
ServerB 為 Mirror (Mirror, Synchronized / Restoring …)
Connectionstring 為 “Data Source=ServerA;Failover Partner=ServerB;Initial Catalog=DB“;

此時Connection Pool中已經有一些Connection了(通常都會有,因為是Defaut設定)。當我們對這條connection call open(),此時和ServerA連線順利建立。(Server A回傳ServerB為Partner並Cache在Client端)。此時,當我們對這條connection call close(),代表這條Connection 會進入Pool,所以下次call open()就會直接從pool裡面拿取Connection 。

現在進行Failover (ServerA變為Mirror, ServerB變為Principal)。並對這條connection call open(),會得到以下Error。

System.Data.SqlClient.SqlException (0x80131904):
A transport-level error has occurred when sending the request to the server.

這是因為在Pool裡的connection 並沒有任何訊息知道Failover已經發生,所以仍然以為ServerA為Principal並企圖連線。


Case 6

ServerA 為 Mirror (Mirror, Synchronized / Restoring …)
ServerB 為 Principal (Principal, Synchronized)
Connectionstring 為 “Data Source=ServerA;Failover Partner=ServerB;Initial Catalog=DB“;

此時Connection pool中已經有一些Connection了。當我們對這條connection call open(),此時和ServerA連線建立失敗,並且會透過Connectionstring中的Failover Partner Parameter連接到ServerB。(接著會從Server B 下載ServerA為Partner並Cache 在Client端。) 此時,當我們對這條connection call close(),代表這條Connection 會進入Pool,所以下次call open()就會直接從pool裡面拿取Connection 。

現在進行Failover (ServerA變為Principal, ServerB變為Mirror)。並對這條connection call open(),會發現連線順利建立成功。這個方法可以解決Case 5遇到的事件。

主要的原因是因為Datasource為 ServerA,所以第一次連線會連線到ServerA,並且可以成功連線,所以Connection中的Failover Partner Parameter會被忽略。
這篇文章大致上都是參考 Clarification on the Failover Partner in the connectionstring in Database Mirror setup ,如果大家看完上述還有興趣也可以看該作者寫的 Running a database mirror setup with the SQLBrowser service off may produce unexpected results
,這篇文章主要分析使用SQL Browser可能會遇到的問題。

SqlConnection.ConnectionString Property
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring.aspx
Making the Initial Connection to a Database Mirroring Session
http://msdn.microsoft.com/en-us/library/ms366348.aspx
Using Database Mirroring
http://msdn.microsoft.com/en-us/library/ms131373.aspx
The Impact of a Stale Failover Partner Name
http://msdn.microsoft.com/en-us/library/ms366350.aspx
Database Mirroring in SQL Server (ADO.NET)
http://msdn.microsoft.com/en-us/library/5h52hef8.aspx

發表留言