首页 | 免费域名 | 个人服务器 | 一流信息监控拦截系统 | 虚拟主机知识库 | ASP 空间 | ASP技术大全 | 下载中心 | 客户服务中心
  7i24 > ASP技术大全 > ASP与数据库 > 微软数据库文章 >
    7i24 .Com  
  数据访问技术

7i24.Com不停为您服务
数据访问技术
通常,您不会将 Pi 计算到小数点后第 n 位,或是没事训练神经网络。您是在访问一个数据库,对它进行查询和更新,并且在访问数据库方面遇到麻烦。对数据访问技术的正确使用,加上对后端数据库的了解,对保持高性能和持续可扩展性需求很关键。下面是可能想从业务层考虑的一些问题。

一般参考

信息:使用数据库组件和 MTS 的技巧 (Q169210)(英文)
ADO 示例与最佳练习(英文),作者 William R. Vaughn,Apress! 出版。

使用最新版本的 Microsoft 数据访问组件

Windows 2000 附带了“Microsoft 数据访问组件 (MDAC) 2.5”。该 MDAC 版本包括了改进和增加的功能,例如不需要创建文件的 XML 集成、URL 资源支持和层次结构命名空间导航。

MDAC 2.5 也可用于运行 Windows NT 4.0 和 Windows 9x 的计算机。参见下面的链接可以获得更详细的信息,并可下载。

MDAC 包括 MS ODBC 和 OLE DB 组件。请使用 MDAC 软件包中附带的最新版本组件。不要混合和匹配 ODBC 及 OLE DB 组件来创建“新口味”。MDAC 解决方案经过测试,并通过离散的 DLL 包进行部署。下面的关键词已经过测试。其他配置很有可能偶尔使用。

参考

从 www.microsoft.com/data/ 可获得最新的 MDAC 版本和信息。

尽快将 ADO 对象关闭并设置为 Nothing

在使用 ADO 对象时,请确保在用完后立即显式调用 Close 方法并将使用的记录集和连接设置为 Nothing。一种最常见的 ADO 编码错误,是在用完对象后忘记关闭。虽然显式关闭对象不是强制的,但是这么做可能是成功或失败的应用程序之间的差别。

将 ADO 对象设置为 Nothing 会清除存储在 Err 中的错误信息。如果清除了错误处理程序中的 ADO 对象,可能会带来问题。因此,如果希望存储该信息,请在关闭对象之前的 ADO 对象清除过程中,将 Number、Source 和 Description 存入变量。

注意 如果要返回断开连接的记录集,则不应该关闭记录集。关闭记录集则会取消它的内部高速缓存,因此只要将它的 ActiveConnection 设置为 Nothing 就可以了。

操作方式

要确认是否正确关闭了 Connection 或 Recordset 对象,可以实现下面的代码:

  If Not oMyRecordset Is Nothing Then
   If oMyRecordset.State <> 0 Then oMyRecordset.Close
   Set oMyRecordset = Nothing
  End If

正如以前所提到的,不能在将返回给客户机的记录集中调用 Close 方法。

避免复用 ADO 连接对象来执行多个命令

避免在多个数据库命令上复用打开连接对象。也就是说,每当需要时请打开、使用和关闭连接。

在数据库访问对象中封装 ADO 代码是不会有问题的,原因是这些封装是在无状态方式下执行的。但是,如果对象中有 ADO 对象,尤其是在类级别上存储了 ADO 连接,那么请参考下面的“知识库”文章。主要问题在于如何在执行其他任务时保持打开的数据库游标。如果正在检索要发送到客户机的记录集,那么请从 RDBMS 断开它们的连接。

实现一种复用 ADO 连接对象的方式会大大加重维护任务,并且可能导致通过良好封装能够避免的设计错误。ADO-OLE DB 层实现了它自己的内部连接池。该连接池使下面的流程成为访问服务器上数据的首选方式:

创建 ADO 连接


打开连接


使用它


关闭连接


将 ADO 连接对象设为 Nothing
开发和维护将更方便,并且更快速和可扩展。

参考

基本知识:在 MTS 事务中重用 ADO 连接 (Q234218)(英文)

使用 OLE DB 提供程序而不是 ODBC 驱动程序

在通过 ADO 使用 OLE DB 时,可以选择使用本机 OLE DB 提供程序,或者选择能够转换并将所有调用转发给 ODBC 驱动程序的指定的 OLE DB 提供程序(MSDASQL — 即“OLE DB Provider for ODBC Drivers”) 。

