修复:SQL Server 在 Windows Server 2003 或 Windows 2000 上运行一段时间后出现错误消息:"无法加载 FileName.dll"和"尝试加载任何类型的 dll 可能在 SQL Server 进程中失败"

适用于: SQL Server 2008 R2 StandardSQL Server 2008 R2 WorkgroupSQL Server 2008 R2 Developer

症状


在基于 Windows Server 2003 的计算机或基于 Windows 2000 的计算机上运行 Microsoft SQL Server 时,可能会收到包含以下错误消息的错误消息:
  • 无法加载文件名.dll
  • 尝试加载任何类型的 dll 可能会在 SQL Server 进程中失败,错误指向 LoadLibrary 失败。
此问题通常在 SQL Server 运行一段时间后发生。您收到的完整错误消息如下所示:
异常类型:Microsoft.SqlServer.管理.SqlIMail.Server.Common.BaseexceptionMessage:数据库上的读取失败。原因: 无法加载 Msxmlsql.dll.data: System.collections.list字典I,4092,NULL,NULL,2007-04-13 09:44:11.640,DB_SQLServer5,警告,2007-04-13 09:44:13.153,激活的proc [dbo]。[sp_sysmail_activate] 在队列 msdb.dbo.外部邮件队列上运行输出如下:"服务队列"外部邮件队列"当前已禁用。Msg 6610,级别 16,状态 16,程序sp_xml_preparedocument,行 1 失败加载 Msxmlsql.dll.Msg 6607,级别 16,状态 3,Proceduresp_xml_removedocument,行 1 sp_xml_removedocument:参数 1 提供的值无效。尝试加载任何类型的 dll 可能会在 SQL Server 进程中失败,错误指向 LoadLibrary 失败。尝试使用扩展存储过程将导致 Msg 0、级别 16、状态 0、过程xp_ss_backup、行 1 无法加载 DLL C:\程序文件\微软 SQL Server_MSSQL_binn_SQLsafe_ExtendedStoredProc.dll,或它引用的 DLL 之一。原因:1114(动态链接库 (DLL) 初始化例程失败。错误: 18210, 严重性: 16, 状态: 1.备份虚拟设备设置::初始化: 备份设备上的 CoCreate实例故障 'd4630f27-03a1-47ae-b7a7-4813a680908'。操作系统错误 0x8007045a(动态链路库 (DLL) 初始化例程失败。错误: 6512, 严重性: 16, 状态: 27. 未能初始化通用语言运行时 (CLR) v2.0.50727 与 HRESULT 0x80004005.您需要重新启动 SQL Server 才能使用 CLR 集成功能。

原因


出现此问题的原因是 SQL Server 进程 (Sqlservr.exe) 没有可用的线程本地存储 (TLS) 插槽。这是 Windows Server 2003 和 Windows 2000 中的问题。 当 SQL Server 卸载 DLL 时,由于TlsFree函数中的问题,DLL 使用的 TLS 插槽可能无法释放。如果 SQL Server 经常加载各种 DLL,然后卸载这些 DLL,则这些 DLL 会使用所有可用的 TLS 插槽。最终,SQL Server 无法再加载需要 TLS 插槽的 DLL。

解决方案


备注此分辨率仅适用于 Windows 服务器 2003。如果使用 Windows 2000,请按照"解决方法"部分中的步骤操作。

Windows Server 2003 的修补程序信息

微软提供了受支持的修补程序。但是,此修补程序旨在仅更正本文中描述的问题。仅此修补程序应用于遇到此特定问题的系统。此修补程序可能会接受其他测试。因此,如果您未受到此问题的严重影响,我们建议您等待包含此修补程序的下一个软件更新。如果修补程序可供下载,则此知识库文章顶部有一个"可用的修补程序下载"部分。如果未显示此部分,请与 Microsoft 客户服务和支持部门联系以获取修补程序。备注如果发生其他问题或需要进行任何故障排除,您可能需要创建单独的服务请求。通常的支持成本将应用于其他支持问题和不符合此特定修补程序的问题。有关 Microsoft 客户服务和支持电话号码的完整列表或创建单独的服务请求,请访问以下 Microsoft 网站:备注"可用的修补程序下载"窗体显示修补程序可用的语言。如果您看不到您的语言,这是因为该语言没有修补程序。
先决条件
您必须在服务器上安装 Windows Server 2003 服务包 2。有关详细信息,请单击以下文章编号以查看 Microsoft 知识库中的文章:
889100如何获取 Windows 服务器 2003 的最新服务包
重启信息
应用此修补程序后,必须重启计算机。
修补程序替换信息
此修补程序不会替换任何其他修补程序。
文件信息
此修补程序的英文版本具有下表中列出的文件属性(或更高版本的文件属性)。这些文件的日期和时间列在协调世界时间 (UTC) 中。当您查看文件信息时,它将转换为本地时间。要查找 UTC 和本地时间之间的差异,请使用"控制面板"中的"日期和时间"中的"时区"选项卡。Windows 服务器 2003 与服务包 2,基于 x86 的版本
文件名文件版本文件大小日期时间平台
Ntkrpamp.exe5.2.3790.41772,348,03229-Oct-200719:01x86
Windows 服务器 2003 与服务包 2,基于 x64 的版本
文件名文件版本文件大小日期时间平台
Hal.dll5.2.3790.4225280,06428-Jan-200810:42x64
Ntkrnlmp.exe5.2.3790.42254,603,90428-Jan-200810:42x64
Ntoskrnl.exe5.2.3790.42254,533,76028-Jan-200810:42x64
Windows 服务器 2003 与服务包 2,基于 IA64 的版本
文件名文件版本文件大小日期时间平台
Ntdll.dll5.2.3790.42251,636,86428-Jan-200810:40IA-64
Ntkrnlmp.exe5.2.3790.42256,568,96028-Jan-200810:40IA-64

