Страница 1 из 1

ADO.NET - проблема с множественными подключениями к БД

Добавлено: 14 июл 2011, 22:03
mtripathi
Борюсь (пока безуспешно) с такой проблемой: при подключении к БД из приложения .NET через ADO.NET provider v.2.6.5, не могу к этой же БД подключиться другим приложением - сервер отвечает: "IO error during "CreateFile (open)" operation for file "xxx.fdb". Error while trying to open file. The process cannot access the file because it is being used by another process."

Если мой .NET клиент не подключен к БД - любое другое приложение подключается без проблем. Но в этом случае мой клиент не может подключиться с той же ошибкой.

Такое ощущение, что ADO клиент требует от сервера эксклюзивного доступа к БД, но в строке коннекта ничего похожего не нашел чтобы отключить эту функцию. Кто-нибудь сталкивался с подобной проблемой?

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 15 июл 2011, 00:01
hvlad
Выглядит как использование встроенного (embedded) сервера

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 15 июл 2011, 11:00
mtripathi
нет, это исключено. я специально проверял, что клиент подключен к полнофункциональному серверу Firebird, а не к embedded.
netstat показывает наличие tcp-подключения от моего клиента к серверу на порту 3050

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 15 июл 2011, 12:41
hvlad
Значит или другое приложение лезет через embedded (или другой экземпляр сервера), или .Net приложение лезет на сервер к другой БД, а "проблемную" открывает через embedded.

Чудес не бывает. Два разных приложения пытаются открыть файл БД в эксклюзивном режиме каждое.

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 15 июл 2011, 13:32
mtripathi
Согласен, чудес не бывает. Поэтому я взял ProcessExplorer, чтобы посмотреть кто держит файл. Оказалось, файл держит только 1 процесс - fbserver.exe, в обеих случаях (в случае когда подключен мой клиент, и в случае, когда подключено другое приложение. Другое приложение - это на самом деле IBExpert, который уж точно не будет лезть через Embedded). Таким образом, версия о том что другое приложение или мой клиент лезет через embedded - отпадает.

Попробую резюмировать еще раз всю последовательность:

Шаг 1. Подключаюсь к БД из моего приложения, использующего ADO .NET - проблем нет, подключается великолепно.
Шаг 2. При подключенном моем приложении (см. Шаг 1), пробую подключиться к этой же базе через IBExpert - FB сервер отвечает, что файл занят
Шаг 3. При подключенном моем приложении (см. Шаг 1), проверяю кто держит файл БД с помощью ProcessExplorer - файл держит только 1 процесс - fbserver.exe.
Шаг 4. Отключаю свой клиент.
Шаг 5. Проверяю, кто держит файл БД с помощью ProcessExplorer - файл никем не занят (как и ожидалось, ибо клиент отключен)
Шаг 6. Подключаюсь к БД с помощью IBExpert - проблем нет, подключается великолепно (ибо мой клиент не подключен)
Шаг 7. Пробую подключиться моим клиентом - сервер отвечает что файл занят
Шаг 8. Проверяю, кто держит файл БД с помощью ProcessExplorer - файл держит только 1 процесс - fbserver.exe.

Дополнительно делаю еще 1 шаг, чтобы убедиться что проблема не в сервере Firebird:

Шаг 9. При подключенном IBExpert (см.Шаг 6) пробую подключиться любым другим клиентом, не использующим ADO .NET - подключается без проблем хоть 10 раз.

Таким образом, вопрос: почему на Шаге 2 и Шаге 7 сервер отвечает, что файл занят?

Единственная разумная версия, которая мне приходит в голову, - клиент ADO .NET каким-то образом требует от сервера монопольного доступа к файлу.
Вопрос - каким таким образом он это делает и как это предотвратить? Или я где-то не прав в цепочке рассуждений?

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 15 июл 2011, 14:37
Dimitry Sibiryakov
Угу, неправ.
mtripathi писал(а):Другое приложение - это на самом деле IBExpert, который уж точно не будет лезть через Embedded).
Дальше можно не читать, ибо это предположение - ошибочно. В состав IBExpert входит Firebird Embedded, которым он пользуется направо и налево.

