Конференция "Базы" » Зависает программа после обрыва сетевого соединения с БД [D7, MySQL]
 
  • dmadma (14.10.13 00:20) [0]
    Здравствуйте!

    Попробуйте провести какой эксперимент.
    Создайте новое приложение, новая форма.
    Установите подключение к какой либо базе данных (например ADOConnection)
    База должна находится удаленно, на соседней машине или на хостинге.
    В свойствах в design-time устанавливаем connection:=true - всё ок
    Ставим на форму кнопку и таймер.
    В таймере выставляем 10 секунд и в обработчике пишем команду halt;
    Таймер по умолчанию отключен.
    По нажатии на кнопку пишем:
    включить таймер, далее сделать любой запрос из базы данных и показать результат на форме.
    Всё - этого достаточно для эксперимента.

    Запускаем программу (соединение уже установлено). Нажимаем на кнопочку. Раз - появляются результаты запроса и через 10 сек - прога вылетает. Всё отлично.

    Теперь вторая попытка, но с небольшим но...

    Запускам программу. Теперь вытаскиваем штекер из сетевой карты. Нажимаем на кнопочку. И ВСЁ.... ВИСИМ... Где таймер??? Почему не закрывается программа...

    Я понимаю, что соединение прервалось и могут быть какие-то там из-за этого заморочки, но почему таймер не срабатывает? Ведь мы его запустили до того, как начали делать запрос? Почему ВСЁ висит... Причем висит не по какому-то таймауту, а бесконечно...

    Пробовал с разными базами, пробовал под Win и под Lin - всё одно...
    Что делать? Может кто-то подскажет чего я не понимаю?
  • RWolf © (14.10.13 01:04) [1]
    предположу, что управление не покидает обработчик нажатия, останавливаясь на сделать любой запрос из базы данных.
    потому и не закрывается.
    отчего не генерируется исключение по ошибке связи — это отдельный вопрос.
  • dmadma (14.10.13 02:03) [2]
    Так в том то и дело - нет исключения... Попробуйте сами...
  • sniknik © (14.10.13 08:10) [3]
    > Попробуйте сами...
    100500 раз пробовали уже.

    если в драйвере стоит бесконечное ожидание то никогда не выйдет из зависания... при синхронной модели ты зависишь от того чтобы использованные методы возвращали управление. а т.к. у тебя обработчик блокирован (основной поток), то и таймер не работает, не дожидается события, ди и выполнятся ему негде, его обработчик тоже в основном потоке отрабатывает.
  • sniknik © (14.10.13 08:24) [4]
    +
    в D5 в самом ADO таймаут работал не правильно, приходилось один модуль из него в программу импортировать (чтоб генофонд не трогать) и делать правки... но в D7 там уже все нормально.

    ++
    > В свойствах в design-time устанавливаем connection:=true - всё ок
    в десигне коннект устанавливать вовсе не ок, так не обработаешь исключение при подсоединении. (это не по теме, т.к. у тебя на запросе, но... для инфы)
  • sniknik © (14.10.13 09:49) [5]
    > Попробуйте сами...
    > 100500 раз пробовали уже.
    100501-й раз, первый при вставленном штекере, второй с выдернутым -

    информикс
    0  Выполнено применительно к 100 записям
    1  EOleException : [Informix][Informix ODBC Driver][Informix]System error occurred in network function

    MSSQL
    2  Выполнено применительно к 100 записям
    3  EOleException : Ошибка подключения

    база/драйвер те, что есть, ставить mysql ради "попробуйте" нафиг.
  • dmadma (14.10.13 13:31) [6]
    Программа работает с БД MySql на соседнем компе через сетевое соединение.
    ОС Ubuntu Linux.

    После соединения, делаю запрос - получаю ответ - всё ОК.

    Попробовал вызвать ошибку:
    соединяюсь с базой - вытаскиваю штекер из сетевухи - делаю запрос - ...
    Далее программа висит около 18 минут и после этого дает исключение sql error lost connection...

    Почему так долго и где можно изменить это время до 10 секунд.
    Я понимаю, что выставляться это должно на клиенте, так как после разрыва сети сервер недоступен...

    Помогите разобраться...
  • Ega23 © (14.10.13 15:15) [7]
    Я в отдельном требе создавал отдельный адо-коннект с таймаутом на 15 секунд и с такой же connectionstring. И время от времени пинговал БД простым запросом, что-то типа 'select 1'. Любое исключение трактовал как обрыв связи, о чём сигнализировал главному потоку.
  • sniknik © (14.10.13 16:21) [8]
    так у него и поток повиснет на 18 мин...
    надо смотреть параметры подключения, проверить в чем нибудь "не авторском"..., + попробовать асинхронный режим (таймаут не должен зависеть от "зависания" драйвера),
  • Ega23 © (14.10.13 16:30) [9]

    > так у него и поток повиснет на 18 мин...

    дык ConnectionTimeout выставлялся явно.
    Хотя что-то припоминаю, были там какие-то проблемы с этим таймаутом.
  • sniknik © (14.10.13 16:37) [10]
    в D5, да были. но в D7 вряд ли..., ни разу не сталкивался. (стоит с последним 2м апдейтом - d7_ent_upd1_1.exe)
  • Ega23 © (14.10.13 16:39) [11]

    > в D5, да были. но в D7 вряд ли


    Я уже не помню, откровенно говоря...
  • sniknik © (14.10.13 16:43) [12]
    +
    кстати, ИМХО это не проблема таймаута... т.к. вот то что в [5] пробовал odbc iformix определил разрыв за 0.025 сек, mssql за 0.120 сек. разные да, но в любом случае время ГОРАЗДО меньше определенного (30 сек) таймаута.
  • Медвешонок Порошок (14.10.13 18:53) [13]
    дык ConnectionTimeout выставлялся явно.

    коннект у него успешно все законнектил.
    затем он выдернул шнурок и стал выполнять запрос.
    и его ConnectionTimeout уже ни к селу ни к городу.
  • dmadma (14.10.13 19:56) [14]
    >> коннект у него успешно все законнектил.
    >> затем он выдернул шнурок и стал выполнять запрос.
    >> и его ConnectionTimeout уже ни к селу ни к городу.

    да, всё правильно. выдергиваем шнурок уже после состоявшегося соединения и посылаем запрос - вот тогда висим 18 минут и срабатывает исключение. Если сначала выдернуть, а потом соединяться, то исключение срабатывает мгновенно - тут проблемы нет. Но почему именно через 18 минут и каким образом это поменять непонятно. Стучу бубном уже вторые сутки - и ноль... везде ноль...

    Кто-то отправляет менять настройки (переменные) на MySql-сервере, таймауты разные. Но причем здесь сервер. Он даже не получает запрос. Менял все возможные таймауты и всё равно 18 минут. Менял keep_alive в настройках ОС и всё равно 18 минут, а если быть точнее 17 минут и 45 секунд.

    Я понимаю, что можно засунуть в поток и пинговать, но позвольте. У меня крупный проект, куча различных соединений и если я всё это буду рассовывать по потокам и пытаться синхронизировать, то к 2100 году не доделаю. Мне кажется по правильному, процедура (метод) запуска запроса (пусть это будет .Open или .ExecSQL или .Active:=true) должна сразу выдвать исключение после обнаружения дисконнекта с сервером (пусть хоть с локальным или через сеть). В этом случае реконнектимся и едем дальше без проблем. А потоки в этом случае - это "пытаться запустить в космос велосипед с квадратными колесами".
  • Медвешонок Порошок (14.10.13 20:03) [15]
    Ты когда выдернул сетевой шнурок, сразу выдерни шнур монитора и шнур блока питания компа.
    Тогда никакого зависона видно не будет.
    Проверено, работает.
  • dmadma (14.10.13 20:29) [16]

    > Ты когда выдернул сетевой шнурок, сразу выдерни шнур монитора
    > и шнур блока питания компа.
    > Тогда никакого зависона видно не будет.
    > Проверено, работает.


    можно только питание дергать - остальное само отвалится...

    а если без шуток, то я не понимаю как все работают, ведь обрывы связи это не редкость... где этот таймаут, который выставлен на 18 минут и для какой цели это сделано???
  • sniknik © (14.10.13 22:08) [17]
    > Менял все возможные таймауты и всё равно 18 минут.
    да ты "гониш". (это про "все возможные", не 18 мин, пусть и примерно)

    > а если без шуток, то я не понимаю как все работают, ведь обрывы связи это не редкость...
    без шуток все прекрасно работает, как выше было по твоему "сами попробуйте", попробовано.

    > где этот таймаут, который выставлен на 18 минут и для какой цели это сделано???
    перечисли "все" (раз уж менял "все возможные") там может и найдется...
    цели нет, как нет и такого таймаута.
  • Ega23 © (15.10.13 10:27) [18]

    > коннект у него успешно все законнектил.
    > затем он выдернул шнурок и стал выполнять запрос.


    А в параллельном потоке "создал коннект - убил коннект" дёргается. Тут-то он эту байду и отловит.

    А почему именно 18 минут?
  • dmadma (15.10.13 20:15) [19]
    По поводу висящего запроса к базе данных MySql я выяснил, что сам по себе запрос отправляет данные и ждет ответа, при этом он не проверяет само соединение. Поэтому нужно проверять такие вещи отдельно. Для этого создается отдельный поток и в нем через интервал (10-60 сек) проверяется open-close через дополнительное соединение к этой же базе. Как только выскакивает исключение - значить соединение разорвано и нужно закрыть все другие соединения к базе.

    Ega23 прав...

    Но мне кажется было бы правильно, если сам запрос просто выдавал бы исключение в случае потери связи и все.

    Спасибо за помощь...
  • Ega23 © (15.10.13 22:55) [20]

    > Но мне кажется было бы правильно, если сам запрос просто
    > выдавал бы исключение в случае потери связи и все.


    А откуда он узнает, что произошёл именно обрыв связи?
    Реальный пример из реальной жизни: система проработала 5 лет в режиме 24х7, потребовалось "ужать" устаревшие данные. Скрипт работал примерно 4 часа. Результат выполнения - select result = @result;
  • sniknik © (16.10.13 07:56) [21]
    > А откуда он узнает, что произошёл именно обрыв связи?
    сетевое соединение обычно знает, что оно разорвано... если коннект установлен/устанавливается через сеть,  то почему бы ему не знать? ... не UDP же они используют.
  • Ega23 © (16.10.13 09:08) [22]

    > сетевое соединение обычно знает, что оно разорвано...

    Это если оно штатно разорвано. А если нет, то зависит от реализации: шлётся там внутри handshake или нет.
    Я пока ни одного коннекшена не знаю, у которого бы было такое событие.
  • brother © (16.10.13 09:27) [23]
    > сетевое соединение обычно знает, что оно разорвано

    где, как? имхо узнаем, по таймауту только...
  • brother © (16.10.13 09:29) [24]
    хотя по модели osi, сетевая может сказать, что коннекшин лост, но это под вопросом...
  • sniknik © (16.10.13 09:45) [25]
    > Это если оно штатно разорвано.
    а если оно держится внутри драйвера то как ADO в синхронном режиме поймет это, не получив управления?

    > но это под вопросом...
    для informix-а и mssql вопроса нет... а вот для mysql почему то есть... и вывод? сокет не знает, что его "разорвали"? чушь.
  • brother © (16.10.13 09:46) [26]
    разорвали или помехи на канале, как определить? таймаут!
  • Ega23 © (16.10.13 10:16) [27]

    > сокет не знает, что его "разорвали"?


    Я на минуточку не понял: а что, сокет сам регулярный пинг делает?
  • sniknik © (16.10.13 10:44) [28]
    если тип не дейтаграмы (UDP) то да
  • Ega23 © (16.10.13 10:59) [29]
    О как... А я был уверен, что это дело самому надо реализовывать.
  • brother © (16.10.13 11:11) [30]
    > то да

    а можно подробнее, я чет тож в первый раз слышу об этом
  • sniknik © (16.10.13 12:03) [31]
    и гугль в первый раз видишь?
    первая же ссылка по протоколу
    http://www.xnets.ru/plugins/content/content.php?content.217.5
    смотри к примеру раздел "гарантированная доставка", и там про служебную информацию.
  • brother © (16.10.13 13:49) [32]
    вот не вижу там реализацию ping в tcp протоколе! то, что ответом от клиента приходит подтверждение, так это понятно...
  • sniknik © (16.10.13 15:23) [33]
    не знаю чего ты там не видишь, а пинг это всего лишь "прозвон" коннекта/соединения... (подтверждение друг для друга)
    то ты в него "не веришь", а то тебе это понятно, а ping очевидно должен означать утилиту для юзера.
  • brother © (16.10.13 16:06) [34]
    > подтверждение друг для друга

    теперь ВАЖНЫЙ момент: в простое... а не во время передачи данных!
  • sniknik © (16.10.13 16:37) [35]
    не буду спорить, проще согласиться... да, "брат" лучше знает, а ТУПЫЕ разработчики низкоуровневых протоколов писавшие TCP именно так и делают, и в процессе передачи данных совсем не обращают внимания на то что данные не передаются... и ждут 18мин.
    плевать на на мои проверки у информикса/mssql, определивших разрыв в долю секунды, у них наверно случайно получилось 100500 раз подряд. случайно.
  • Ega23 © (16.10.13 16:37) [36]
    Розыч ругался нехорошими словами, но таки дал вот такую ссылку:
    http://www.rsdn.ru/article/net/keep_alive.xml
  • sniknik © (16.10.13 17:21) [37]
    > вот такую ссылку:
    по ней все с точностью до наоборот, в простое посылка проверочных пакетов не обязательна (даже по умолчанию отсутствует), но вот как только начнут передавать данные никакого таймаута не нужно чтобы определить разрыв... что собственно и происходит. по моим наблюдениям.

    p.s. в ADO тоже есть свойство "keep alive" но оно значит несколько иное - будет ли закрываться коннект при закрытии последнего открытого датасета, с последующим открытием первого открытого, или нет. а не собственно проверку коннекта.
  • brother © (16.10.13 17:43) [38]
    > и в процессе передачи данных совсем не обращают внимания
    > на то что данные не передаются... и ждут 18мин.

    где я об этом говорил???
  • brother © (16.10.13 17:48) [39]
    [35] ты бредишь или как?
    Я тебе говорю одно, ты уперся на другом, не вникая в мои слова...
  • brother © (16.10.13 17:53) [40]
    тогда так:
    > определивших разрыв в долю секунды

    механизм определения опиши (кратко) и найдем, то место, где мы недопонимем друг друга...
  • sniknik © (16.10.13 18:04) [41]
    > механизм определения опиши (кратко)
    кртк, пдмй чт присхдт н Cmd.Execute.
  • brother © (16.10.13 18:07) [42]
    ясн
  • Rouse_ © (16.10.13 22:24) [43]

    > sniknik ©   (16.10.13 17:21) [37]
    > > вот такую ссылку:
    > по ней все с точностью до наоборот, в простое посылка проверочных
    > пакетов не обязательна (даже по умолчанию отсутствует)

    Коль, позволю себе не согласиться с твоим утверждением :)
    Дело в том, что сокеты Windows, это не совсем полная трактация беркли.
    В частности сокет может получить уведомление о разрыве соединения и без выставления параметров SO_KEEPALIVE, которое ему направит драйвер сетевой карты, получивший уведомление о том что кабель выдернули. Правда это конечно не означает то, что данное уведомление получит вторая сторона канала.
  • Rouse_ © (16.10.13 22:27) [44]
    Да, ну и по поводу этого вашего ADO - Легыч меня сегодня с пристрастием пинал в курилке, как оно это все работает, так вот как работает ADO и почему оно не получает дисконнекта там, где обычная реализация сокета получает - сие мне не ведомо :)
  • sniknik © (16.10.13 23:35) [45]
    > В частности сокет может получить уведомление о разрыве соединения и без выставления параметров SO_KEEPALIVE
    не вижу ничего противоречащего, ну не стоит параметр для постоянного "прозвона", но при начале работы (передаче данных) он что пакеты не шлет, ответы/ексепты не анализирует?... вот и узнали. вот и "может получить". все сходится.

    > и почему оно не получает дисконнекта там, где обычная реализация сокета получает
    обычная реализация сокета одна... ну по сути, написана "дядей мелкософтом", а драйвера пишут чуть ли не каждый желающий... причем обмен(сокет/мемори/пайпы/...) идет внутри этих драйверов... не наводит на мысли?
    чисто ADO-шный (не зависящий от реализации драйвера) таймаут будет только в асинхронном режиме, ИМХО, т.к. в этом случае драйвер работает в отдельном потоке, и ADO не блокирует, т.е. есть шанс проверить/снять зависший поток (хотя делает он это или нет хз. ломает проверять... ну надо найти для начала зависающий драйвер, поставить для него сервер, ... да ну его нафиг, пусть остается просто домыслами).
  • Ega23 © (17.10.13 01:03) [46]

    > В частности сокет может получить уведомление о разрыве соединения
    > и без выставления параметров SO_KEEPALIVE, которое ему направит
    > драйвер сетевой карты, получивший уведомление о том что
    > кабель выдернули. Правда это конечно не означает то, что
    > данное уведомление получит вторая сторона канала.


    Ээээ, секундочку!
    Клиент - Свич - Сервер. Кабель был обрезан между свичём и сервером. Как клиент узнает, что ёк?
  • sniknik © (17.10.13 02:28) [47]
    > Как клиент узнает, что ёк?
    слова "гарантированная доставка" ни о чем не говорят? вот представь стреляешь из автомата по мишени... ты - клиент, мишень - сервер, пули - данные (пакеты), задание переложить весь рожок "на сервер"... с гарантией! т.е. выстрелил, тут же бинокль к носу, проверяешь для гарантии, попал? да - го то следующий выстрел, нет - добавляешь к рожку такую же пулю которой смазал и повторяешь (3 раза).
    и вот вопрос, как клиент (ты) узнает, что мишень пропала?

    протокол, это не почта России, типа послал, и тишина..., это взаимодействие... прекратилось/испортилось в нем что-то, как не узнать?
  • brother © (17.10.13 05:16) [48]
    > Кабель был обрезан между свичём и сервером

    no route to host - disconnect
  • brother © (17.10.13 05:19) [49]
    дельта времени, за которую мы об этом узнаем оч мала. но имхо, возможны ситуации, когда эта дельта будет больше, тот самый таймаут, но это для прикладного уровня, опять же имхо... (ситуацию пока не придумал ;) )
  • brother © (17.10.13 05:31) [50]
    о придумал, клиент льет данные на сервер, на магистрали авария, и пакеты идут 50x50, но идут, поднимается нагрузка на вспомогательный трафик, но обмен все еще идет. потом бац! разрыв как в [46].
    на транспортном уровне все понятно - сервер не доступен, но что делать софту? перед разъединением, по идее, он должен некоторое время попытаться восстановить соединение (на прикладном уровне). Вот он его и делает некоторое время (те таймаут времени, заложенном программистом), не получилось? полный дисконнект.

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

    теперь выводы: мы всегда знаем о проблеммах соединения клиента с сервером, даже если данные не передаются... но как мы будем это обрабатывать, это уже зависит от задачи... все таймауты, о которых я говорил выше, это таймауты программистов прикладного уровня, не более...
  • Ega23 © (17.10.13 08:21) [51]

    > слова "гарантированная доставка" ни о чем не говорят?


    Гарантированная доставка - это когда движуха есть. А я соединение установил и уехал в Углич на рыбалку.
  • sniknik © (17.10.13 09:47) [52]
    > А я соединение установил и уехал в Углич на рыбалку.
    тогда смотри ссылку которую сам дал... установлен параметр, значит, продолжая аналогию, есть специальный человек который время от времени "зырит" в бинокль на предмет на месте ли мишень... не установлен, считай этот человек в "отпуске".
  • Ega23 © (17.10.13 10:32) [53]

    > установлен параметр, значит, продолжая аналогию, есть специальный
    > человек который время от времени "зырит" в бинокль на предмет
    > на месте ли мишень... не установлен, считай этот человек
    > в "отпуске".


    Вот. И теперь мы плавно подходим к реализации драйверов доступа к БД. Вот почему никакая падла этот параметр не взводит в случае TCP?
  • sniknik © (17.10.13 11:11) [54]
    > Вот почему никакая падла этот параметр не взводит в случае TCP?
    а по большому счету тебе он нафига? вот ты соединился (что-то посмотрел с сервера), и уехал в Углич на рыбалку... завтра сеть "упала", и "поднялась" через 2 недели, только за полчаса до твоего возвращения... ты вернулся и снова что-то посмотрел, падения даже не заметил... смысл получать эксепты/загружать канал служебной инфой (платить за трафик если сеть-инет такой) все 2 недели бездействия??? при том что первое же активное действие тут же получит статус сети.
  • stas © (17.10.13 15:21) [55]
    dmadma
    В AdoCommand или AdoDataSet как вы там запрос выполняете, есть таймаут, вот его надо смотреть, а не AdoConnection.
    Для MySql есть свои компоненты, с ними получше работать чем с ADO.
  • Дмитрий (30.10.13 15:45) [56]
    Пользуюсь MySQL + AnyDAC.
    Но тоже интересно, как специалисты рекомендуют обставлять проблему.
    Пока вообще никаких специальных мер не принимаю.
    Что несколько смущает.
  • Ivan (01.12.13 06:53) [57]
    Предлагаю запихать коннект в отдельный поток, и перед тестом передавать управляющей переменной что соединение отключено. В потоке сделать тест если он зависает, то управляющая переменная уже со значением False если все гут то соединение будет  практически  мгновенными передаст упр. переменной статус true.
  • Ivan (01.12.13 06:55) [58]
    Вернее не соединение, а "прозвон"
 
Конференция "Базы" » Зависает программа после обрыва сетевого соединения с БД [D7, MySQL]
Есть новые Нет новых   [134427   +38][b:0.001][p:0.002]