如果有的话,可以使用能够与数据库进行本机对话的 OLE DB 提供程序,以便获得更高的性能、更多功能、转发兼容性以及参与活跃的 OLE DB 第三方解决方案市场。

操作方式

如果下面的任何条件为真,就说明正在使用 ODBC:

您在 ODBC 管理单元中配置“系统”、“用户”或“文件 DSN”以便使用某个应用程序。


您的连接字符串中包括“MSDASQL”或“DSN”。


没有在连接字符串中指定提供程序。
如果使用的是 ODBC,请确定本机提供程序是否访问有相同功能支持的同一数据库。要查看的关键部位是:连接池、分布式事务支持等等。

参考

MDAC 伙伴领域:目前市场上的 OLE DB 产品(英文)
针对 ODBC 编程人员的 OLE DB(英文)
Merant Corporation(英文)

使用通用数据链接 (UDL) 文件来保存连接字符串

使用 UDL 文件存储数据库连接的方式和使用“ODBC 数据源名称 (DSN)”非常相似。UDL 文件存储 OLE DB 连接信息,例如提供程序、用户名、密码和其他选项。用存储在该 UDL 文件中的信息可以打开 ADO 连接,从而允许管理员在需要的情况下更改它,并且避免了打开注册表或者使用 ODBC。

确保软件包身份有权读取该文件,并且恰当的管理员有权读写该文件(实际上是编辑它)。如果是 Web 站点的情况,请确保 DLL 和 UDL 文件不在虚拟目录中,否则就可以通过 Web 直接访问和下载它们了。

要创建 UDL 文件,请创建一个空文件并用 UDL 扩展名命名它。通过双击该文件输入所有信息,然后在它的属性表中输入信息,如下面所示。

要用 UDL 打开 ADO 连接,请用以下语法:

  oOConnection.Open "FILE Name=C:\SecureStuff\MyDataLink.UDL"

您可以要求管理员将 DLL 和 UDL 都放在同一安全目录中,在这种情况下必须对完整的 UDL 文件路径进行硬编码。如图 6 所示,您必须需要设置“允许”保存存储完整连接字符串的密码。系统会发出警告,指出您正以纯文本方式将密码存储在文件中。如果对此文件设置了正确的 NTFS 权限,这不会成为问题。

不要将 UDL 文件放在文件共享区中,以避免其他服务器都能打开它。如果有许多服务器,请在每个服务器上保存一个 UDL 文件的副本。



图 6. 设置“允许”保存密码

性能可能是倍受关心的问题;毕竟这是对磁盘的访问,对吗?实际上在使用该技术时,文件系统将在内存中缓存该文件,而且强度测试表明,如果完全可以度量的话,在比较它访问“系统”或访问“文件 DSN”时,性能的下降是可以忽略的。

使用存储过程而不是动态 SQL 字符串

使用存储过程有许多优点,包括:

通过将概念数据命令与命令的实现隔离,添加来自数据库架构的抽象级别。存储过程还使应用程序代码减少耦合,使测试更方便。


提供更好的代码分布。与构造、发送和分析 SQL 字符串,加上上面的所有工作相比,包装参数和返回结果集的逻辑要更少。


由于它们的执行计划是预编译的,因此在运行时会更有效。动态 SQL 串必须包括能够使它们的查询计划优化缓存的参数。


允许更多的运行时灵活性 — 一旦被部署后,要更改在 DLL 中编译的 SQL 串,比更改存储过程更难。


由于它们的参数已经声明了方向和类型,因此允许更好的工程代码。


允许更好的安全配置。使存储过程限制在不同的应用程序/软件包标识或者限制在不同服务器应用程序上的不同连接串,通常是更容易维护些。


如果您已经用了存储过程,那么在需要改变时完成的速度会更快。
操作方式

添加存储过程是很方便的。只要查看 T-SQL 中的 CREATE PROCEDURE 语句,并按那些准则做就可以了。如果在数据访问对象的实现中选择使用存储过程,那么为了维护起见,请保持它们的一致性。请把它们作为一个整体使用或者完全不用。这有助于排除故障,有助于为今后的开发而构造的功能,不必预言动态 SQL 和存储过程的混合。

使用存储过程的 OUTPUT 参数以获得单行返回值

在从数据库查询中返回单项数据或者单行时,请使用 OUTPUT 参数而不是结果。OUTPUT 参数不使用在服务器上构造的任何游标/结果集,并且使组件和数据库之间能进行更有效的数据传输。

但是,根据体系结构的不同,您可能不希望单行或多行查询有不同的代码路径。必须同时考虑数据库架构的动态性。有了更强大的类型化存储过程后,它们就会更紧密地耦合到您的数据库。和其他情况一样,灵活性和性能是密切相关的。

不要在单元之间传送 ADODB.Connection 对象

在数据库连接的交叉单元/进程汇集上需要注意一些问题。我们建议您不要这么做。汇集和数据库驱动程序的局限性,可能会引起一些意想不到的行为。

如果这么做,那么可能需要自己管理连接池并且实现自己的连接分配程序。在大多数情况下,自己提供池功能可能太困难了。通常情况下,即使是最严格的资源管理器,也会允许在同一单元上发生的不同活动上有不同的连接。如果 ODBC 驱动程序或者 OLE DB 提供程序允许池(通常是这样的),那么请关闭连接再在需要的时候打开它们,并且允许 OLE DB/ODBC 层提供基本结构。

如果使用交叉单元/进程汇集的原因是为了提供正确的连接串,那么请按前面讨论的方式,在 SPM 中存储字符串,然后按我们建议的方式重新在每个方法调用中创建连接。

参考

Microsoft 数据访问组件 (MDAC) 中的池(英文)

记住 ACID 规则

请记住事务操作的规则,它通常描述为 ACID 属性:原子性、一致性、隔离性和持久性。在应用程序设计中,可能会遗忘的是事务的原子性和一致性属性需要所有操作“可串行化”。串行化的操作在所有有关的资源上强制锁定机制。如果事务要超过其锁定的范围,那么可能需要多个事务。

所有书都是有关该主题的。只要记住这些概念是紧密相关的就可以了:事务、ACID 属性和锁。

参考

ACID 文化(英文)
事务处理原理,作者 Philip A. Bernstein 和 Eric Newcomer (ISBN: 1558604154)(英文)

这些书是理解数据库和事务的坚实基础,但它们是完全面向更理论的团体,并且很难读懂。

事务处理:概念和技术,作者 Jim Gray 与 Andreas Reuter (ISBN: 1558601902)(英文)
关系型数据库系统简介,作者 C. J. Date (ISBN: 020154329X)(英文)

使用 SetComplete 和 SetAbort 对事务表决

无论您调用这两个方法中的哪一个,都是对当前事务的投票表决,并且告诉 COM+/MTS 您已经准备停用了(被取消,或在 VB 对话中设置为 Nothing)。所有方法都应该将它们的票投向当前的事务。这样可以获得更好的逻辑封装,从而提高可重用性或集成的几率。

在开发代码时,投票是件好事。它迫使您考虑错误情况并且考虑资源管理。一旦所有参与的方法调用都投票放弃事务,该事务便死亡。当方法退出时,对象就变成可以复用。在调用 SetAbort 后,没有任何理由继续对事务的任何处理。

请记住,在方法调用完成后将停用对象,从而要求无状态实现。请参见上面的内容,了解有状态/无状态之间的详细区别。

操作方式

在从方法返回之前,请调用 GetObjectContext.SetComplete。在错误处理程序中,在调用 Err.Raise 之前先调用 GetObjectContext.SetAbort。这可以确保进行了与调用者无关的正确表决。当然可以实现更复杂的表决方案,但是这里描述的方案是个好的开端。

参考

MSJ:Microsoft Transaction Server 如何改变 COM 编程模型(英文)
MSJ:用 Visual Basic 和 SQL Server 7.0 编写 MTS 风格的事务(英文)

理解使用 Command.Parameters.Refresh 的含义

ADO Command 对象可以用于执行参数化的存储过程。有两种方式可以使 Command 对象知道参数及其数据类型、方向和其他信息。

第一种方法:.Parameters.Refresh,要求对数据库引擎的调用,以从存储过程的声明中检索该信息。请注意该方法要求 Command 的 ActiveConnection 有开放的连接对象或者正确的连接串。

第二种方法是指定参数信息本身。在这种情况下,您必须知道要添加的参数的确切名称、类型和方向,然后重复调用 Parameters.Append 来填充该集合。

问题

在调用 Parameters.Refresh 方法时,实际上是在数据库服务器上执行对参数信息的查询。在决定是否使用 .Refresh 方法之前,请考虑网络流量、组件的运行时适应性和数据库的相邻性(通过与 DB 的通信开销来衡量),以及有精确参数信息的好处。

