你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用只读副本卸载只读的查询工作负荷

适用于: Azure SQL 数据库 Azure SQL 托管实例

作为高可用性体系结构的一部分,“高级”和“业务关键”服务层级中的每个单一数据库或弹性池数据库会自动预配有一个主读写副本和一个或多个次要只读副本。 为次要副本预配的计算大小与主要副本相同。 “读取扩展”功能允许使用一个只读副本的计算容量而不是在读写副本上运行它们来卸载只读工作负荷。 这样,一些只读工作负载可与读写工作负载隔离,并且不会影响其性能。 该功能适用于包含逻辑隔离的只读工作负荷(例如分析)的应用程序。 在“高级”和“业务关键”服务层级中,应用程序可以使用此额外的容量获得性能优势,而无需额外付费。

如果至少添加了一个次要副本,则在超大规模服务层级中也可以使用“读取扩展”功能。 超大规模次要命名副本提供独立缩放、访问隔离、工作负载隔离、对多种读取扩展方案的支持以及其他优势。 多个次要 HA 副本可用于对只读工作负载进行负荷平衡,只读工作负荷需要的资源量超过了一个次要 HA 副本上提供的资源。

“基本”、“标准”和“常规用途”服务层级的高可用性体系结构不包含任何副本。 读取扩展功能在这些服务层级中不可用。 但是,使用 Azure SQL 数据库时,异地副本可以在这些服务层级中提供类似的功能。 使用 Azure SQL 托管实例和故障转移组时,故障转移组只读侦听器可以分别提供类似的功能。

下图说明了用于高级版和业务关键数据库以及托管实例的功能。

显示只读副本的示意图。

新的“高级”、“业务关键”和“超大规模”数据库中默认已启用读取扩展功能。

注意

读取扩展在 SQL 托管实例的业务关键服务层中始终处于启用状态,并且对于至少具有一个辅助副本的超大规模数据库处于启用状态。

如果为 SQL 连接字符串配置了 ApplicationIntent=ReadOnly,则将应用程序重定向到该数据库或托管实例的只读副本。 有关如何使用 ApplicationIntent 属性的信息,请参阅指定应用程序意向

仅对于 Azure SQL 数据库,如果你希望确保应用程序始终连接到主要副本,而不管 SQL 连接字符串中的 ApplicationIntent 设置如何,则必须在创建数据库或更改其配置时显式禁用读取扩展。 例如,如果你将数据库从标准层级或常规用途层级升级到高级版或业务关键,并且要确保所有连接继续转到主副本,请禁用读取横向扩展。有关禁用方法的详细信息,请参阅启用和禁用读取横向扩展

注意

只读副本不支持查询存储和 SQL Profiler 功能。

数据一致性

对主要副本进行的数据更改根据副本类型以同步或异步方式在只读副本上持久保存。 但是,对于所有副本类型,从只读副本进行的读取始终与主要副本异步。 在连接到只读副本的会话中,读取始终在事务上保持一致。 由于数据传播延迟是可变的,因此不同的副本可能会在相对于主要副本和其他副本略微不同的时间点返回数据。 如果只读副本变得不可用并且会话重新连接,则它可能会连接到与原始副本位于不同时间点的副本。 同样,如果应用程序在主要副本上使用读写会话更改数据,并立即使用只读会话在只读副本上读取该数据,则最新的更改可能不会在只读副本中立即可见。

主要副本和只读副本之间的典型数据传播延迟在几十毫秒到几秒的范围内变化。 但是,数据传播延迟没有固定的上限。 副本中的高资源利用率等条件会显著增加延迟。 如果应用程序需要保证跨会话数据一致性或需要提交的数据立即可读,则应使用主要副本。

注意

数据传播延迟包括将日志记录发送和保存(如果适用)到次要副本所需的时间。 它还包括将这些日志记录恢复(应用)到数据页所需的时间。 为确保数据一致性,在应用事务提交日志记录之前,更改不可见。 当工作负载使用更大的事务时,有效的数据传播延迟会增加。

若要监视数据传播延迟,请参阅对只读副本进行监视和故障排除

连接到只读副本