isql рулит!!!

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 15 июл 2011, 15:41
hvlad
mtripathi писал(а):Единственная разумная версия, которая мне приходит в голову, - клиент ADO .NET каким-то образом требует от сервера монопольного доступа к файлу.
Вопрос - каким таким образом он это делает и как это предотвратить?
Никаким. Клиент не может потребовать от сервера такого доступа.
Можно перевести БД в шатдаун, можно потребовать сделать валидацию, которая не допускает посторонних подключений, но сообщение об ошибке будет другим.
mtripathi писал(а):Или я где-то не прав в цепочке рассуждений?
Конечно. Скорее всего ты что-то не видишь. Например второй экземпляр сервера...

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 15 июл 2011, 16:48
mtripathi
УРА, НАШЕЛ!!! Спасибо Дмитрию, натолкнул на мысль. Хотя он был и не совсем прав )))
Возможно IBExpert и в самом деле может использовать embedded server, точно не знаю, но зато я на 100% уверен что в моем случае он подключается к настоящему FB серверу. (доказательства в Шагах 9 и 8 моего предыдущего поста).

Оказалось, что проблема на самом деле не в IBExpert, не в embedded server и не в ADO.NET. Проблема в том, как fbserver обрабатывает символические ссылки.

Поскольку я считаю это как минимум некорректностью реализации сервера, а как максимум - багом, то детально опишу причины проблемы.
Сформулировать можно в общем случае так: "При одновременном подключении 2 и более независимых клиентов к одному и тому же файлу БД через FB server, при условии, что один из клиентов сообщает серверу путь к файлу, отличающийся от пути, сообщенного серверу первым подсоединившимся клиентом, сервер отказывает клиенту в подключении мотивируя это тем, что файл уже используется другим приложением".

В каком случае пути к одному и тому же файлу могут отличаться? в случае, если используется символическая ссылка на каталог. Пример:
На диске С: в каталоге db лежит файл application.fdb.
На этом же диске создана символическая ссылка (symlink или junction) на каталог db с именем sdb.
В этом случае, к файлу application.fdb можно "добраться" двумя разными путями, которые абсолютно эквивалентны с точки зрения операционной системы:

1) c:\db\application.fdb
2) c:\sdb\application.fdb

Однако же, эти два пути представляются серверу Firebird абсолютно различными! Поэтому, если вы попытаетесь подключиться ЛЮБЫМ клиентом (даже упомянутым Дмитрием isql.exe) к одной и той же БД, используя при первом подключении путь (1), а при втором - путь (2), сервер отвергнет вторую попытку подключения!!!

Вероятнее всего, когда сервер проверяет путь к БД, к которой клиент хочет подключиться, он сравнивает его с путями уже имеющихся подключений. Не найдя совпадения, сервер считает что он этой БД не подключен, а следовательно требует монопольного доступа к файлу. Что не есть корректно (на мой взгляд).

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

А можно просто нам, разработчикам, зарубить на носу - всегда серверу передавать в строке коннекта только абсолютный путь, без всяких ссылок.
В любом случае, всем спасибо за участие, для меня проблема решена :-)

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 16 июл 2011, 11:49
kdv
а следовательно требует монопольного доступа к файлу. Что не есть корректно (на мой взгляд).
корректно, и более чем. При первом коннекте сервер проверяет монопольно transaction inventory pages, с целью найти транзакции в активном состоянии, чего при первом подключении быть не должно. Если он их находит (было нештатное выключение), то переводит в состояние rollback.

