现在的位置: 首页 > 综合 > 正文

Yukon(SQL Server 2005) CLR 基本架构 (翻译)

2013年03月10日 ⁄ 综合 ⁄ 共 3233字 ⁄ 字号 评论关闭

Yukon CLR 基本架构

 

概述

 

随着SQL Server “Yukon” Beta1(也许也有人说:SQL Server2005)的推出,人们发现微软在Yukon中集成了非常多的新功能,其中最引人瞩目的是在数据库引擎中集成了对Windows .NET Framework Common Language Runtime (CLR 公用语言运行环境)的支持。在20007月的专业开发者大会(PDC)上,微软第一次向世界展示了这个新特征。

 

作为SQL Server 2000的开发人员,编写数据库的应用程序往往只局限于T-SQL,而宿主了CLRYukon,引入了许多强大的新特征,我们可以用Visual Basic.NET, C# 等面向对象的语言完成以前T-SQL难于完成的任务。比如,以前我们如果要调用一些系统函数(WIN32APICOM组件),我们必须写扩展存储过程,通过ODS(Open Data Services)开放式数据服务层和数据库引擎交互,而现在我们通过CLR提供的托管对象可以非常方便的调用Windows .NET Framework Class Library (FCL).NET框架类库。这些托管对象包括:

 

·         托管存储过程

 

·         托管函数

 

·         托管触发器

 

·         自定义复杂数据库类型

 

·         自定义复杂类型索引

 

·         自定义集合函数

 

首先,我们要了解数据库引擎集成CLR的优势和CLR可以提供的一些关键特征。

 

CLR是一个托管的运行环境,所谓“托管”的意思是许多任务过去需要程序员负责的(比如内存管理)现在可以委托CLR来处理。作为托管代码的一部分,CLR控制代码执行过程中的每一个部分,同时CLR是基于类型安全(CLR扮演了代码验证的角色)和安全许可的环境――彻底地编译为本地代码(Native Code)。CLR可以“辨识”出运行的代码是否企图直接处理内存或调用非.NET的代码。

 