为数据库启用读取横向扩展时,客户端提供的连接字符串中的 ApplicationIntent 选项会指示连接是要路由到写入副本还是只读副本。 具体而言,如果 ApplicationIntent 值为 ReadWrite(默认值),则连接会定向到读写副本。 这与连接字符串中未包括 ApplicationIntent 时的行为相同。 如果 ApplicationIntent 值为 ReadOnly,则连接将路由到只读副本。

例如,以下连接字符串将客户端连接到只读副本(请将尖括号中的项替换为环境的正确值,并删除尖括号):

Server=tcp:<server>.database.windows.net;Database=<mydatabase>;ApplicationIntent=ReadOnly;User ID=<myLogin>;Password=<password>;Trusted_Connection=False; Encrypt=True;

若要使用 SQL Server Management Studio (SSMS) 连接到只读副本,请选择“选项”

显示 SSMS 选项的屏幕截图。

选择“其他连接参数”,再输入 ApplicationIntent=ReadOnly,然后选择“连接”

显示 SSMS“其他连接参数”的屏幕截图。

以下连接字符串之一将客户端连接到读写副本(请将尖括号中的项替换为环境的正确值,并删除尖括号):

Server=tcp:<server>.database.windows.net;Database=<mydatabase>;ApplicationIntent=ReadWrite;User ID=<myLogin>;Password=<password>;Trusted_Connection=False; Encrypt=True;

Server=tcp:<server>.database.windows.net;Database=<mydatabase>;User ID=<myLogin>;Password=<password>;Trusted_Connection=False; Encrypt=True;

验证连接到只读副本

可通过在数据库上下文中运行以下查询来验证是否连接到只读副本。 连接到只读副本时,它返回 READ_ONLY。

SELECT DATABASEPROPERTYEX(DB_NAME(), 'Updateability');

注意

在“高级”和“业务关键”服务层级中,只有一个只读副本随时可供访问。 “超大规模”层级支持多个只读副本。

对只读副本进行监视和故障排除

当连接到只读副本时,动态管理视图 (DMV) 反映副本的状态,并可对其进行查询以进行监视和故障排除。 数据库引擎提供了多个视图来公开各种监视数据。

以下视图通常用于副本监视和故障排除:

名称 目的
sys.dm_db_resource_stats 提供最近一小时的资源利用率指标,包括相对于服务目标限制的 CPU、数据 IO 和日志写入使用率。
sys.dm_os_wait_stats 提供数据库引擎实例的聚合等待统计信息。
sys.dm_database_replica_states 提供副本运行状况状态和同步统计信息。 重做队列大小和重做速率针对只读副本用作数据传播延迟的指示。
sys.dm_os_performance_counters 提供数据库引擎性能计数器。
sys.dm_exec_query_stats 提供每个查询的执行统计信息,例如执行次数、已用 CPU 时间等。
sys.dm_exec_query_plan() 提供缓存的查询计划。
sys.dm_exec_sql_text() 提供缓存的查询计划的查询文本。
sys.dm_exec_query_profiles 提供正执行查询时的实时查询进度。
sys.dm_exec_query_plan_stats() 提供最近的已知实际执行计划,包括查询的运行时统计信息。
sys.dm_io_virtual_file_stats() 提供所有数据库文件的存储 IOPS、吞吐量和延迟统计信息。

注意

逻辑 master 数据库中的 sys.resource_statssys.elastic_pool_resource_stats DMV 返回主要副本的资源利用率数据。

监视具有扩展事件的只读副本

连接到只读副本时,无法创建扩展事件会话。 但是在 Azure SQL 数据库和 Azure SQL 托管实例中,主要副本上创建和更改的数据库范围内扩展事件会话的定义将复制到只读副本(包括异地副本),并捕获只读副本上的事件。

在 Azure SQL 数据库中,可独立于主要副本的会话来启动和停止基于主要副本中会话定义的只读副本上的扩展事件会话。

在 Azure SQL 托管实例中,要在只读副本上启动跟踪,必须先在主要副本上启动跟踪,然后才能在只读副本上启动跟踪。 如果没有先在主要副本上启动跟踪,则会在尝试在只读副本上启动跟踪时收到以下错误:

Msg 3906,级别 16,状态 2,行 1 无法更新数据库“master”,因为该数据库为只读。

先在主要副本上启动跟踪,然后在只读副本上启动后,你可以停止主副本上的跟踪。

若要在只读副本上删除事件会话,请执行以下步骤:

  1. 向只读副本连接 SSMS 对象资源管理器或查询窗口。
  2. 通过在对象资源管理器中的会话关联菜单中选择“停止会话”,或通过在查询窗口中执行 ALTER EVENT SESSION [session-name-here] ON DATABASE STATE = STOP; 来停止只读副本上的会话。
  3. 向主要副本连接对象资源管理器或查询窗口。
  4. 通过选择会话关联菜单上的“删除”或执行 DROP EVENT SESSION [session-name-here] ON DATABASE;,在主要副本上删除会话

只读副本上的事务隔离级别

只读副本上的事务始终使用快照事务隔离级别,无论会话的事务隔离级别是什么,也不管有什么查询提示。 快照隔离使用行版本控制,以避免在读取器阻止写入器的情况下发生阻止。

极少数情况下,如果快照隔离事务访问已在其他并发事务中修改的对象元数据,则可能会收到错误 3961,“数据库 "%.*ls" 中的快照隔离事务失败,因为自此事务启动后,该语句所访问的对象已由其他并发事务中的 DDL 语句修改。 禁用它是因为元数据未进行版本控制。 如果与快照隔离混合,对元数据进行并发更新可能导致不一致。”

只读副本上的长时间运行的查询

在只读副本上运行的查询需要访问查询中引用的对象的元数据(表、索引、统计信息等)。在极少数情况下,如果在主副本上修改了对象元数据,而查询在只读副本上持有对同一对象的锁定,则查询能会阻止将主副本中的更改应用到只读副本的过程。 如果此类查询长时间运行,会导致只读副本与主要副本明显不同步。 若副本是潜在故障转移目标(辅助副本在高级版和业务关键服务层、超大规模 HA 副本和所有地理副本),这还会让数据库恢复延迟(如果应进行故障转移),导致时间比预期时间长。

如果对只读副本的长时间运行的查询直接或间接地导致此类阻止行为,则查询可能会自动终止,以避免过多的数据延迟以及可能对数据库可用性造成的影响。 该会话收到错误 1219:“由于高优先级 DDL 操作,你的会话已断开连接”或错误 3947:“由于辅助计算未能赶上重做,事务已中止”。 请重试该事务。”

注意

如果针对只读副本运行查询时收到错误 3961、1219 或 3947,则重试查询。 或者,当在次要副本上执行长时间运行的查询,避免在主副本上执行将修改对象元数据的操作(架构更改、索引维护、统计更新等)。

提示

在“高级”和“业务关键”服务层级中,连接到只读副本时,sys.dm_database_replica_states DMV 中的 redo_queue_sizeredo_rate 列都可用于监视数据同步过程,作为只读副本上数据传播延迟的指示。

为 SQL 数据库启用和禁用读取扩展

对于 SQL 托管实例,读取扩展在业务关键服务层级上自动启用,而在常规用途服务层级中不可用。 无法禁用然后重新启用读取扩展。

对于 SQL 数据库,“高级”、“业务关键”和“超大规模”服务层级中默认已启用读取扩展。 无法在“基本”、“标准”或“常规用途”服务层级中启用读取扩展。 在配置了 0 个次要副本的“超大规模”数据库上会自动禁用“读取扩展”。

对于 Azure SQL 数据库中的单一数据库和共用数据库,可以使用 Azure 门户和 Azure PowerShell 在高级或业务关键服务层中禁用和重新启用读取扩展。 这些选项不适用于 SQL 托管实例,因为无法禁用读取扩展。

注意

对于单一数据库和弹性池数据库,禁用读取扩展的功能是出于后向兼容性而提供的。 无法在“业务关键”托管实例上禁用读取扩展。

Azure 门户

对于 Azure SQL 数据库,可以在“设置”下的“计算 + 存储”数据库窗格中管理读取扩展设置。 使用 Azure 门户启用或禁用读取扩展不适用于 Azure SQL 托管实例。

PowerShell

重要

