使用資料相依路由將查詢路由傳送至適當的資料庫

適用於:Azure SQL Database

資料相依路由是可使用查詢中的資料,將要求路由至適當的資料庫。 資料相依路由是使用分區化資料庫時的一種基本模式。 要求內容也可能會用於路由要求,特別是如果分區化索引鍵不是查詢的一部分。 在使用資料相依路由的應用程式中,每個特定的查詢或交易會限制每個要求只能存取一個資料庫。 針對 Azure SQL Database 彈性工具,此路由會使用 ShardMapManager (Java.NET) 類別來完成。

應用程式不需要在分區化環境中追蹤不同的連接字串或與不同資料片段相關聯的 DB 位置。 相反地,分區對應管理員會根據分區對應中的資料和分區金鑰的值 (應用程式要求的目標),在必要時開啟正確資料庫的連線。 此索引鍵通常是 customer_id、tenant_id、date_key,或作為資料庫要求基本參數的其他一些特定的識別項。

如需詳細資訊,請參閱 Scaling Out SQL Server with Data Dependent Routing (使用資料相依路由相應放大 SQL Server)

下載用戶端程式庫

若要下載:

在資料相依路由應用程式中使用 ShardMapManager

應用程式應該在初始化期間,使用 Factory 呼叫 GetSQLShardMapManager (Java.NET) 來具現化 ShardMapManager。 此範例中會初始化 ShardMapManager 及其包含的特定 ShardMap。 這個範例示範 GetSqlShardMapManager 和 GetRangeShardMap (Java.NET) 方法。

ShardMapManager smm = ShardMapManagerFactory.getSqlShardMapManager(connectionString, ShardMapManagerLoadPolicy.Lazy);
RangeShardMap<int> rangeShardMap = smm.getRangeShardMap(Configuration.getRangeShardMapName(), ShardKeyType.Int32);
ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(smmConnectionString, ShardMapManagerLoadPolicy.Lazy);
RangeShardMap<int> customerShardMap = smm.GetRangeShardMap<int>("customerMap"); 

盡可能使用最低權限的認證來取得分區對應

如果應用程式不會自行操作分區對應,用於 Factory 方法中的認證在全域分區對應資料庫上應該有唯讀權限。 這些認證通常不同於用來對分區對應管理員開啟連接的認證。 另請參閱 用來存取彈性資料庫用戶端程式庫的認證

呼叫 OpenConnectionForKey 方法

ShardMap.OpenConnectionForKey (Java.NET) 方法傳回的連線可根據 key 參數的值,對適當的資料庫發出命令。 ShardMapManager 會將分區資訊快取在應用程式中,因此這些要求通常不需要針對全域分區對應資料庫進行資料庫尋查。

// Syntax:
public Connection openConnectionForKey(Object key, String connectionString, ConnectionOptions options)
// Syntax:
public SqlConnection OpenConnectionForKey<TKey>(TKey key, string connectionString, ConnectionOptions options)
  • key 參數做為分區對應中的查閱索引鍵,以決定要求的適當資料庫。
  • connectionString 只用來傳遞使用者認證給所需的連接。 此 connectionString 中不含任何資料庫名稱或伺服器名稱,因為此方法會使用 ShardMap 來決定資料庫和伺服器。
  • 若分區對應所在的環境可能變更,且資料列可能會移動到其他的資料庫成為分割或合併作業的結果,則 connectionOptions (Java.NET) 應設為 ConnectionOptions.Validate。 此驗證牽涉到在將連接傳遞至應用程式之前,對目標資料庫上的本機分區對應 (不是全域分區對應) 的簡短查詢。

如果本機分區對應驗證失敗 (表示快取不正確),分區對應管理員會查詢全域分區對應來取得查閱的新正確值、更新快取,然後取得並傳回適當的資料庫連線。

唯有當應用程式在線上,分區對應的變更是非預期之時,才使用 ConnectionOptions.None 。 在此情況下,快取的值可假定為永遠正確,可放心地略過對於目標資料庫的額外往返驗證呼叫。 這會減少資料庫流量。 也可透過組態檔中的值來設定 connectionOptions ,以指出在一段時間內是否預期有分區化變更。

此範例會利用名為 customerShardMapShardMap 物件,使用整數索引鍵值 CustomerID

