Курсорадаптер и max_user_connections | |
---|---|
Sandwich Автор Сообщений: 137 Дата регистрации: 08.02.2014 |
Здравствуйте
Сделал приложение, работающее с БД MySQL на веб-сервере. Использую курсорадаптеры. Все работало прекрасно, пока пользователь был один. Возникла необходимость работы с нескольких компьютеров. При запуске программы на 4-5 по счету компьютере получаю от ODBC - ... already has more then "max_ user_connections" active connections В настройках MySQl max_ user_connections = 100 (хостер не дает право изменять). Начал следить за подключениями через консоль MySQL: 1. Без запущенной программы - 8-12 активных подключений 2. Каждый запущенный экземпляр программы прибавляет еще ~20 Соответственно лимит быстро исчерпывается. На этой строке решил сделать паузу, потому что понял, что у меня 12 КАДов и для каждого из них создаю своё подключение. Исправил - все 12 "посадил" на один SQLSTRINGCONNECT. Ситуация немного улучшилась: каждый экземпляр программы добавляет ~12 подключений (итого можно запустить 6-7 экземпляров) Дальше понял, что из 12 таблиц мне нужно изменять только 2, остальные 10 - только получение данных. Поэтому для этих 10 КАДов после cad.cursorfill() поставил cad.destroy(). Количество подключений от этого не изменилось. В итоге 2 вопроса: 1. Почему в ситуации когда 12 КАДов сидят на одном соединении, MySQl показывает 12 подключений? 2. Как "отключить" 10 "readonly" КАДов (дабы сократить количество активных подключений)? |
Re: Курсорадаптер и max_user_connections | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Значит они НЕ висят "на одном соединении".
Стандартно делается один SQLSTRINGCONNECT() с флагом shared - полученный хендл напрямую НЕ используется, от него создаются новые хендлы при помощи SQLCONNECT. Эти новые хендлы и используются в курсорадаптерах, при этом в destroy их следует закрывать. При отладке можно использовать ASQLHANDLES() - без 2-го параметра и с ним, чтобы смотреть какие же существуют соединения и какие statement handles их используют. P.S. "отключать" ничего не надо - statement handle для "завершённой" выборки не должен потреблять серверных ресурсов (а клиентскими можно пренебречь - сам курсор наверняка гораздо больше памяти потребляет чем блок метаданных в odbc драйвере) - стоит лишь позаботится о синхронном режиме работы с соединением, для чего в курсорадаптере поставить fetchsize=-1 и отключить тем самым "прогрессивную" выборку - когда по сути одновременно фокс пытается данные закачивать в разные адаптеры. ------------------ WBR, Igor Исправлено 1 раз(а). Последнее : Igor Korolyov, 05.05.19 22:02 |
Re: Курсорадаптер и max_user_connections | |
---|---|
Sandwich Автор Сообщений: 137 Дата регистрации: 08.02.2014 |
Результаты мучений:
Вариант 1 lnCon=SQLSTRINGCONNECT() без shared У 12-ти КАДов .DataSourse=lnCon ASQLHANDLES выдает массив из 13 значений (от 1 до 13, видимо 1+12) Вариант 2 lnCon=SQLSTRINGCONNECT() с shared lnCon1=SQLCONNECT(lnCon) lnCon2=SQLCONNECT(lnCon) ... У 12-ти КАДов .DataSourse=lnConN ASQLHANDLES выдает массив из 25 значений (от 1 до 25, видимо 1+2*12) У КАДов.DataSourse идут 3,5,7...25 Соответственно после закрытия этих соединений в destroy, остаются какие-то дополнительные соединения 1,2,4,6...24 ? |
Re: Курсорадаптер и max_user_connections | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Изучай код (кады, поди от какого-то класса наследуются, может там есть свой код управления соединениями, может в формах использующих эти кады что-то делается с их DataSource, или если это "мастером" созданные кады - там тоже будет код управления соединением) - похоже что кто-то открывает и не закрывает дополнительные соединения. Скажем при работе с ораклом мы специально делали отдельные хендлы (но не соединения) для InsertCmdDataSource/UpdateCmdDataSource/DeleteCmdDataSourceType - через один общий с некоторыми версиями клиентских компонент были проблемы - так что один CAD у нас по 4 statement handle использовал (а можно и больше, там ещё на рефреш и на извлечение мемо-полей можно отдельный хендл задать). Конечно же они все закорывались в destroy адаптера.
Проверь для хендлов (пока ещё все 25 живые) 2,4,6... их SQLGETPROP(..,"ODBChdbc") - это "настоящий" хендл соединения - по идее он должен совпадать для всех хендлов порождённых от одного начального shared. Ну и ASQLHANDLES(...,1) и ASQLHANDLES(...,2) покажут общее это соединение или нет. ------------------ WBR, Igor |
Re: Курсорадаптер и max_user_connections | |
---|---|
Sandwich Автор Сообщений: 137 Дата регистрации: 08.02.2014 |
Чем дальше в лес (или влез), тем ...
Получается такая картина: В билдере создаю кад - cad_name. Указываю там Use connection string = 'Строка соединения №1'. Затем код
билдер в cad1.init прописывает
1. Как до создания cad1 задать ему нужное (не designtime) значение DataSource? 2. Как использовать галочку use connection settings in builder only в билдере? |
Re: Курсорадаптер и max_user_connections | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Сложно сказать, я как-то построителем не пользовался никогда У нас были свои базовые классы для cad, и свои генераторы (чтобы мутотень со списокм полей и базовыми запросами не руками прописывать, а только потом править, если надо).
ДО создания - никак. Да и не нужно это. Источник данных может прописываться из Init адаптера (как это делает построитель, только НЕ его кодом, а своим - тут то и прочувствуешь необходимость написания своего класса cad, от которого будут унаследованы все другие адаптеры), или в инфраструктурном коде использующем адаптеры (том где и прописан createobject("cadSomeData") - после этих Create но до вызова CursorFill и нужно задать DataSource). Помещать адаптеры в DE не советую, малоуправляемо и сложно в нормальном ООП стиле оформить. Для начала простейший вариант с созданием объекта-коллекции в Load формы и добавлением в неё нужных адаптеров (опять же всё кодом в Load - добавил, вызвал CursorFill - возможно с флажком NoData, если параметры ограничивающие выборки известны будут лишь позже, в Init формы или вообще будут браться из полей ввода на ней). ------------------ WBR, Igor |
Re: Курсорадаптер и max_user_connections | |
---|---|
Sandwich Автор Сообщений: 137 Дата регистрации: 08.02.2014 |
Успел разобраться сам, но не успел написать здесь. А построитель работает так: если НЕ ставишь галку use connection settings in builder only, то он формирует такой Init
Спасибо за помощь! |
© 2000-2024 Fox Club  |