解决方法


您可以使用以下方法之一来解决此问题。 我们建议您使用方法 1,因为扩展的存储过程功能可能会在 SQL Server 的未来版本中删除。

方法 1

  1. 使用sp_OACreate存储过程来确定 SQL Server 加载到 SQL Server 进程中的 DLL。为此,请按照以下步骤操作:
    1. 打开 SQL 探查器,然后连接到 SQL Server 的实例。
    2. 在"跟踪属性"对话框中,指定跟踪的名称,指定 SQL 探查器保存跟踪的位置,然后单击"运行"。
    3. 运行 SQL 探查器一段时间后,分析跟踪以查找sp_OACreate存储过程的发生。
    4. 请注意sp_OACreate存储过程的每个匹配项的第一个参数。备注第一个参数指示 OLE 对象的编程标识符 (ProgID) 或 OLE 对象的类标识符 (CLSID)。
    5. 确定包含此 OLE 对象的 DLL。
    备注在启动 SQL Server 服务时,可以使用 SQL 探查器监视 SQL Server 的实例。
  2. 请确保您已启用OLE 自动化过程选项。有关如何确定是否启用OLE 自动化过程选项以及如何启用OLE 自动化过程选项的详细信息,请访问以下 Microsoft 开发网络 (MSDN) 网站:
  3. 在 SQL Server 2008 R2、SQL Server 2008 或 SQL Server 2005 的 SQL Server 管理工作室中,或在 SQL Server 2000 的 SQL 查询分析器中运行以下语句。备注 例如,以下代码演示如何加载 Wbemdisp.dll 文件。
    DROP PROC sp_Load_DllGOCREATE PROC sp_Load_DllASdeclare @WmiServiceLocator int, @hr intexec @hr = sp_OACreate 'WbemScripting.SWbemLocator', @WmiServiceLocator output if @hr = 0 raiserror ( 'wbemdisp.dll loaded into sql address space by startup procedure sp_Load_Dll, Object Info: %d' , 10 , 1 , @WmiServiceLocator) --WITH LOGWHILE 1=1 WAITFOR DELAY '01:00:00'GOEXEC sp_procoption 'sp_Load_Dll' , 'startup' , 'true' GO
    这些语句创建一个存储过程。这些语句还允许存储过程在 SQL Server 服务启动时运行。此存储过程执行以下操作:
    • 加载 Wbemisp.dll 文件。
    • 将 Wbemisp.dll 文件保留在内存中,因为语句不会退出。
    只要 Wbemdisp.dll 文件在内存中,其他语句就不会再次加载 Wbemdisp.dll 文件。因此,SQL Server 不会调用 Wbemdisp.dll 文件的TlsAlloc函数和TlsFree函数。备注您必须更新代码以加载在步骤 1 中确定的 DLL。
  4. 将语句添加到步骤 3中的sp_Load_Dll存储过程。这些语句加载您在步骤 1 中确定的 DLL。
  5. 重新启动 SQL Server 服务。
  6. 验证 SQL Server 是否在内存中加载 Wbemdisp.dll 文件。为此,请按照以下步骤操作:
    1. 打开 SQL Server 错误日志文件。
    2. 搜索以下消息:
      wbemdisp.dll 通过启动过程加载到 sql 地址空间sp_Load_Dll
      备注此消息指示 SQL Server 已加载 Wbemdisp.dll 文件。
    3. 在命令提示符下,运行以下命令:
      tasklist /m
    4. 在获取的结果中,找到 Sqlservr.exe 进程,然后验证 Wbemdisp.dll 文件是否列出。备注如果列出了 Wbemdisp.dll 文件,则 SQL Server 已加载 Wbemdisp.dll 文件。

方法 2

  1. 使用sp_OACreate存储过程来确定 SQL Server 加载到 SQL Server 进程中的 DLL。为此,请按照以下步骤操作:
    1. 打开 SQL 探查器,然后连接到 SQL Server 的实例。
    2. 在"跟踪属性"对话框中,指定跟踪的名称,指定 SQL 探查器保存跟踪的位置,然后单击"运行"。
    3. 运行 SQL 探查器一段时间后,分析跟踪以查找sp_OACreate存储过程的发生。
    4. 请注意sp_OACreate存储过程的每个匹配项的第一个参数。备注第一个参数指示 OLE 对象的编程标识符 (ProgID) 或 OLE 对象的类标识符 (CLSID)。
    5. 确定包含此 OLE 对象的 DLL。
    备注在启动 SQL Server 服务时,可以使用 SQL Server 探查器监视 SQL Server 的实例。
  2. 创建扩展的存储过程。扩展存储过程包含一个函数,该函数加载您在步骤 1 中确定的 DLL。
  3. 将扩展的存储过程添加到 SQL Server。
  4. 在 SQL Server 中,使用sp_addextendedproc系统存储过程在扩展的存储过程中注册函数。
  5. 使用sp_procoption存储过程使扩展的存储过程能够在 SQL Server 服务启动时自动启动。
  6. 重新启动 SQL Server 服务。
当 SQL Server 在扩展的存储过程中执行该函数时,SQL Server 通过调用 LoadLibrary API 来加载 DLL。

状态


这在 SQL Server 中不是问题。这是 Windows 服务器 2003 和 Windows 2000 中的问题。此问题不会出现在 Windows Vista 或 Windows 服务器 2008 中。

参考


有关TlsAlloc功能的详细信息,请访问以下 Microsoft 开发人员网络 (MSDN) 网站:有关TlsFree功能的详细信息,请访问以下 MSDN 网站:有关sp_OACreate存储过程的详细信息,请访问以下 MSDN 网站: