System.AccessViolationException для OleDbConnection.Query с использованием Dapper

Я использую OleDbConnection в .Net 4.0 для запроса базы данных Microsoft Access 2010 с помощью механизма ACE OleDb 12.0. Возможно, процесс выполняет большое количество запросов в секунду, так как у меня есть около 60 возможных параллельных потоков (я установил ограничение ThreadPool для TPL после прочтения эту статью). Файл mdb находится на сетевом диске. Я создаю и удаляю соединение для каждого запроса со следующим кодом:

Using connection As New OleDb.OleDbConnection(connectionString)
    result = connection.Query(Of Foo)(query, New With {.Param1 = param1, .Param2 = param2}).FirstOrDefault()
End Using

Время от времени, казалось бы, случайно, я получаю System.AccessViolationException in System.Data.dll при звонке connection.Query. Это исключение должно вызываться неуправляемым кодом, но я напрямую не использую неуправляемый код, поэтому это происходит после вызова Query. Я также хотел убедиться, что это не проблема, явно связанная с многопоточностью, но, если я правильно понимаю документацию, использование одного IDbConnection на запрос должно быть потокобезопасным, и Dapper также должен быть потокобезопасным.

Ошибка не всегда возникает при одном и том же запросе или типе POCO, и, вероятно, это не проблема с оборудованием (процессор ‹ 50%, память ‹ 75% и мой процесс не ест более 250 МБ). Я еще не видел проблемы с подобным кодом на SqlConnection для SQL Server.

Кроме того, я работаю с VS Express 2012, поэтому, даже если я настроил «Разрыв при исключении», я не могу использовать помощник по исключениям для устранения неполадок. Я, очевидно, не хочу перехватывать исключение вверх по стеку, так как это исключение, связанное с памятью (поскольку я бы не хотел перехватывать исключение OutOfMemoryException).

Я делаю что-то неправильно? Есть ли способ отладить это, так как это происходит только время от времени? Может ли это быть ошибкой Dapper или движка OleDb?


person Benjamin Beaulieu    schedule 03.12.2013    source источник


Ответы (1)


Я подозреваю, что проблема будет заключаться в том, что несколько потоков попадут в БД Access. Насколько мне известно, MS Access не предназначен для multi-threaded приложений, поскольку у него есть ограничение на параллелизм.

Документации по нему немного, но упоминается here, что MS Access не предназначен для высокой нагрузки и высокой параллелизма.

EDIT: на основе комментариев

  1. Вы можете сбросить базу данных доступа непосредственно в SQL Server в качестве промежуточного процесса, а затем запустить свой код .Net для данных в промежуточной таблице в его финальную таблицу на SQL.
  2. Используйте SSIS data flow to manipulate the data, возможно, используя задачу сценария для кода .Net.
  3. Я видел процесс, в котором Reactive Extensions использовались для больших файлов CSV размером 2 ГБ, используя буфер для потоковой передачи данных. Итак, если вы можете сбросить данные доступа ms в CSV, вы можете запустить аналогичный процесс в памяти.
person christiandev    schedule 03.12.2013
comment
Я нашел в другом месте (не могу найти в своей истории), что Access должен поддерживать до 255 одновременных подключений, и статья, о которой я упоминал в своем вопросе, устанавливает ограничение в 64 соединения на процесс. Хотя я знаю, что Access не обязательно подходит для моих нужд (на самом деле проблема возникает при переносе данных из Access в новую базу данных SQL Server), я не понимаю, почему он не справится с парой десятков операций чтения. -только связи. Я мог бы попытаться уменьшить максимальное количество потоков, но никогда не узнаю наверняка. - person Benjamin Beaulieu; 04.12.2013
comment
@BenjaminBeaulieu, я помню, как много лет назад работал над небольшими веб-приложениями с Access, и многие пользователи могли его отключить. Вы используете TPL для переноса данных? Нельзя ли экспортировать в CSV, а затем использовать SSIS для загрузки данных в SQL? - person christiandev; 04.12.2013
comment
Мы используем .Net для повторной проверки, преобразования (формата и структуры) и переноса данных из Access в SQL Server. Я не думаю, что существует универсальный инструмент, который позволил бы нам настолько глубоко погрузиться в работу с пользовательским кодом .Net. Производительность также очень важна, поскольку у нас есть только небольшое временное окно для переноса всех данных каждый день. - person Benjamin Beaulieu; 04.12.2013
comment
У меня есть обновления ответа с некоторыми альтернативными решениями. Насколько большим будет дамп CSV базы данных MS Access? - person christiandev; 04.12.2013
comment
Я рассматривал возможность использования вашего первого решения (сброс Access в SQL Server, а затем запрос оттуда), но помощник по миграции в Access выдает ошибку и не может завершить миграцию (совершенно другая проблема). Даже если бы это сработало, миграция должна выполняться автоматически каждый день, поэтому использование помощника на самом деле не вариант. Очевидно, что перенос данных из Access в промежуточную область в SQL Server с кодом .Net, вероятно, приведет меня к той же проблеме, что и сейчас. - person Benjamin Beaulieu; 04.12.2013
comment
Что касается CSV-файла, я должен предположить, что он может довольно быстро вырасти за пределы пары ГБ, поэтому это не может быть долгосрочным решением. Однако мне нравится ваша идея обработки фрагментов данных в памяти. Я попытаюсь выяснить, может ли механизм кэширования помочь мне снять нагрузку с базы данных Access. - person Benjamin Beaulieu; 04.12.2013
comment
Не должно ли долгосрочное решение заключаться в отключении записи данных в Access? - person christiandev; 04.12.2013
comment
Мы планируем отказаться от Access, но я не могу сказать, когда и произойдет ли это на самом деле. База данных Access в настоящее время является частью операционной системы, а база данных SQL Server будет использоваться в качестве хранилища данных для отчетов/анализа данных из нескольких операционных систем. Планируется перевести все операционные системы на SQL Server, но это может занять некоторое время. В любом случае миграция должна будет довольно легко адаптироваться к изменению базы данных. - person Benjamin Beaulieu; 04.12.2013
comment
Принятие этого ответа, поскольку в нем упоминается возможная проблема с высоким уровнем стресса в Access. В итоге я закешировал большинство таблиц, необходимых для миграции, поэтому запросов выполняется гораздо меньше. - person Benjamin Beaulieu; 16.12.2013
comment
пример кода для процесса Reactive Extensions с использованием буфера для потоковой передачи данных? может в гитхабе? - person Kiquenet; 12.07.2019