这个周末我发现了SQL Server 2014里Hekaton的一个有趣副作用,很遗憾它会负面影响你数据库的目标恢复时间(Recovery Time Objective,RTO)。你已知道,对于每个本地编译表和存储过程,Hekaton都会创建一个DLL,这些都是以C语言代码实现的。这些DLL文件载入sqlservr.exe的执行空间。你可以用下列的查询通过DMV sys.dm_os_loaded_modules 来查看当前载入的Hekaton表:
1 SELECT * FROM sys.dm_os_loaded_modules 2 WHERE description LIKE 'XTP%'
在CTP2里,我遇到的副作用是:当你删除对应表后存储过程时,载入的Hekaton的DLL文件并没有卸载掉。假设你创建了一个本地编译的存储过程,在一定时间后你想删除那个存储过程来重建,为了获得更好的本地编译执行计划(在Hekaton里的当前执行时间并不支持重编译)。在那个情况下,你的存储过程的老实现方式还在 sqlservr.exe 的执行空间里,在消耗额外的内存。当你删除表时也会同样发生,DLL本身还在内存里!
去除这些额外不需要的DLL文件的唯一方法是让你的整个数据库离线,再联机。然后当你查询DMV sys.dm_os_loaded_modules 时,你会看到只有当前实现的本地编译表和存储过程被载入 sqlservr.exe 。 当你没有特定的可用维护界面时,这是你Hekaton第一个遇到的糟糕问题。
但事情变得更加糟糕:当你重启SQL server,SQL Server会编译和链接 每个 原先已经生成的DLL。编译和链接每个Hekaton的DLL会占用一些CPU时间,在此期间你的数据库是处理恢复阶段,从用户角度来说,意味着你的数据库是不能访问的!即使当你尝试访问基于传统硬盘的表,在此期间,你会得到类似如下的错误信息:
Msg 922, Level 14, State 1, Line 1
Database ‘HashCollisions’ is being recovered. Waiting until recovery is finished.
你也可以在C:/Program Files/Microsoft SQL Server/MSSQL12.MSSQLSERVER/MSSQL/DATA/xtp目录里看到原先老的.c,.obj和.dll还在,因为对于下次SQL Server的启动它们是需要。
假设你创建50个本地编译表和存储过程并立即删除。在那个情况下你在结束100个DLL文件,这些文件会在SQL Server启动期间编译和连接。我在虚拟机上测试SQL Server 2014的CTP2,我的数据库在69秒后才联机!
因此请留意这些副作用,因为它们会大幅度降低你的目标恢复时间(RTO)!设想下你在群集故障转移,在那个情况下, 每个 DLL必须在你另外的群集点编译和链接好,对于的终端用户,你的数据库才会 联机 。我说过,这是我在SQL Sever 2014 CTP2里遇到的问题,因为我希望在RTM版本发布时,微软对这方面会有所改进!
感谢关注!