该决策是运行时灵活性和性能之间的折中。添加硬编码值本身通常会更快些,但是任何其他方法(比如从 SPM 中检索这些值)可能比调用 .Refresh 方法要慢一些。但是,如果将 MDAC 代码包装在数据访问帮助器类中,那么您会发现 .Refresh 方法可以获得更大的运行时灵活性,其结果需要重新编译和重新部署组件的频率会减少。

对该机制的了解应该是实现中的重要因素。.Refresh 方法有助于获得高度的封装,同时不必与后端紧密耦合。

参考

MIND:使用 ADO 2.1 的存储过程:增强刷新方法(英文)

不要用服务器端组件上的数据环境

Visual Basic 6.0 “数据环境”对使用 ADO 执行对数据库的操作有很大的帮助。但是,对于要在 MTS 或 COM+ 下运行的组件来说,请使用直接 ADO 代码,它在并发环境下会更稳定。如果在帮助器类或函数中有包装好的 ADO,那么开发会比“数据环境”下更快和更方便。

详细信息

“数据环境”用它自己的、与连接和对象复用有关的策略,来包装 ADO。“数据环境”使用的某些实现是受客户端技术决策驱动的。当用作为服务器端工具时,某些设计决策的实现并不十分可靠。如果您已经在服务器上的分布式解决方案中使用了“数据环境”,那么在应用程序生命周期的某些时候可能出现不稳定。

操作方式

请不要依赖“数据环境”提供的抽象层次,请为数据访问代码构造能够在没有任何中间处理程序的情况下直接处理数据访问组件的包装程序。纯 ADO 代码是 MTS 友好的,并且符合在多线程环境下正常工作的基本需求。

理解改变事务隔离级别的影响

所有从事务 COM+ 对象初始化的 SQL Server 事务,都将得到指定可串行化隔离的提示。默认为 Read Committed。这是最高隔离级别,它可以确保所有方案的一致性。

但是,这意味着在从事务 COM+ 对象执行数据库操作时可以看到更多的锁。这些锁非常重要。它们的作用是保证数据操作的一致性。但是,如果在目标中性能比一致性更重要,则可以调整隔离级别。换句话说,当不一致的成本低于低性能的成本时,只要改变隔离级别就可以了。

为优化性能而改变隔离级别的方法有好几个,但是必须理解这么做的含义,它可能导致将错误的数据发送给客户、意想不到的计算结果,等等。

问题

确定某块数据是否适合更少限制的隔离级别的最简便方法,要求确定将应用程序逻辑显示为不一致结果的全部影响。对于某些应用程序和使用情况来说,某个级别的错误或误算,如果只是损失些精度,则是可以接受的,只要数据不是旧的就行。

不同的隔离级别可以防止不同的危险,出现这种危险的情况是来自两个事务的、对同一块数据的、连续的读写操作。例如:

读后写(在使用“可串行化”级别时得到保护)。


写后读(在“游标稳定性”和“可串行化”级别时得到保护)。


写后写(在“浏览”、“游标稳定性”和“可串行化”级别下得到保护)。
作为一个准则,请评估每个命令需要的精度,而不是在应用程序范围决定它。如果精度不是问题,那么数据库访问方法则适合更低的隔离级别和更好的可扩展性。但是应该准确地记录您的决策,然后按您的规格来解释它。

操作方式

有两种方式可以在命令中更改隔离级别。

设置事务的隔离级别。对连接所执行的所有命令将共享它。在 SQL Server 上,在打开数据库连接后,执行下面的命令:
oConn.Execute "SET TRANSACTION ISOLATION LEVEL x"
此处“x”代表需要的隔离级别。

另一种方式是在实际语句或存储过程中指定一种提示。
参见联机 SQL Server 书籍,了解 WITH 关键词和正确的隔离级别值。其他 RDBMS 和资源管理器,在事务、连接和命令上实现不同的隔离。
参考

SQL Server:设置事务隔离级 (T-SQL)(英文)
SQL Server:锁定提示(英文)
SQL Server:sp_lock (T-SQL)(英文)

“记住 ACID 规则”一节下面的链接也是很有用的。



  2002年1月8日  阅读 3479 次  发送此页给朋友  来源:    版权争议  删除

相关文章:   近期热点:

上一篇: 优化Microsoft Access提高速度
下一篇: 建立高可用性的数据库群集
返回上一层...
搜索:

(C)2004-2022 7i24.Com 保留所有权利