MSSQLSERVER_19407

适用于:SQL Server

详细信息

属性
产品名称 SQL Server
事件 ID 19407
事件来源 MSSQLSERVER
组件 SQLEngine
符号名称 HADR_AG_LEASE_EXPIRED
消息正文 可用性组 '%.*ls' 与 Windows Server 故障转移群集之间的租约已过期。 SQL Server 实例与 Windows Server 故障转移群集之间出现连接问题。 若要确定可用性组是否已正确完成故障转移,请检查 Windows Server 故障转移群集中的相应可用性组资源。

说明

当 SQL Server 与 Windows Server 故障转移群集之间的通信中断时,SQL Server 错误日志中会引发错误 19407。 通常会执行纠正操作 - 故障转移到另一 Always On 节点。

租约是一种基于时间的通信机制,它出现在 SQL Server 与 Windows Server 故障转移群集 (WSFC) 进程(尤其是 RHS.EXE 进程)之间。 这两个进程会定期相互通信,以确保另一进程正在运行且在响应。 此通信使用 Windows 事件对象 进行,并确保在不知道 WSFC 的情况下不会发生 AG 资源的故障转移。 如果其中一个进程未根据预定义的租约期响应租约通信,则会发生租约超时。 有关详细信息,请参阅 AlwaysOn 可用性组的租约、群集和运行状况检查超时机制和指南。 另请参阅 工作原理:SQL Server AlwaysOn 租约超时

原因

由于 Windows 事件是轻型同步对象,因此影响它们的外部因素相对较少。 可能导致租约超时的典型问题涉及系统范围问题。 下面是可能导致租约过期并导致重启或故障转移的可能性列表:

  • 系统上 CPU 使用率高(接近 100%)。

  • 内存不足条件 - 正在分页的虚拟内存和/或其中一个进程。

  • WSFC 由于仲裁丢失而脱机。 若要排查仲裁丢失问题,请参阅 配置和管理仲裁,以及 通过强制仲裁(SQL Server)进行 WSFC 灾难恢复。

  • VM 限制 会影响性能并导致租约过期。

  • 生成大型内存转储时,SQL Server 进程不会做出响应。 有关堆栈转储生成的详细信息,请参阅 转储生成的影响。 由于以下一些原因,可能会生成堆栈转储:

    • 非有力计划程序
    • 闩锁超时
    • 死锁计划程序
    • 未解决的死锁

用户操作

排查高 CPU 问题

  1. 打开任务管理器。

  2. 转到 “性能 ”选项卡,查看 CPU 是否接近或利用率为 100%。

  3. 转到“进程”选项卡,通过选择 CPU 列,按 CPU 列降序对进程进行排序。

  4. 确定使用大多数 CPU 的进程,并努力理解和解决导致 CPU 过高的原因。

  5. 如果进程是 SQL Server,请参阅 排查 SQL Server 中的高 CPU 使用率问题。

  6. 可以使用以下 PowerShell 脚本检查系统上的 CPU 使用率。

    Get-Counter -Counter "\Processor(_Total)\% Processor Time" -SampleInterval 5 -MaxSamples 30 |
        Select-Object -ExpandProperty CounterSamples | Select-Object TimeStamp, Path, CookedValue
    

排查内存不足问题

如果系统上存在虚拟内存或物理内存不足的情况,可以分页显示 SQL Server 或群集资源主机服务 (RHS.exe) 进程。如果进程分页到磁盘,则不会主动执行,并且租约超时可能由可用内存的时间到达,进程虚拟字节将分页回物理内存。 低虚拟内存可能是由系统上占用整个内存的应用程序、驱动程序或 OS 引起的。 使用以下方法排查此问题:

  1. 检查应用程序或系统事件日志中是否存在类似 Your system is low on virtual memory错误。 如果登录到服务器,甚至可能会在屏幕上显示此错误。

  2. 打开任务管理器,选择“性能 -> 内存”以检查是否消耗了接近 100% 的内存。 使用“详细信息”选项卡标识可能是最大内存使用者的任何应用程序。

  3. 也可使用性能监视器并随着时间的推移监视这些计数器:

    • Process\Working Set - 检查各个进程内存使用情况
    • 内存\可用 MBytes - 检查系统上的总体内存使用情况

    可以使用以下 PowerShell 脚本确定所有进程和系统上可用内存的总体内存使用率。 如果要获取单个进程内存使用情况,请将其 "\Process(_Total)\Working Set" 更改为 "\Process(*)\Working Set"

    $serverName = $env:COMPUTERNAME
    $Counters = @(
      ("\\$serverName" + "\Process(_Total)\Working Set") , ("\\$serverName" + "\Memory\Available Bytes")
    )
    
    Get-Counter -Counter $Counters -MaxSamples 30 | ForEach-Object {
        $_.CounterSamples | ForEach-Object {
            [pscustomobject]@{
                TimeStamp = $_.TimeStamp
                Path      = $_.Path
                Value_MB  = ([Math]::Round($_.CookedValue, 3)) / 1024 / 1024
            }
            Start-Sleep -s 5
        }
    }
    
  4. 如果确定消耗大量内存的特定应用程序,请考虑停止或移动其他系统上的应用程序或控制其内存使用情况。

  5. 如果 SQL Server 消耗了大量内存,则可以考虑使用 sp_configure 'max server memory' 来降低其内存使用量。

性能监视器 CPU、内存和磁盘的数据收集

此 PowerShell 脚本有助于收集 CPU、内存和磁盘方面的性能监视器(PerfMon)数据。 该脚本设计为灵活,允许对 SQL Server 的默认实例和命名实例进行自定义。

