【问题标题】:Sync Framework - Batching同步框架 - 批处理
【发布时间】:2012-10-27 12:03:49
【问题描述】:

我使用同步框架 2.1 over WCF(N-Tier)同步两个远程数据库(Sql Express 和 Sql Compact),使用批处理。

最近我收到了这个日志文件,这是一个很少出现的错误,但是当它出现时会产生很多问题(似乎包含在此同步范围内失败的数据中的表已被删除)。 我很肯定没有人会弄乱 BatchingDirectory,所以它应该在那里并包含所有数据。下面的错误是否与我有

CleanupBatchingDirectory = true

这是在应用更改之前删除?

11/06/2012 14:16:49 Error ** :PosPosSync:ThreadId=7: **: 
SyncScope ErpProduct  failed
Message: An unexpected error occurred when applying batch file C:\Documents and Settings\kasse6\Application Data\POSSyncDataClient\PosSync_5b009e9008c14d0ba6a9e47726d8d620\4e77ef8c-3045-4c55-809f-014ae2b96155.batch. See the inner exception for more details.
Type   : Microsoft.Synchronization.Data.DbSyncException
Stack  :    at Microsoft.Synchronization.Data.DbSyncBatchConsumer.ApplyBatches(DbSyncScopeMetadata scopeMetadata, DbSyncSession syncSession, SyncSessionStatistics sessionStatistics)
   at Microsoft.Synchronization.Data.RelationalSyncProvider.ProcessChangeBatch(ConflictResolutionPolicy resolutionPolicy, ChangeBatch sourceChanges, Object changeDataRetriever, SyncCallbacks syncCallbacks, SyncSessionStatistics sessionStatistics)
   at Microsoft.Synchronization.KnowledgeProviderProxy.ProcessChangeBatch(CONFLICT_RESOLUTION_POLICY resolutionPolicy, ISyncChangeBatch pSourceChangeManager, Object pUnkDataRetriever, ISyncCallback pCallback, _SYNC_SESSION_STATISTICS& pSyncSessionStatistics)
   at Microsoft.Synchronization.CoreInterop.ISyncSession.Start(CONFLICT_RESOLUTION_POLICY resolutionPolicy, _SYNC_SESSION_STATISTICS& pSyncSessionStatistics)
   at Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWaySyncHelper(SyncIdFormatGroup sourceIdFormats, SyncIdFormatGroup destinationIdFormats, KnowledgeSyncProviderConfiguration destinationConfiguration, SyncCallbacks DestinationCallbacks, ISyncProvider sourceProxy, ISyncProvider destinationProxy, ChangeDataAdapter callbackChangeDataAdapter, SyncDataConverter conflictDataConverter, Int32& changesApplied, Int32& changesFailed)
   at Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWayKnowledgeSync(SyncDataConverter sourceConverter, SyncDataConverter destinationConverter, SyncProvider sourceProvider, SyncProvider destinationProvider, Int32& changesApplied, Int32& changesFailed)
   at Microsoft.Synchronization.KnowledgeSyncOrchestrator.Synchronize()
   at Microsoft.Synchronization.SyncOrchestrator.Synchronize()
   at PosPosSync.Local.PosPosSyncService.SynchronizeProviders(KnowledgeSyncProvider localProvider, KnowledgeSyncProvider remoteProvider, SyncDirectionOrder syncDirectionOrder)
   at PosPosSync.Local.PosPosSyncService.SyncronizeData(String scopeName, SyncDirectionOrder syncDirectionOrder)
Source : Microsoft.Synchronization
Target : Void Start(CONFLICT_RESOLUTION_POLICY, _SYNC_SESSION_STATISTICS ByRef)
------- Inner Exception ------
    Message: Could not find a part of the path 'C:\Documents and Settings\kasse6\Application Data\POSSyncDataClient\PosSync_5b009e9008c14d0ba6a9e47726d8d620\4e77ef8c-3045-4c55-809f-014ae2b96155.batch'.
    Type   : System.IO.DirectoryNotFoundException
    Stack  :    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode)
   at Microsoft.Synchronization.Data.DbSyncBatchInfoFactory.Deserialize(String batchFileName, Boolean deserializeData)
   at Microsoft.Synchronization.Data.DbSyncBatchConsumer.ReadBatchFile(UInt32 lookupLocation, UInt32 expectedNumber)
   at Microsoft.Synchronization.Data.DbSyncBatchConsumer.ReadBatchFile(UInt32 expectedNumber, String& batchFileName)
   at Microsoft.Synchronization.Data.DbSyncBatchConsumer.ApplyBatches(DbSyncScopeMetadata scopeMetadata, DbSyncSession syncSession, SyncSessionStatistics sessionStatistics)
    Source : mscorlib
    Target : Void WinIOError(Int32, System.String)

认为它会在一段时间后尝试再次同步所有数据,并且根据我拥有的日志信息,它似乎将所有内容从客户端下载到服务器:

11/06/2012 14:26:02 Info ** :PosPosSync:ThreadId=7: **: 
EndSync: ScopeName: ErpProduct
DownloadChanges: Applied - Failed: 122363 - 0
UploadChanges: Applied - Failed:  0 - 0
FinishedSync: ElapsedTime, sec: 545,0086488

【问题讨论】:

  • 您指定的批处理目录是否正确? “似乎删除了此同步范围中包含的数据中失败的表” - 框架从不删除用户表。您的错误在批处理文件上。即使批处理文件有错误,后续同步应该仍然有效。
  • 您好,批处理目录路径是我指定的。问题是当这个错误发生时,范围内包含的表的内容是空的(不是被删除的表,而是它的内容)。我无法在我的机器上重现它,但这是我从日志文件中收到的输入。
  • 你的意思是表在错误发生后被清空,或者你的意思是正在同步的表实际上是空的?
  • 是的,对于这个范围 ErpProduct,发生错误的地方,我只将数据从 SQL EXPRESS 数据库下载到 SQL Compact 数据库。在问题的第一次出现之间,我有一些产品(应该存在)直接到数据库的调用,但没有找到任何东西。来自 SyncOrchestrator 的消息证实了我的恐惧:DownloadChanges: Applied - Failed: 122363 - 0
  • 是什么?同步框架清空你的表?或者它真的是空的?失败可能意味着发生冲突或在应用更改时遇到错误。订阅 ApplyChangeFailed 事件并查看它是错误还是冲突

标签: microsoft-sync-framework batching


【解决方案1】:

在与类似问题斗争了几年之后,我想我终于找到了解决方案。

如果定义了多个作用域(并且作用域大到可以使用批处理),也会发生“找不到路径的一部分”问题,因为 MS 的示例代码中有一个小错误。问题出在 SqlWebSyncService 中的 Dispose 上,删除了此会话的批处理文件夹,但目录信息变量未设置为 null(这是下一个范围用于了解它是否正在创建文件夹的测试)。添加将批处理目录设置为 null 可以解决此问题,因为当 CheckAndCreateBatchingDirectory 然后运行它时,它会发现批处理目录为 null 并完成它。

private void Dispose(bool disposing)
{
try
{
    if (!this.m_disposed)
    {
        if (disposing)
        {
            if (this.m_ServerProvider != null)
            {
                this.m_ServerProvider.Dispose();
                this.m_ServerProvider = null;
            }
            if (this.m_SessionBatchingDirectory != null)
            {
                this.m_SessionBatchingDirectory.Refresh();
                if (this.m_SessionBatchingDirectory.Exists)
                {
                    try
                    {
                        this.m_SessionBatchingDirectory.Delete(true);
                    }
                    catch
                    {
                    }
                }
                this.m_SessionBatchingDirectory = null;
            }
        }
        this.m_disposed = true;
    }
}
catch (Exception exception)
{
    string message = "SqlWebSyncService Cleanup Exception: " + exception;
    LogWriter.TraceError(message, new object[0]);
    throw new FaultException<WebSyncFaultException>(new WebSyncFaultException(message, exception));
}
}

同样在客户端 SqlSyncProviderProxy.EndSession

...
if (this.m_LocalBatchingDirectory != null) 
{
    this.m_LocalBatchingDirectory.Refresh();
    if (this.m_LocalBatchingDirectory.Exists) 
    {
       this.m_LocalBatchingDirectory.Delete(true);
    }
    this.m_LocalBatchingDirectory = null;
}
...

更改批量大小时会显示此行为。我们将批量大小设置为 70000,发现问题消失了。事后看来,这是因为第一个范围都适合一个批次,所以它没有被分解并实施批处理。当我们将大小设置为较小时,我们的第一个作用域(3 个中的第一个)将使用批处理,当作用域 2 启动时我们会看到这一点。

【讨论】:

    【解决方案2】:

    尝试更改客户端上的 SqlSyncProvider.MemoryDataCacheSize(批量大小)。

    当我将 Batch Size 设置为 100kb 时,我的客户端 Synchronize 抛出 DirectoryNotFoundException,通常我运行 500kb。我只在大型同步(例如大型数据库的初始同步)上看到了这一点。随后的同步工作正常,因为较小)。

    更新

    根据MS Documentation,问题可能是由于数据库行超过 MemoryDataCacheSize 的 110%。

    应用程序为参与同步会话的每个提供程序指定内存数据缓存大小。 如果两个提供程序都指定了缓存大小,则 Sync Framework 为两个提供程序使用较小的值。实际缓存大小将不超过最小指定大小的 110%。 在同步会话期间,如果单行大于大小的 110%,则会话终止并出现异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-04
      • 2017-01-09
      相关资源
      最近更新 更多