У меня есть простой запрос, который возвращает 25 026 строк:
MySqlCommand cmd = new MySqlCommand("SELECT ID FROM People", DB);
MySqlDataReader reader = cmd.ExecuteReader();
(ID
int
.), Если я просто делаю это:
int i = 0;
while (reader.Read()) i++;
i
будет равняться 25026. Однако я должен сделать некоторую обработку на каждом идентификаторе в моем цикле; каждое повторение заканчивает тем, что брало где-нибудь в сотнях миллисекунд.
int i = 0;
MySqlCommand updater = new MySqlCommand("INSERT INTO OtherTable (...)", anotherConnection);
updater.Prepare();
while (reader.Read()) {
int id = reader.getInt32(0);
// do stuff, then
updater.ExecuteNonQuery();
i++;
}
Однако около 4:15 обработки, reader.Read()
просто возвращает false. В большинстве моих тестовых прогонов, i
уравненный 14896, но это также иногда останавливается в 11 920. DataReader
при выходе после того, как то же количество записей подозрительно, и времена, которые оно останавливает после того, как другое количество строк кажется еще более странным.
Почему reader.Read()
возвращение false, когда существует определенно больше строк? Нет никаких выданных исключений – даже первые случайные исключения.
Обновление: Я упомянул в своем ответе на ответ Shaun, что становился убежденным это MySqlDataReader.Read()
глотает исключение, таким образом, я загрузил исходный код Коннектора/Сети (bzr branch lp:connectornet/6.2 C:/local/path
) и добавил проект к моему решению. Конечно же, после 6:15 обработки, исключения!
Вызов к resultSet.NextRow()
броски a MySqlException
с сообщением "Чтения из потока перестал работать". InnerException
a SocketException
:
{ Message: "An existing connection was forcibly closed by the remote host",
ErrorCode: 10054,
SocketErrorCode: ConnectionReset }
10054 означает, что сокет TCP был прерван с a RST
вместо нормального квитирования разъединения (FIN
, FIN ACK
, ACK
), который говорит мне, что что-то странное происходит с сетевым соединением.
В my.ini я провернул interactive_timeout
и wait_timeout
к 1814400 (секунды) напрасно.
Так..., почему мое соединение разъединяет после чтения в течение 6:15 (375 секунд)?
(Кроме того, почему это исключение глотает, когда я использую официальный двоичный файл? Похоже, что это должно пузыриться до моего кода приложения.)
Попробуйте установить более длительный тайм-аут соединения.
Попробуйте установить таймаут на MySqlCommand, а не на MySqlConnection и в "cmd", и в "updater".
Что произойдет, если вы сделаете : SELECT TOP 100 ID FROM PEOPLE
?
Попробовать 1. Добавьте ссылку на System.Transactions;
using(TransactionScope scope = new TransactionScope())
{
//Initialize connection
// execute command
:
:
scope.Complete();
}
. Запишите всю логику вставки / обновления в Scope, используя. Это определенно вам поможет.
Возможно, у вас повреждена таблица - проблема этого парня очень похожа на вашу: http://forums.asp.net/t/1507319.aspx?PageIndex=2 - отремонтируйте таблицу и посмотрите, что произойдет.
Если это не сработает, читайте дальше:
Я предполагаю, что вы попали в какой-то тупик, особенно учитывая, что вы читаете и пишете. Это объяснило бы, почему он работает с простым циклом, но не работает при обновлении. Это также объяснило бы, почему это происходит каждый раз примерно в одном и том же ряду / раз.
В SqlDataReader была странная ошибка, подавлявшая исключения ( http://support.microsoft.com/kb/316667 ). В MySqlDatareader может быть что-то подобное - после последнего вызова .Read () попробуйте вызвать .NextResult (). Даже если это не тупик, это может помочь вам диагностировать проблему. В таких ситуациях вам нужно больше склоняться к «доверяй, но проверяй» - да, в документации сказано, что и исключение будет сгенерировано вовремя, но иногда (очень редко) документация лжет :) Это особенно верно для сторонних разработчиков. поставщики - например, см. http://bugs.mysql.com/bug.php?id=53439 - у библиотеки mysql .net было несколько проблем, подобных той, что была у вас в прошлом.
Еще одна идея - наблюдать за тем, что происходит в вашей базе данных - убедитесь, что данные постоянно извлекаются до той строки, в которой завершается ваш код.
В противном случае я бы просто прочитал все данные, кэшировал их, а затем внес бы ваши изменения. За счет пакетирования модификаций код будет менее болтливым и будет выполняться быстрее.
Как вариант, перезагружайте считыватель примерно каждые 1000 строк (и отслеживайте, какой у вас идентификатор строки).
Надеюсь, здесь что-то поможет вам справиться с разочарованием! :)
я нашел здесь статью http://corengen.wordpress.com/2010/06/09/mysql-connectornet-hangs-on-mysqldatareader-read/
То, что испытал этот парень, было нечто похожее: зависание метода Read точно при в тот же момент, во время чтения той же записи (я думаю, это то же самое, что и вы). В его случае он вызвал другой веб-сервис во время цикла Read (), и у него истекло время ожидания, что привело к зависанию Read () без исключения.
Может ли быть на вашем компьютере то же самое, что время ожидания обновления в цикле Read () истекает (я думаю, что обновление использует тайм-аут по умолчанию 30 секунд) и вызывает тот же эффект?
Может быть, длинный снимок, но чтение эти две истории звучали очень знакомо.
Добавьте следующее после создания команды.
cmd.CommandTimeout = 0;
Это установит CommandTimeout на неопределенное время. Причина, по которой вы получаете таймаут, вероятно, заключается в том, что соединение, хотя и выполнено, все еще находится в фазе "команды" из-за Reader.
Попробуйте либо установить CommandTimeout = 0, либо сначала прочитать все, а затем выполнять последующие функции над результатами. В противном случае единственная проблема, которую я могу увидеть, заключается в том, что Sql Server отбрасывает набор результатов для указанного идентификатора процесса из-за таймаута на самом сервере.