虽然Jet/OLE DB参数相对较好地记录在案,但我无法理解这两个连接参数之间的区别:
第一个:
Jet OLEDB:事务提交模式 (DBPROP_JETOLEDB_TXNCOMMITMODE)
指示Jet在提交事务时是同步还是异步将数据写入磁盘.
第二个:
Jet OLEDB:用户提交同步 (DBPROP_JETOLEDB_USERCOMMITSYNC)
指示在事务中进行的更改是以同步还是异步方式写入的.
有什么不同?什么时候用哪个?
这很长,所以这里的答案很简短:
不要设置其中任何一个.这两个选项的默认设置可能是正确的.第一种是事务提交模式,它控制Jet的隐式事务,并在显式事务之外应用,并设置为YES(异步).第二个控制Jet在显式事务期间如何与其临时数据库交互,并设置为NO(同步).我想不出你想在这里覆盖默认值的情况.但是,您可能希望显式设置它们,以防您在Jet数据库引擎设置已从其默认值更改的环境中运行.
现在,很长的解释:
我已经浏览了很多与Jet有关的资源,看看我能否找到这里的情况.两个OLEDB常量似乎映射到顶级DAO DBEngine对象的SetOptionEnum的这两个成员(此处详细说明那些没有可用Access帮助文件的人):
dbImplicitCommitSync
dbUserCommitSync
Run Code Online (Sandbox Code Playgroud)
这些选项用于在运行时为任何特定连接覆盖Jet数据库引擎的默认注册表设置,或者用于在注册表中永久更改其存储的设置.如果您在注册表中查找HLKM\Software\Microsoft\Jet\XX \,您会发现在您使用的Jet版本的密钥下面有密钥,其中两个是:
ImplicitCommitSync
UserCommitSync
Run Code Online (Sandbox Code Playgroud)
Jet 3.5数据库引擎程序员指南定义了以下内容:
ImplicitCommitSync:值为Yes表示Microsoft Jet将等待提交完成.除Yes之外的值意味着Microsoft Jet将异步执行提交.
UserCommitSync:当设置值为Yes时,Microwsoft Jet将等待提交完成.任何其他值意味着Microsoft Jet将异步执行提交.
现在,这只是对你已经说过的内容的重述.令人沮丧的是,第一个默认值为NO,而第二个默认值为YES.如果他们真的控制着同样的事情,你会期望它们具有相同的价值,或者相互矛盾的价值会成为一个问题.
但实际上关键在于名称,它反映了Jet关于如何在事务内外提交数据写入的历史.在Jet 3.0之前,Jet在显式事务之外默认为同步更新,但从Jet 3.0开始,引入了IMPLICIT事务,默认情况下使用(在Jet 3.5中有警告 - 见下文).因此,这两个选项之一适用于提交事务OUTSIDE(dbImplicitCommitSync),另一个适用于提交INSIDE事务(dbUserCommitSync).我终于在Jet数据库引擎程序员指南中找到了这些详细的解释(p.607-8):
UserCommitSynch UserCommitSynch设置确定作为显式事务的一部分进行的更改是以同步模式还是以 异步模式写入数据库.默认值...是Yes,它指定异步模式.建议您不要更改此值,因为在同步模式下,无法保证在代码进入下一个命令之前已将信息写入磁盘.
ImplicitCommitSync 默认情况下,当执行在显式事务之外添加,删除或更新记录的操作时,Microsoft Jet会自动执行称为隐式事务的内部事务,这些事务临时将数据保存在其内存缓存中,然后将数据作为块写入磁盘.ImplicitCommitSync设置确定使用隐式事务所做的更改是以同步模式还是以异步模式写入数据库.默认值...是No,它指定这些更改以异步模式写入数据库; 这提供了最佳性能.如果要将隐式事务以同步模式写入数据库,请将值更改为"是".如果更改值...当您不使用显式事务时,您将获得类似于Microsoft Jet版本2.x及更早版本的行为.但是,这样做也会严重影响性能,因此不建议您更改此设置的值.
注意:不再需要使用显式事务来提高Microsoft Jet的性能.使用Microsoft Jet 3.5的数据库应用程序应仅在可能需要回滚更改的情况下使用显式事务.Micosoft Jet现在可以自动执行隐式事务,以便在添加,删除或更改记录时提高性能.但是,在Microsoft Jet 3.5中删除了SQL DML语句的隐式事务...请参阅本章后面的"删除SQL DML语句的隐式事务".
那部分:
删除SQL DML语句的隐式事务 即使Microsoft Jet 3.0中的所有工作都要消除事务以获得更好的性能,SQL DML语句仍然放在隐式事务中.在Microsoft Jet 3.5中,SQL DML语句不会放在隐式事务中.这在运行影响许多数据记录的SQL DML语句时大大提高了性能.
尽管此更改提供了显着的性能改进,但它还引入了对SQL DML语句行为的更改.使用Microsoft Jet 3.0以及对SQL DML语句使用隐式事务的先前版本时,如果语句的任何部分未完成,则会回滚SQL DML语句.使用Microsoft Jet 3.5时,可能会有一些SQL DML语句提交的记录,而其他记录则没有.例如,当超过Microsoft Jet缓存时.缓存中的数据将写入磁盘,下一组记录将被修改并放入缓存中.因此,如果连接终止,可能有些记录已保存到磁盘,但其他记录则没有.这与使用DAO循环例程在Microsoft Jet 3.0中使用显式事务更新数据的行为相同.如果要避免此行为,则需要在SQL DML语句周围添加显式事务以定义一组工作,并且必须牺牲性能增益.
困惑了吗?我当然是.
对我来说,关键点似乎是dbUserCommitSync似乎控制Jet写入用于暂存EXPLICIT事务的TEMPORARY数据库的方式,而dbImplicitCommitSync与Jet使用其显式事务的隐式事务OUTSIDE的位置有关.换句话说,dbUserCommitSync在BeginTrans/CommitTrans循环内控制引擎的行为,而dbImplicitCommitSync控制Jet在显式事务之外的异步/同步方面的行为.
现在,关于"删除隐式事务"部分:我的解释是,当您在事务外循环记录集时,隐式事务适用于更新,但不再适用于事务外的SQL UPDATE语句.理所当然的是,提高逐行更新性能的优化效果会很好,并且实际上对SQL批量更新实际上没有多大帮助,这已经非常快(相对而言).
另请注意,可以通过两种方式执行此操作的事实使DoCmd.RunSQL能够进行不完整的更新.也就是说,如果使用DoCmd.RunSQL执行,则使用CurrentDB.Execute strSQL,dbFailOnError失败的SQL命令可以运行完成.如果您关闭DoCmd.SetWarnings,则不会收到错误报告,并且您没有机会回滚到初始状态(或者,如果您被告知错误并决定提交,则无论如何).
因此,我认为正在进行的是默认情况下通过Access UI执行的SQL包装在事务中(这就是获得确认提示的方式),但是如果关闭提示并且出现错误,则会得到不完整的更新应用.这与DBEngine设置无关 - 这是Access UI执行SQL的方式(并且可以选择将其关闭/打开).
这与DAO中的更新形成对比,DAO全部包含在以Jet 3.0开始的隐式事务中,但从Jet 3.5开始,只有顺序更新包含在隐式事务中 - 批处理SQL命令(INSERT/UPDATE/DELETE)不包含.
至少,这是我的阅读.
因此,关于实际问题中的问题,在设置OLEDB连接时,您可以根据您的操作为该连接设置Jet DBEngine的选项.在我看来,默认的Jet DBEngine设置是正确的,不应该更改 - 您希望使用隐式事务进行编辑,其中您正在遍历记录集并一次更新一行(在显式事务之外) .另一方面,您可以将整个事物包装在事务中并获得相同的结果,所以实际上,这仅适用于您正在处理记录集并更新并且未使用显式事务的情况,并且默认设置似乎对我来说很正确
另一个设置,UserCommitSync,在我看来也是你肯定想要独自留下的东西,因为在我看来,它应用于Jet在显式事务期间与其临时数据库交互的方式.将它设置为异步在我看来是非常危险的,因为您基本上不知道您提交数据时的操作状态.