.NET的可执行代码在CLR中被装载为程序集(assemblies)的形式。程序集中包括中间语言代码(IL指令),描述代码的元数据(Metadata)和其它资源(比如:引用其它文件列表),源代码并不是直接保存在程序集中,而是编译为一种CLR可以读懂的中间语言(IL,在程序执行之前CLR通过即时编译(JIT)将代码转换为本地代码(通常是X86代码)。如果代码在本地运行,这个本地代码会被加载到一段拥有生命周期的缓存,这就是说.NET的代码是非解释型的――它在运行时最终会被编译成本地代码。

 

CLR拥有自己管理内存的方式:如果一个对象或一组对象没有被其它运行的代码引用,从理论上说要回收所有不在使用的内存,但是对于CLR,内存只是在运行资源不足时才会被回收,CLR在需要额外的内存资源时才调用垃圾收集器,这种内存管理机制使程序员不用担心内存泄漏。

 

所有的代码都运行在自己的应用程序域(Application  Domain。在CLR环境中,应用程序域的作用是在单个进程中宿主不同的应用程序域,用来隔离不同的执行代码 ―― 换句话说,在一个应用程序域中的运行失常的代码不会影响其它应用程序域中运行的代码。 每个进程中都存在至少一个拥有CLR的应用程序域, 当然, 也可以有多个――这是由寄宿进程和运行的托管代码决定的。当一个程序集被CLR加载时,是指被加载(即时编译(JIT))到一个指定的应用程序域中,同时这个程序集也可以被加载到同一个进程中不同的应用程序域中。也可以加载一个中立的程序集――在这种情况下,一个程序集的单独备份可以为一个进程中所有的用户提供服务。

 

寄宿

 

宿主CLRYukon数据库引擎有一些特殊需求。数据库引擎对于资源管理是非常谨慎的――比如:通过直观推断数据库使用的资源变化,在不同的缓存之间移动内存。因此,应该在数据库引擎和CLR的资源管理方式保持某种默契关系。

 

CLR1.01.1的版本中, CLR提供一个API来加强进程的控制――比如判断CLR线程池的大小。当然,这个API并非强大到可以替代CLRYukon中的作用, 比如:考虑以下几种情况

 

内存管理

 

Yukon 数据库引擎完全控制已经被分配的内存空间,在不同的缓存之间切换,比如:存储过程缓存和数据缓存。在这种情况下,Yukon 数据库引擎需要有更加灵活的方法来运行CLR的垃圾收集器,同时对CLR垃圾收集器发生的条件,分配或释放多少内存产生影响。

 

线程管理

 

CLR通过线程技术完成异步任务和多元化的并发操作。CLR拥有自己的托管线程池,用来计划执行线程池中的任务。然而, SQL Server使用更精致的纤程机制(mechanism of fibres)来应对可能的巨量并发请求,因此,SQL Server需要接管CLR的线程管理。

 

并且,由于存在CLR的运行机制和SQL Server的需要之间的微妙关系,我们意识到这需要对CLR的寄宿接口进行扩展。因此随着Whidbey(是微软Visual Studio .NET 的下一代版本)的发布.NET会提供更多和更强大的寄宿APIYukon发布的.NET版本和Yukon支持的.NET版本将保持一致)

 

Whidbey 寄宿 API 的特征

 

Whidbey中,有7处寄宿API的关键部分得到了扩展:

 

1.        内存管理

 

现在CLR允许宿主机(Yukon)取代WINDOWSC运行库分配常规内存,因此现在宿主机可以控制和判断内存的分配或释放多少。同时,宿主机可以用自己的内存通知机制取代标准的内存通知机制,从而可以触发垃圾收集器。宿主机也可以不进行内存分配,这时CLR会警告宿主机内存分配失败的结果,这样宿主机可以采取相应的策略。

 

Yukon通过这种策略施加对内存分配的影响,这样来控制缓存的大小和预防潜在地可能造成内存分页的操作。

 

2.        线程

 

现在,CLR从线程中抽象出一个新的概念叫任务(Task)。宿主机可以控制任务的分配和存储,包括任务的开始,结束和同步等等。同时CLR和宿主机相互告知显著的事件(比如当任务从可执行到不可执行的状态改变,反之亦然,宿主机也要通知CLR)。宿主机可以提供配置CLR线程池工具。这样的集成级别允许Yukon延续自己的轨迹同时允许CLR运行2个异步任务。

 

3.        I/O实现

 

寄宿API现在可以为了CLR的利益配置宿主机I/O同步,在I/O操作完成后通知CLR。这样Yukon可以完全了解进程内所有I/O的操作。

 

4.        同步

 

如果CLR放弃对任务的控制,就必须运许宿主机提供同步不同任务的手段。因此,宿主机必须提供一个方法来建立:临界区(critical section),互斥体(mutexes),事件(events),读写锁(reader/writer locks)和监控器(monitors)。 宿主机通过这些控制方式,就完全可以检测死锁操作。这样Yukon就可以正确的处理CLR请求的计划任务从而提高整体运行的可靠性,解决同步过程中的死锁。

 

5.        托管和非托管

 

宿主机托管代码完成P/Invoke调用,转换为本地机器码时可能会有问题,因为目前还没有在代码运行时检测何种锁被丢弃的方法。新的宿主API中允许任务在脱离CLR控制时通知宿主机。比如:当代码运行在CLR外部时,Yukon会调整任务到non-fibre scheduled 任务。同样这些非托管的代码块对数据库引擎是透明的-例如:数据访问的API,这些和其它的非托管代码是区别对待的。

 

6.        应用程序域中性代码

 

应用程序域中性允许加载一个程序集(assembly)时所有的应用程序域共享一个单独的即使编译的程序集镜像代码。在Whidbey以前版本,CLR3个选项:加载所有程序集的应用程序域中性;不加载程序集的应用程序域中性;只加载强名称程序集的应用程序域中性。

 

抱歉!评论已关闭.