Обработка тысяч SqlCommands с использованием SqlTransaction вызывает исключение памяти
-
12-12-2019 - |
Вопрос
Я написал специальную функцию репликации в стандартном приложении Windows Forms C# с базой данных SQL Server 2008 Express.По сути, он извлекает набор операторов sql, которые необходимо выполнить для базы данных подписчиков.При полном обновлении может быть выполнено более 200 тысяч операторов, которые необходимо выполнить.
Я обрабатываю эти операторы внутри блока кода, как показано ниже:
using (SqlConnection connection = ConnectionManager.GetConnection())
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
// Process 200k+ Insert/Update/Delete statements using SqlCommands
transaction.Commit
}
Я обнаружил, что использование памяти моими приложениями остается довольно стабильным и составляет около 40 МБ для первых 30 тысяч операторов.После чего внезапно кажется, что он подскочил примерно до 300 МБ, а затем увеличился, пока я не столкнулся с исключением OutOfMemory.
Возможен ли вообще метод, который я использую, могу ли я обработать такое количество операторов внутри одной транзакции?Я предполагаю, что смогу это сделать.Если есть лучший способ, я бы с удовольствием разместил его здесь.Мне нужно, чтобы это было транзакционным, иначе частичная репликация приведет к повреждению базы данных.
Спасибо.
РЕДАКТИРОВАТЬ:
После перезагрузки компьютера мне удалось выполнить полную репликацию более 200 тысяч.Несмотря на то, что в какой-то момент использование памяти выросло до 1,4 ГБ после завершения репликации, использование памяти снова упало до 40 МБ.Это приводит меня к выводу, что что-то внутри моего цикла, обрабатывающее команды, возможно, вызывает рост памяти.
Решение
Ты Disposing
ваши формы и одноразовые элементы управления перед закрытием?
Оберните все одноразовые объекты в оператор using.Нажмите здесь для более подробной информации
Не открывайте/закрывайте соединение снова и снова, вместо этого отправляйте данные в базу данных за одну транзакцию.Нажмите здесь для более подробной информации
Тем не менее, ваше приложение занимает слишком много памяти, тогда вам нужен доктор, такой как профилировщик памяти Red Gate Ants.Нажмите здесь, чтобы увидеть более подробную информацию об этом
могу ли я обработать такое количество операторов внутри одной транзакции?
У вас есть варианты ниже, чтобы сделать это...
- Массовая вставка и управление записями в
Stored Proc
. - Подготовить
XML
и отправьте строкуDatabase
. - Отправить только для чтения
DataTable
на сервере Sql через хранимую процедуру
Пример сохраненной процедуры
Begin Try
Set NoCount ON
Set XACT_Abort ON
Begin TRan
--Your queries
Commit Tran
Begin Tran
Begin Catch
Rollback Tran
End Catch
Убедись в Dispose
объекты, когда-то не используемые.
Это должно быть так
using (SqlConnection connection = new SqlConnection())
{
connection.Open();
using (SqlTransaction transaction = connection.BeginTransaction())
{
transaction.Commit();
}
}
Вы проверили SqlCommand
также?
using (SqlCommand cmd = new SqlCommand())
{
}