COM+ 事务管理操作
COM+ 注册数据库 (RegDB) 是可以参与 COM+ 事务的事务处理资源管理器。 这可用于在事务中执行管理操作,所有配置更改都作为原子操作提交或中止,即使在多台计算机上操作也是如此。 在某些情况下,这样做可能非常有益,但是应该考虑隔离和阻止行为,并且在事务中执行管理任务确实涉及对正常管理编程模型的轻微更改。
在事务中执行管理操作的好处
- **数据一致性 — **事务中执行的管理操作作为一个整体提交或中止,但是如果存在一些非事务性 COM+ 目录资源,就不是这种情况了。 (请参阅下面的非事务性 COM+ 目录资源。
- **跨多台计算机进行一致的部署—**如果要跨多个服务器部署 COM+ 应用程序,可以保证所有服务器都保留相同的配置。
- **扩展和性能 — **在事务中执行多个操作时,将同时对 RegDB 执行所有写入操作。 对 RegDB 的持久写入操作相对成本高昂;如果要对 RegDB 进行多次写入,则可以从一次性执行所有这些操作(而不是每次调用 SaveChanges)中获得很大的性能优势。
RegDB 的隔离行为
为了确保适当的数据一致性和可序列化的事务,RegDB 在事务中执行管理操作时强制实施特定的阻止和隔离行为。
每当在事务中执行工作的组件调用会导致写入 COM+ 目录(如 SaveChanges、InstallApplication 或 InstallComponent)的任何方法时,都会对 COM+ 目录服务器代码执行编写器锁定,此操作将阻止任何其他编写器进入,直到当前事务提交或中止为止。 也就是说,仅当编写器具有正确的事务相关性并参与当前事务时,才能进入。
读取器未被阻止。 但是,读取器看到的数据不会反映事务中所做的任何临时更改,直到实际提交该事务。 参与该事务的任何组件在读取数据时都会看到临时数据状态,但事务外部的所有组件只有在事务完成后才会看到这些更改。
SaveChanges 行为
为了实现上述隔离行为,RegDB 有效地提供由事务中的组件执行的缓存。 这会更改 SaveChanges 方法的行为。
通常,如果不存在事务,则在调用 SaveChanges 时,所有挂起的更改都会写入目录,并且在完成所有写入之前,SaveChanges 不会返回。 这可以保证,如果对 SaveChanges 的调用成功返回,则可以调用 StartApplication,并且将使用新数据激活应用程序。
但是,在事务中,SaveChanges 仅影响缓存(而不是 RegDB 本身),无论所有更改是否已以事务方式提交到 RegDB,SaveChanges 都会立即返回。 不能保证 StartApplication 在 SaveChanges 返回后使用新数据。 如果需要在此上下文中调用 StartApplication,建议等待一段时间再执行此操作。
事务超时期限
如果在事务中执行大量管理操作,则可能是长时间运行的事务。 在这种情况下,事务超时值可能是个问题。 这由为启动事务的组件设置的事务超时值或运行该组件的计算机的计算机范围超时设置确定。 如果在事务中执行大量操作,建议将适当的事务超时期限设置为足够长的值,必要时在完成后还原原始设置。
非事务性 COM+ 目录资源
注册表、文件系统和 Windows Installer (MSI) 是非事务性 COM+ 目录资源。
注意
如果发生中止事务的错误,则可能不会回滚对这些资源的更改。
如果从 .msi 文件安装现有 COM+ 应用程序时出错,则应用程序不会显示在组件服务管理单元中,可能会显示在“添加/删除”程序中,在这种情况下,需要手动将其删除。
在系统挂起时恢复
如果在事务中执行管理操作的组件在目录服务器代码上持有编写器锁时挂起,则会阻止其他人对目录进行任何更改。 如果发生这种情况,可以通过关闭并重启系统应用程序来清除目录上的锁定。
使用 TransactionContext 对象编写脚本
在事务中执行管理操作的一种简单方法是使用 TransactionContext 对象来控制事务。 例如,以下 Visual Basic 脚本演示如何以事务方式添加两个新应用程序,以便创建两个应用程序或两个应用程序均不创建:
Dim txctx
Dim cat
Dim apps
Dim app1
Dim app2
WScript.Echo "Starting"
Set txctx = CreateObject("TxCtx.TransactionContext")
Set cat = txctx.CreateInstance("COMAdmin.COMAdminCatalog")
Set apps = cat.GetCollection("Applications")
Set app1 = apps.Add
app1.Value("Name") = "Test App #1"
apps.SaveChanges
Set app2 = apps.Add
app2.Value("Name") = "Test App #2"
apps.SaveChanges
WScript.Echo "Ending"
txctx.Commit
相关主题