dbExsress, одновременный Open() в разных потоках
Проблемы возникают при работе с БД, используя dbExpress. Точнее при МНОЖЕСТВЕННЫХ и ОДНОВРЕМЕННЫХ соединениях с СУБД (MS SQL, или Oracle, или Informix).
Проблему хорошо показать на примере, посему для примера и тестирования сделал вот такое:
1. Три компонента на форме: SQLConnection1,SQLQuery1 и Button1;
2. SQLQuery1.SQLConnection := SQLConnection1
3. SQLConnection1 настроен на соединение с СУБД (адреса, логины, пароли как положено)
4. При старте программы сразу SQLConnection1.Open()
5. По нажатию кнопки Button1 запускается цикл на 500 оборотов, в каждом обороте запускается НОВЫЙ поток
6. В каждом потоке :
- создаётся новый TSQLConnection : New_SQLConnection := SQLConnection1.CloneConnection();
- создаётся новый TSQLQuery : New_SQLQuery := new TSQLQuery(NULL);
- соединяется New_SQLQuery с New_SQLConnection : New_SQLQuery.SQLConnection := New_SQLConnection;
- выполняем какой-то запрос к БД
- разъединяемся New_SQLConnection1.Close();
- очищаем память delete New_SQLConnection1; delete New_SQLQuery;
Из этих 500 соединений удачно выполняются от 300 до 450, остальные, на шаге SQLConnection1.CloneConnection() отбиваются с разными ошибками : нет соединения, или сервер не найден, или всех лучше ошибка - Accsess Violation. Точный текст ошибки зависит от используемой СУБД.
Если делать не клонирование, а ручное заполнение параметров и после выполнить SQLConnection1.Open(), то ошибки вылетят те же на шаге Open(). То есть, разницы с клонированием нет.
Методом всяких тестов пришли к выводу - вылет происходит при МНОЖЕСТВЕННЫХ, ОДНОВРЕМЕННЫХ попытках создать соединение с БД. То есть, если открывать по очереди соединения (!) и даже не закрывать их, то все соединения выполняться. Если компьютер слабенький (не успевает он одновременно запустить столько потоков), то опять же проходит всё без ошибок. Чем сильнее ПК (брали для теста 4 разных) - тем больше ошибочных соединений из этих пяти сотен - значит чем больше потоков успевает запуститься одновременно, тем больше отбивается.
При чём ошибка ИМЕННО на клиентском месте, до сервера соединения и не доходит (проверяли - сервер ничего не отбивал). Начали грешить на параметр в Windows-е - разрешённое кол-во одновременных соединений TCP/IP. Запустили на Windows Server 2003, где таких разрешений 9999 - ошибки те же.
ВЫВОД : dbExpress при соединениии задействует что-то, что имеет ограниченый ресурс. Очень ограниченный . Прежде чем лепить какие-то заплатки в программу, избегая этой ошибки, надо выяснить ОТКУДА ЭТА ОШИБКА!!! Чего не хватает dbExpress???? Оперативки? Какого-то буфера сетевого?