仍然支持 PowerShell Azure 资源管理器模块,但是所有未来的开发都是针对 Az.Sql 模块。 Azure 资源管理器模块至少在 2020 年 12 月之前将继续接收 bug 修补程序。 Az 模块和 Azure 资源管理器模块中的命令参数大体上是相同的。 若要详细了解其兼容性,请参阅新 Azure PowerShell Az 模块简介

在 Azure PowerShell 中管理读取横向扩展需要安装 Azure PowerShell 2016 年 12 月版或更高版本。 有关最新的 PowerShell 版本,请参阅 Azure PowerShell

在 Azure SQL 数据库中,通过在 Azure PowerShell 中调用 Set-AzSqlDatabase cmdlet,并为 -ReadScale 参数传入所需的值(EnabledDisabled),即可禁用或重新启用读取扩展。 无法为 SQL 托管实例禁用读取扩展。

若要对现有数据库禁用读取扩展(请将尖括号中的项替换为环境的正确值,并删除尖括号):

Set-AzSqlDatabase -ResourceGroupName <resourceGroupName> -ServerName <serverName> -DatabaseName <databaseName> -ReadScale Disabled

若要对新数据库禁用读取扩展(请将尖括号中的项替换为环境的正确值,并删除尖括号):

New-AzSqlDatabase -ResourceGroupName <resourceGroupName> -ServerName <serverName> -DatabaseName <databaseName> -ReadScale Disabled -Edition Premium

若要对现有数据库重新启用读取扩展(请将尖括号中的项替换为环境的正确值,并删除尖括号):

Set-AzSqlDatabase -ResourceGroupName <resourceGroupName> -ServerName <serverName> -DatabaseName <databaseName> -ReadScale Enabled

REST API

若要创建已禁用读取扩展的数据库,或更改现有数据库的设置,请在将 readScale 属性设置为 EnabledDisabled 的情况下使用以下方法,如以下示例请求所示。

Method: PUT
URL: https://management.azure.com/subscriptions/{SubscriptionId}/resourceGroups/{GroupName}/providers/Microsoft.Sql/servers/{ServerName}/databases/{DatabaseName}?api-version= 2014-04-01-preview
Body: {
   "properties": {
      "readScale":"Disabled"
   }
}

有关详细信息,请参阅数据库 - 创建或更新

在只读副本上使用 tempdb 数据库

主要副本上的 tempdb 数据库不会复制到只读副本。 每个副本具有自身的 tempdb 数据库,该数据库是创建该副本时创建的。 这确保 tempdb 可更新,并可以在执行查询期间进行修改。 如果只读工作负荷依赖于使用 tempdb 对象,则应该在连接到只读副本时,在同一个工作负荷中创建这些对象。

结合使用读取扩展与异地复制的数据库

异地复制的辅助数据库具有与主数据库相同的高可用性体系结构。 如果要连接到启用了读取扩展的异地复制辅助数据库,则设置为 ApplicationIntent=ReadOnly 的会话会路由到其中一个高可用性副本,就像在主要的可写入数据库上路由它们一样。 而未设为 ApplicationIntent=ReadOnly 的会话会路由到异地复制辅助数据库的主要副本,该副本也是只读的。

这样,创建异地副本可以为读写主数据库提供多个额外的只读副本。 其他每个异地副本提供另一组只读副本。 可在任何 Azure 区域(包括主数据库的区域)创建异地副本。

注意

异地复制辅助数据库的副本之间没有自动轮循机制或任何其他负载均衡路由,但具有多个 HA 副本的超大规模异地副本除外。 在这种情况下,具有只读意向的会话分布在异地副本的所有 HA 副本上。

只读副本上的功能支持

下面列出了只读副本上某些功能的行为:

  • 对只读副本的审核会自动启用。 要详细了解存储文件夹、命名约定和日志格式的层次结构,请参阅 SQL 数据库审核日志格式
  • Query Performance Insight 依赖于查询存储中的数据,该查询存储当前不跟踪只读副本上的活动。 Query Performance Insight 不会显示在只读副本上执行的查询。
  • 自动优化依赖于查询存储,如自动优化纸张中所述。 自动优化仅适用于在主要副本上运行的工作负载。

后续步骤