устранение повреждений в файлах базы данных SQL Server Compact Edition - PullRequest
20 голосов
/ 08 сентября 2011

Это не запрос. Это краткое изложение нашего решения обойти проблему повреждения в файлах базы данных SQL Compact с (почти) определенным успехом. SQLCE Коррупция является очень распространенной проблемой. Мы получили огромную помощь от предыдущих постов в StackOverflow и, следовательно, от этого поста.

Наш продукт представляет собой 3-уровневую архитектуру с сервером, работающим в качестве службы Windows, подключенным к Rich Clients через .Net Remoting. Наш продукт использует SQLCE с 2006 года. Мы перешли с версии 3.1 на версию 3.5, а теперь и на версию 4.0. У нас есть специальный инструмент OR-Mapping для некоторых очень специфических требований. С v3.1 мы столкнулись с ограниченными проблемами, больше с v3.5 и v4.0.

Изначально с v3.5 мы реализовали SqlCeEngine.Repair. Но он только удаляет поврежденные данные и пытается восстановить стабильную базу данных. Мы обнаружили, что внешние ключи затронутых таблиц пропали без вести. Мы должны были покончить с этим немедленно. Мы начали уведомлять пользователей о повреждении БД и восстанавливать последнюю резервную копию. Это только обеспечило временное облегчение; проблема коррупции все еще стояла.

В этом году мы приняли v4.0. Однако наше приложение также представило несколько новых функций, которые значительно увеличили количество вызовов базы данных. v4.0 начал хорошо, но начал давать проблемы, когда использование программного обеспечения увеличилось. Повреждения, возникающие во время работы приложения, не вызваны сбоем Windows, ненормальным завершением работы или проблемами с диском. База данных просто повреждена.

Следующий пост посвящен решению, которое мы разработали для этой проблемы:

Ответы [ 2 ]

17 голосов
/ 31 декабря 2011

[Разделение запроса и решения]

Вот как мы решили проблему:

A) Закрытие / удаление объектов Connection / Command / Transaction: мы убедились, что неиспользуемые, незакрытые объекты связи, транзакции или команды.Наш инструмент ORM создавал новые объекты после вызова commit для транзакции, которая в некоторых случаях простаивала.Это в значительной степени уменьшило количество искажений на 50%.

B) Отключение автосжатия: единственной процедурой, происходящей в середине выполнения приложения, над которой мы не имели никакого контроля, была автосжатие.Мы вызывали SqlCeEngine.Compact при запуске приложения.Мы решили покончить как с уплотнением, так и с автоусадкой.И, к нашему удивлению, мы сократили коррупцию еще на 48%.Это был выстрел в темноте, и мы не могли поверить, что автоматическое сжатие могло вызвать такие проблемы.Мы практически решили проблему с этим обновлением.

C) Синхронизированные транзакции базы данных: некоторые повреждения базы данных все еще происходят.Без четких причин мы решили синхронизировать транзакции базы данных!Я знаю, что многим людям из баз данных это не понравится.Мне это тоже не нравится.Мы ввели блокировки на нашем среднем уровне, чтобы гарантировать, что только один вызов изменяет базу данных одновременно.Наша самая большая реализация - 55 клиентов, одновременно использующих нашу систему.Синхронизация вызовов базы данных едва ли приводила к какой-либо видимой задержке производительности.Скорее Синхронизация позволила нам реализовать управляемый таймером вызов SqlCeEngine.Compact через регулярные промежутки времени.Мы знали, что Compact не был виновником, и мы чувствовали, что Compaction - необходимый вызов, поскольку он переиндексирует базу данных (наше решение выполняет много операций вставки и удаления).Тем не менее, он должен функционировать исключительно;нет звонков из базы данных при вызове Compact.Синхронизация позволила нам контролировать это во время запуска приложения.С тех пор как мы это сделали, мы не получили ни одной проблемы с повреждением базы данных.Прошло уже больше месяца.От почти 5 клиентов в неделю до нуля в месяц.

Основная идея, которая привела нас к идеям B и C, заключается в том, что SQLCE является встроенной базой данных.Повреждения являются общими для каждого решения встраиваемой базы данных.Полноценные решения для баз данных работают независимо, поддерживаются круглосуточным db-сервером, управляющим соединениями и другими задачами.Встроенная система баз данных не имеет такой системы поддержки.Единственный этап, когда он жив, - это когда соединение открыто.

Еще несколько указателей: 1) Мы реализуем commit с CommitMode.Immediate, что делает свойство Flush-Interval избыточным.2) AutoShrink установлен на 100, что полностью отключает процедуру. 3) Я увеличил тайм-аут соединения, чтобы синхронизированные вызовы базы данных функционировали плавно.4) Компакт вызывается при запуске приложения.В тех случаях, когда клиенты вообще не выключают свою машину, мы включили таймер для вызова Compact каждые 24 часа.

Надеюсь, этот пост поможет решить проблемы.

5 голосов
/ 11 февраля 2016

При использовании SQL Server CE 4.0 существует известная проблема, которая может препятствовать переносу данных на диск (ВСЕ). https://support.microsoft.com/en-us/kb/2979868 и исправление https://support.microsoft.com/en-us/kb/2960153

своими словами:

Предположим, что вы указали интервал очистки в максимальном количестве секунд в строке подключения, прежде чем зафиксированные транзакции будут записаны на диск в Microsoft SQL Server Compact 4.0. В этой ситуации зафиксированные транзакции могут занимать намного больше времени, чем интервал очистки, чтобы быть записанными на диск, или могут даже не быть сброшены на диск. Кроме того, потеря данных происходит в случае ненормального завершения программы.

Исправление, решающее эту проблему, включено в пакет обновления исправлений по требованию для SQL Server Compact 4.0 с пакетом обновления 1 (SP1).

Обходное решение - использовать transaction.Commit(CommitMode.Immediate) вокруг блока, который вы хотите убедиться, что он сбрасывается

...