SqlSyncChangeTrackingProvider and sync_scope_last_clean_timestamp updates #1337
-
Hello, I am trying to use SqlSyncChangeTrackingProvider with IsolationLevel.Snapshot in my one way synchronisation from server database to multiple client databases (1:N). I use snapshot to avoid blocking changes in original database during synchronisation of the data as with a lot of clients almost always at least some of the are being synchronized. It looks like it works (I need to disable snapshot isolation level when creating scope_info table as DDL updates are not allowed in snapshot), but it causes frequent exceptions that look like those:
I can just retry and it usually works, but with increasing amount of synchronized clients the exception becomes more and more frequent. I have tracked down the SQL that is causing the exception to the one that is generated by SqlChangeTrackingScopeBuilder, method GetUpdateScopeInfoClientCommand: link to the source I think the source is updating sync_scope_last_clean_timestamp column for all of the scopes, not just the one that is being updated - it is causing conflicts if a lot of clients are trying to update at the same time.
Is there any reason why the update is done for all the scopes, and not just currently updated one? I have tried to adjust the code myself by using custom scope builder like this:
and it looks like it makes the exception go away, but I wonder if my change doesn't break anything. Any thoughts? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
Hey @slawomirpiotrowski There is a reason why tracking tables record are not tight to each scope: Legacy / Performances. You are using the tracking changes feature from SQL Server, and there is no relation beetween the value from IF you are using the classic Each time a record has changed (or is deleted) the tracking table records the state of this record, for all scopes involved. In your case, if you are updating the Let's try to explain by a quick example: Each time you are retrieving the Imagine:
10 days later, you are making a new sync for Scope 1, and then automatically updating the last cleanup timestamp ONLY for this scope (has you are doing in your code)
Scope 2 and 3 are wrong as we don't have the state for all records changed between Now your problem is coming from this exeception:
I don't undersand why you are hitting this kind of error I'll do some search on my side, but I never had this kind of error so far. |
Beta Was this translation helpful? Give feedback.
-
Hello and thanks for your answer. My code for setting up the synchronisation is non standard in one way. I am enabling snapshot isolation level for source side. I am also using download only direction of synchgronisation and I am configuring separate scope for each destination of synchronisation. Code looks like this (MySqlSyncChangeTrackingProvider has only the changes shown above, nothing else):
Of couse I also need to enable snapshot isolation support in the database and I need to disable snapshot isolation transaction for first time synchronisation (where scope_info table is created, as altering table structure is not allowed from within snapshot isolation transaction). The reason why I'm using snapshot isolation is using a lot of frequent, simultanous one way synchronisations (single source, many destinations) with poor connectivity to destination databases. Net effect is always a few synchrosations are ongoing and without snapshot I often block writes to source database. Snapshot works nicely (each and every synchronisation is seeing database's state as it was when given synchronisation transaction started). Unfortunatelly when sync_scope_last_clean_timestamp is updated updating transaction is done in the same transaction as synchrosation was done, so comparision is done to the state when synchronisation started. It heavily increases a window when update conflict can happen comparing to not using snapshot isolation. Going back to your example of incorrect data in the database. Yes, after 10 days if I only update scope 1, then scope 2 and scope 3 would have incorrect information. But is that a problem? When is this information used? I mean right before synchronisation of scope 1 (let's say after 9 days, 23 hours and 59 minutes), scope 2 and scope 3 would also have incorrect information (and scope 1 too). I think this information would be updated as soon as those scopes get synchronised next time and the fact that information used to be outdated shouldn't matter? Or is it used somewhere and this can cause problems? |
Beta Was this translation helpful? Give feedback.
thanks @slawomirpiotrowski, you made a really good example, and I was easily reproducing the error.
I made a fix by overriding the isolation level using the table hint
WITH (READCOMMITTED)
for the scope info tables.I've created the issue here: #1340
I will create a prerelease in the upcoming weeks, but you can test the solution by using the source code directly
Let me know if it's ok for you
Thanks for discovering that issue !!