Govinda Mahajan Ответов: 2

Запрос обновления Sqlserver иногда не удается обновить запись.


Логический флаг не обновляется для записи при выполнении запроса SQL Update.

Я использую C# .NET и SQL Server 2014 (Std Edition) для запуска 32-разрядного приложения Windows.
Это приложение обновляет некоторые поля в таблице с интервалом от 300 до 400 миллисекунд.

Все записи вставляются в начале или операции, а затем начинается выполнение, которое обновляет некоторые поля для любой конкретной строки. Приблизительно. каждый цикл выполнения имеет от 100000 до 125000 записей.

Таблица имеет ItemID (уникальный для каждой записи) в качестве первичного ключа и категории, которая является общей для некоторых записей. Существует 6 логических флагов и 6 полей DateTime для записи записей UpdatedDateTime.

&ЛТ;&ЛТ;таблицы дизайн&ГТ;&ГТ;
_AutoID		numeric(18, 0)
CustID		numeric(18, 0)
Category   	varchar(3)
ItemID		varchar(15)
ItemDesc		varchar(MAX)
IsChecked1	bit	
Checked1Date	datetime	
IsChecked2	bit	
Checked2Date	datetime	
IsChecked3	bit	
Checked3Date	datetime	
IsChecked4	bit	
Checked4Date	datetime	
IsChecked5	bit	
Checked5Date	datetime	
IsChecked6	bit	
Checked6Date	datetime	
AutoReason	varchar(MAX)
UserId		int	
RecordCreatedOn	datetime	
RecordLastModified	datetime

5 различных приложений, работающих на 5 компьютерах доступа к БД, доступных в CommonPC все подключены в локальной сети. каждое приложение обновить одно поле и дату-время для одного ItemID и перейти к следующему. Все 5 записей обновления приложений параллельны.
После того как все записи обработаны на всех компьютерах, выполняется резервное копирование данных, очищаются данные из БД и запускаются новые выполнения, которые добавляют новые записи для дальнейшей обработки.

Я использую DbProviderFactories для установления соединения и DbCommand для выполнения запроса. Соединение создается в самом начале как статическое и используется для каждой транзакции.

Используется следующий код обновления.
public int UpdateFlag1(decimal CustID, string Category, string ItemID, bool IsChecked1, bool IsChecked2, DateTime Checked1Date, DateTime Checked2Date, string AutoReason, int UserId)
{
	try
	{
		string sqlQuery = string.Empty;

		///Here, Updating total data recceived from Method/Call
		sqlQuery += "UPDATE [tbl_Item_Data] SET " +
				"[IsChecked1]=@IsChecked1, [IsChecked2]=@IsChecked2," +
				"[Checked1Date]=@Checked1Date, [Checked2Date]=@Checked2Date," +
				"[AutoReason]+=@AutoReason, [UserId]=@UserId ";
				
		sqlQuery += "WHERE [CustID]=@CustID and [Category]=@Category and [ItemID]=@ItemID ";

		DbCommand oDbCommand = DbProviderHelper.CreateCommand(sqlQuery, CommandType.Text);

		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@CustID", DbType.Decimal, CustID));
		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@Category ", DbType.String, Category));
		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@ItemID", DbType.String, ItemID));

		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@IsChecked1", DbType.Boolean, true));
		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@Checked1Date", DbType.DateTime, Checked1Date));

		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@IsChecked2", DbType.Boolean, true));
		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@Checked2Date", DbType.DateTime, Checked2Date));

		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@AutoReason", DbType.String, AutoReason));
		oDbCommand.Parameters.Add(DbProviderHelper.CreateParameter("@UserId", DbType.Int32, UserId));

		return DbProviderHelper.ExecuteNonQuery(oDbCommand);
	}
	catch (Exception ex)
	{
		throw ex;
	}
}

Пожалуйста, дайте мне знать, почему некоторое время он не может обновить флаг IsChecked1 до true.

Частота не обновления редка, из 10000 транзакций это происходит один или два раза...
Некоторое время даже для записей 50K~60K никаких проблем не наблюдается.

Что я уже пробовал:

Сетевое подключение локальной сети очень хорошего качества.
Мы попытались сохранить БД на той же машине, где у нее есть приложение.
Все используемое оборудование является фирменным и i3/4GB.

C# 3.5, MS SQL Server 2014/2016, Windows 7 32 бит,

2 Ответов

Рейтинг:
1

RickZeeland

Ваши индексы могут замедлить работу по мере использования варчар(15) для первичного ключа попробуйте выполнить переиндексацию.
Если у вас есть версия SQL Server, которая выше версии Express, вы можете автоматизировать это с помощью планов обслуживания.
Смотрите эту бесплатную электронную книгу: https://www.slant.co/improve/topics/3492/viewpoints/1/~free-books-about-sql-server-maintenance~guide-to-sql-server-maintenance-plans[^]

С помощью интерфейс ODBC драйвер не даст наилучшей производительности, если вы хотите следить за производительностью чтения: Профилирование производительности драйвера ODBC - SQL Server | Microsoft Docs[^]

Однако лучше всего было бы использовать лучшую базу данных, например PostgreSQL :)


Рейтинг:
0

OriginalGriff

Мы не можем сказать - это требует вашего кода, работающего с вашей базой данных, чтобы получить какую-либо идею, и у нас нет никакого доступа к этому вообще.

Поэтому вам нужно начать с сбора данных.
Первоначально регистрируйте каждое обновление, которое вы собираетесь сделать, вместе с фактическими параметрами, которые вы собираетесь обновить, и добавьте "статус обновления" после попытки: успешно (в комплекте с количеством затронутых строк) или неудачно - вместе со всей информацией об исключениях, а не просто перестраивая ее. Но обратите внимание, что

throw ex;
отбрасывает информацию, поскольку она связывает исходную трассировку стека, что может затруднить отслеживание фактической проблемы. Если вы хотя бы не регистрируете информацию в своем журнале catch блок, то вам, вероятно, лучше вообще не пытаться блокировать, чем то, что у вас есть в данный момент.

Запускайте свой код до тех пор, пока не возникнет ошибка, а затем проверьте журнал: что он говорит, что вы пытались сделать, и что произошло? Если не было зафиксировано никакой ошибки - то есть обновление не провалилось, но ваша БД показывает, что оно не сработало, - то посмотрите долго и внимательно на затронутые строки и фактические данные, которые вы использовали.

Надеюсь, это позволит вам "сузить круг", когда возникнет проблема, и это позволит вам быть гораздо более подробным или конкретным в отношении вашего ведения журнала, чтобы точно определить его.


Извините, но у прерывистых ошибок нет "простого решения": вам нужно собрать данные, чтобы сделать их воспроизводимыми, прежде чем вы сможете даже начать их исправлять!