int customerId = 12345;
int productId = 4321;
// Looks up the key in the shard map and opens a connection to the shard
try (Connection conn = shardMap.openConnectionForKey(customerId, Configuration.getCredentialsConnectionString())) {
    // Create a simple command that will insert or update the customer information
    PreparedStatement ps = conn.prepareStatement("UPDATE Sales.Customer SET PersonID = ? WHERE CustomerID = ?");

    ps.setInt(1, productId);
    ps.setInt(2, customerId);
    ps.executeUpdate();
} catch (SQLException e) {
    e.printStackTrace();
}
int customerId = 12345;
int newPersonId = 4321;

// Connect to the shard for that customer ID. No need to call a SqlConnection
// constructor followed by the Open method.
using (SqlConnection conn = customerShardMap.OpenConnectionForKey(customerId, Configuration.GetCredentialsConnectionString(), ConnectionOptions.Validate))
{
    // Execute a simple command.
    SqlCommand cmd = conn.CreateCommand();
    cmd.CommandText = @"UPDATE Sales.Customer
                        SET PersonID = @newPersonID WHERE CustomerID = @customerID";

    cmd.Parameters.AddWithValue("@customerID", customerId);cmd.Parameters.AddWithValue("@newPersonID", newPersonId);
    cmd.ExecuteNonQuery();
}  

OpenConnectionForKey 方法會傳回新的已開啟連接至正確的資料庫。 以這種方式使用連線仍可充分利用連線共用。

如果您的應用程式利用非同步程式設計,則也可以使用 OpenConnectionForKeyAsync method (Java.NET)。

與暫時性錯誤處理整合

在雲端中開發資料存取應用程式時,最佳做法就是確保應用程式會攔截暫時性錯誤,並且將作業重試數次之後才會擲回錯誤。 暫時性錯誤處理中討論雲端應用程式的暫時性錯誤處理 (Java.NET)。

暫時性錯誤處理可以自然地與資料相依路由模式並存。 主要需求是重試整個資料存取要求,包括用以取得資料相依路由連接的 using 區塊。 上述範例可以改寫如下。

範例 - 資料相依路由與暫時性錯誤處理

int customerId = 12345;
int productId = 4321;
try {
    SqlDatabaseUtils.getSqlRetryPolicy().executeAction(() -> {
        // Looks up the key in the shard map and opens a connection to the shard
        try (Connection conn = shardMap.openConnectionForKey(customerId, Configuration.getCredentialsConnectionString())) {
            // Create a simple command that will insert or update the customer information
            PreparedStatement ps = conn.prepareStatement("UPDATE Sales.Customer SET PersonID = ? WHERE CustomerID = ?");

            ps.setInt(1, productId);
            ps.setInt(2, customerId);
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    });
} catch (Exception e) {
    throw new StoreException(e.getMessage(), e);
}
int customerId = 12345;
int newPersonId = 4321;

Configuration.SqlRetryPolicy.ExecuteAction(() -> {

    // Connect to the shard for a customer ID.
    using (SqlConnection conn = customerShardMap.OpenConnectionForKey(customerId, Configuration.GetCredentialsConnectionString(), ConnectionOptions.Validate))
    {
        // Execute a simple command
        SqlCommand cmd = conn.CreateCommand();

        cmd.CommandText = @"UPDATE Sales.Customer
                            SET PersonID = @newPersonID
                            WHERE CustomerID = @customerID";

        cmd.Parameters.AddWithValue("@customerID", customerId);
        cmd.Parameters.AddWithValue("@newPersonID", newPersonId);
        cmd.ExecuteNonQuery();

        Console.WriteLine("Update completed");
    }
});

當您建置彈性資料庫範例應用程式時,自動會下載實作暫時性錯誤處理所需的封裝。

交易一致性

對於分區範圍內的所有作業,都保證交易式屬性。 例如,透過資料相依路由提交的交易,都在連接的目標分區範圍內執行。 目前無法將多個連接編列到交易中,因此對於跨分區執行的作業,不提供交易式保證。

後續步驟

若要中斷連結分區或重新連結分區,請參閱使用 RecoveryManager 類別來修正分區對應問題

其他資源

尚未使用彈性資料庫工具? 請參閱使用者入門指南。 如有疑問,請在 SQL Database 的 Microsoft Q&A 問題頁面上與我們連絡。如有功能要求,請在 SQL Database 意見反應論壇中新增想法或投票支持現有的想法。