#Replace with your instance name if need to collect PerfMon data for named instance
$InstanceName = 'MSSQLSERVER'

# Replace with your desired location
$Location = "D:\PerfMonLogs"

# Function to create performance counter log
function Create-PerfCounterLog {
    param
    (
        [string]$InstanceName,
        [string]$Location
    )
    $counters = @(
        '\Memory\*',
        '\PhysicalDisk(*)\*',
        '\LogicalDisk(*)\*',
        '\Server\*',
        '\System\*',
        '\Process(*)\*',
        '\Processor(*)\*',
        '\SQLServer:Databases(*)\*',
        '"\SQLServer:Buffer Manager\*"',
        '"\SQLServer:SQL Statistics\*"',
        '"\SQLServer:Transactions\*"',
        '"\SQLServer:Database Mirroring\*"',
        '"\SQLServer:Latches\*"',
        '"\SQLServer:General Statistics\*"',
        '"\SQLServer:Availability Replica(*)\*"',
        '"\SQLServer:Plan Cache(*)\*"'
    )
    if ($InstanceName -eq 'MSSQLSERVER') {
        # This is for the default SQL Server instance
        $logmanCommand = "logman create counter MS_perf_log -f bin -c $counters"

    }
    else {
        # This is for a named SQL Server instance
        $InstanceName = "MSSQL`$$InstanceName"
        $counters = $counters -replace 'SQLServer', $InstanceName
        $logmanCommand = "logman create counter MS_perf_log -f bin -c $counters"

    }

    $Location = $Location + '\MS_perf_log.blg'
    $logmanCommand += " -si 00:00:01 -max 500 -o $Location"

    Start-Process -FilePath "cmd.exe" -ArgumentList "/c $logmanCommand" -Verb RunAs -Wait

}

# Function to start the collector
function Start-PerfCounterLog {
    Start-Process -FilePath "cmd.exe" -ArgumentList "/c logman start MS_perf_log" -Verb RunAs -Wait
}

# Function to stop and delete the collector
function Stop-Delete-PerfCounterLog {
    Start-Process -FilePath "cmd.exe" -ArgumentList "/c logman stop MS_perf_log" -Verb RunAs -Wait
    Start-Process -FilePath "cmd.exe" -ArgumentList "/c logman delete MS_perf_log" -Verb RunAs -Wait
}

# Create folder if not exists - update the file path as per your environment
$folderPath = $Location
if (-not (Test-Path $folderPath)) {
    New-Item -Path $folderPath -ItemType Directory
}

# Create performance counter log
Create-PerfCounterLog -InstanceName $InstanceName -Location $Location

# Start the collector
Start-PerfCounterLog

# If the event has occurred again and captured, then stop the collector
# Uncomment below line when you want to stop and delete the collector
# Stop-Delete-PerfCounterLog

减少或避免 SQL Server 或群集进程的大型内存转储

在某些情况下,SQL Server 进程可能会遇到异常、断言、计划程序问题等。 在这些情况下,SQL Server 会默认触发 SQLDumper.exe 进程,以生成具有间接内存的小型转储。 但是,如果转储生成需要很长时间,SQL Server 进程将停止响应,这可能会触发租约超时。 内存转储花费较长时间的常见原因包括:

  • 进程使用的内存量较大
  • 写入转储的 I/O 子系统速度缓慢
  • 默认设置已从小型转储更改为筛选转储或完全转储

若要避免租约超时,请使用 AG 系统上的以下步骤:

  • 增加会话超时,例如,所有副本的 120 秒
  • 将所有副本的自动故障转移更改为手动故障转移
  • 将 LeaseTimeout 增加到 60,000 毫秒(60 秒),并将 HealthCheckTimeout 更改为 90,000 毫秒(90 秒)

有关详细信息,请参阅 使用 Sqldumper.exe 工具在 SQL Server 中生成转储文件。

检查虚拟机(VM)配置是否过度预配

如果使用虚拟机,请确保不会过度预配或过度使用 CPU 和内存资源。 过度预配 CPU 或内存可能会导致来宾 OS 耗尽资源,并显示前面所述的相同问题 - CPU 高和内存不足。 如果在来宾 OS 中查看内容,请经常解释为何耗尽计算资源是困难的,因为虚拟机本身之外的情况正在发生。 过度使用资源可能会导致暂时停止处理,这可能会导致租约超时。 有关如何解决过度使用的详细信息,请参阅 排查 ESX/ESXi 虚拟机性能问题(2001003)虚拟化 – 过度使用内存以及如何在 VM 中检测内存。

检查虚拟机(VM)迁移或备份

Hyper-V、VMware 和其他 VM 解决方案提供在主机之间移动 VM 的功能(Hyper-V 实时迁移和 VMware vMotion)。 在大多数情况下,这些技术提供几乎即时的迁移。 但是,如果存在网络或主机瓶颈,这些迁移可能会延长,从而导致 VM 处于 挂起的非操作状态。 这可能会导致 SQL Server 和群集进程之间的租约超时过期。 在解决租约超时问题之前,请先解决 VM 迁移的任何问题。

虚拟机备份解决方案还可能导致 VM 停机。 如果在主机 OS 上执行 VM 备份,或者在需要很长时间的主机上执行任何类似的维护,则可能会导致租约超时问题。 原因是时钟计时时,SQL Server 和群集进程无法在挂起的 VM 上相互通信。 在检查租约超时问题之前,请先解决 VM 备份或其他维护导致的任何延迟。