[Separating the query and the solution]
Here goes how we solved the problem:
A) Closing/Disposing Connection/Command/Transaction objects:
We ensured that there are no unused, unclosed connection, transaction or command objects. Our ORM tool used to create new objects after calling commit on the transaction, which were lying idle in some cases. This pretty much reduced the number of corruptions by 50%.
B) Disabling Auto-Shrink:
The only procedure occurring in the middle of an application run, over which we had no control was Auto-Shrink. We were calling SqlCeEngine.Compact when the application starts. We decided to do away with both Compacting and Auto-Shrinking. And to our surprise, we reduced corruptions by another 48%. It was a shot in the dark, and we could not believe that Auto-Shrinking could have caused such problems. We practically solved the problem with that update.
C) Synchronized Database Transactions:
Some database corruptions still happening. With no clear reasons detected, we decided to synchronize database transactions! I know that a lot of database people are not going to like this. I don't like it either. We introduced locks in our middle tier to ensure that only one call is modifying the database at a time. Our largest implementation is 55 clients simultaneously using our system. Synchronizing the database calls hardly resulted in any visible performance delay. Rather, Synchronizing allowed us to implement a timer-driven call to SqlCeEngine.Compact at regular intervals. We knew that Compact was not the culprit, and we felt that Compaction is a necessary call as it reindexes the db (our solution does a lot of inserts and deletes). However, it needs to function exclusively; no database calls when you call Compact. Synchronizing allowed us to control that during an application run. Since we've done that, we've not received a single database corruption problem. Its been more than a month now. From almost 5 clients in a week, to zero in a month.
The basic reasoning which led us to ideas B and C is that SQLCE is an Embedded Database. Corruptions are common to every embedded database solution. A full-scale database solutions works independently supported by a 24x7 db-server managing connections and other tasks. An embedded database system does not have such a support system. The only stage when it is alive is when a connection is opened.
Some more pointers: 1) We implement commit with CommitMode.Immediate, which makes the Flush-Interval property redundant. 2) AutoShrink is set to 100, which disables the procedure completely 3) I've increased the Connection timeout to allow the synchronized database calls to function smoothly. 4) Compact is called when the application starts. In cases where clients do not shutdown their machine at all, we implemented the timer to call Compact every 24-hours.
Hope this post helps solve problems.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…