p.s. симлинки на базу - это надо же додуматься :-)

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 16 июл 2011, 13:29
mtripathi
Мое предположение о некорректности относилось НЕ к проверке транзакций в активном состоянии, а к проверке путей к файлу базы данных.
Как я описал в предыдущем посте, экспериментально установлено, что сервер при коннекте не ресолвит пути к БД в случае наличия в них симлинков.
Если разработчики намерены разобраться в проблеме и ее устранить, могу предоставить подтверждающие мои слова скриншоты/видео и прочие необходимые доказательства.
Если нет, или если разработчики не считают это проблемой - не беда, главное что workaround найден.

Насчет "додуматься" до использования симлинков - все достаточно просто. Я думаю, что я не первый, кто решил размещать локальную БД приложения в профиле пользователей, в специально отведенном для данных приложения каталоге - %APPDATA%. Как известно, доступность иных каталогов на запись отнюдь не гарантирована последними версиями Windows c функциями UAC и прочими заморочками безопасности. Также известно, что путь %APPDATA% содержит симлинки в Windows 7 для совместимости с ранними версиями Windows, пример:
- в Windows XP:
%APPDATA% = \documents and settings\user\Application Data - абсолютный дисковый путь
- В Windows 7:
%APPDATA% = \Users\user\Appdata\Roaming - абсолютный дисковый путь
%APPDATA% = \documents and settings\user\Application Data - путь с символической ссылкой для совместимости с ХР и более ранними.

каким образом этот эффект отражается на проблеме с доступом к базе данных Firebird из разных приложений - детально и с примерами описано в предыдущем посте.

Поэтому авторство идеи с симлинками принадлежит, к счастью, не мне. :-)

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 16 июл 2011, 14:30
hvlad
Также известно, что путь %APPDATA% содержит симлинки в Windows 7
Макросы с симлинками не надо путать.

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 16 июл 2011, 14:31
hvlad
Я, персонально, не считаю это проблемой. Если кто-то считает иначе - трекер ещё не закрыли.

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 16 июл 2011, 15:18
mtripathi
hvlad писал(а):
Также известно, что путь %APPDATA% содержит симлинки в Windows 7
Макросы с симлинками не надо путать.
Вы не поняли. Я не говорил, что макрос %APPDATA% является симлинком. Я говорил, что в Windows 7 каталог \documents and settings\user\Application Data содержит символические ссылки, конкретнее: "documents and settings" ссылается на каталог "Users", а "Application Data" ссылается на "AppData\Roaming".

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 16 июл 2011, 15:57
mtripathi
hvlad писал(а):Я, персонально, не считаю это проблемой. Если кто-то считает иначе - трекер ещё не закрыли.
http://tracker.firebirdsql.org/browse/CORE-3558

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 17 июл 2011, 14:50
Dimitry Sibiryakov
mtripathi писал(а):Предлагаемое решение: перед проверкой пути к БД, сервер должен разрешить все символические ссылки и сравнивать абсолютные дисковые пути, лишенные символических ссылок.
А в Windows есть API для разрешения символических ссылок? Что-то я беглым взглядом в MSDN такого не нашёл...

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 17 июл 2011, 16:07
mtripathi
Я тоже такого API не видел. Скорее всего, надо разбирать путь на компоненты и смотреть - является ли конкретный каталог символической ссылкой, или нет, а затем заново собирать путь

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 17 июл 2011, 23:07
Dimitry Sibiryakov
О, я наконец-то вспомнил какую часть букваря аффтар пропустил мимо ушей: http://ibase.ru/devinfo/dontdoit.htm

Re: ADO.NET - проблема с множественными подключениями к БД

Добавлено: 18 июл 2011, 21:21
mtripathi
Dimitry Sibiryakov писал(а):О, я наконец-то вспомнил какую часть букваря аффтар пропустил мимо ушей: http://ibase.ru/devinfo/dontdoit.htm
увы, поздно :-)
к счастью, уважаемый Дмитрий из багтрекера изволил согласиться со мной, признав вышеописанное несчастье багом, хотя и мелким (в чем я с ним полностью согласен). Так что, возможно уже в ближайшие десятилетия, наши внуки будут читать сей почтенный документ: http://ibase.ru/devinfo/dontdoit.htm без первого пункта :-)