Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Delphi |
![]() ![]() |
Топик располагается на нескольких страницах: ←Ctrl назад 1 .. 39 40 41 42 43 [44] 45 46 47 48 .. 50 вперед Ctrl→ |
PalychXX Member Откуда: Сообщений: 144 |
Здравствуйте! Delphi 10.2, штатный FireDac, БД SQLite Пишу Windows-службу, которая реализует TCP/IP-сервер, принимающий от клиентов данные, которые затем парсит, сохраняет в локальной БД, а отдельный поток периодически отправляет данные из этой БД POST-запросом PHP-скрипту для просмотра через web. Может быть, надо было выбрать вместо SQLite какой-нить FB или MS SQL, но в обычных приложениях без многопоточной работы с БД проблем со связкой FireDac+SQLite не наблюдал, решил и в службе попробовать ее, разрулив доступ к БД из нескольких потоков критическими секциями (одновременных клиентов не так много и высокая скорость доступа не сильно критична). Столкнулся с несколькими проблемами. Перед подключением к БД (событие BeforeConnect) я пытаюсь сделать валидацию БД примерно так: procedure Tdm.ConnectionBeforeConnect(Sender: TObject); const dbname = 'name.db'; var s: string; f: Boolean; begin try s := TPath.Combine(ExtractFilePath(ParamStr(0)), dbname); Connection.ConnectionString:='DriverID=SQLite;Database=' + s; // валидация БД SQLiteValidate.Database := s; if FileExists(s) then begin SQLog('Валидация БД...'); cs.Enter; try f := SQLiteValidate.CheckOnly; finally cs.Leave; end; if (not f) then begin SQLog('Внимание! БД повреждена'); end else SQLog('БД в порядке'); end;} except on e: Exception do begin SQLog(e.Message, True); end; end; end; А после подключения к БД - проверяю существование таблиц и статичных данных справочников в некоторых из них, затем вызываю VACUUM: procedure Tdm.ConnectionAfterConnect(Sender: TObject); var s: string; f: Boolean; begin try // создаем таблицы если не существуют sql := 'PRAGMA foreign_keys = off;' + 'BEGIN TRANSACTION;' + // создаем таблицы 'CREATE TABLE If Not Exists table1 (' + ' idx INTEGER PRIMARY KEY ASC' + ' UNIQUE' + ' NOT NULL,' + ' name TEXT NOT NULL' + ');' + ... // подтверждаем транзакцию 'COMMIT TRANSACTION;' + 'PRAGMA foreign_keys = on;' ; try cs.Enter; try Connection.ExecSQL(sql); finally cs.Leave; end; except on e: Exception do begin SQLog(e.Message, True); end; end; // заполняем таблицы значениями по умолчанию (если отсутствуют) FillDefaultValues; ClearTable(); // удаление старых записей Vacuum; // сжатие except on e: Exception do begin SQLog(e.Message, True); // raise Exception.Create(e.Message); end; end; end; procedure Tdm.Vacuum; begin try ChkConnect; SQLog('Vacuum...'); cs.Enter; try Connection.ExecSQL('VACUUM;'); finally cs.Leave; end; SQLog(sOK); except on e: Exception do begin SQLog(e.Message, True); end; end; end; И в onDestroy удаляю записи старше определенного времени, после чего делаю Backup: procedure Tdm.DataModuleDestroy(Sender: TObject); var dt: TDateTime; dir: string; begin try ClearTable; dt := Now; dir := TPath.Combine(ExtractFilePath(ParamStr(0)), 'backup'); DbBackup(TPath.Combine(dir, Format('db_%.4u_%.2u_%.2u.bak', [YearOf(dt), MonthOf(dt), DayOf(dt)]))); except on e: Exception do begin SQLog(e.Message, True); end; end; if Assigned(cs) then FreeAndNil(cs); end; procedure Tdm.DbBackup(const FileName: string); var s: string; begin try SQLog(Format('DbBackup (FileName = "%s")...', [FileName])); s := ExtractFilePath(FileName); if not DirectoryExists(s) then begin SQLog(Format('Создание папки: "%s"...', [s])); ForceDirectories(s); SQLog(sOK); end; SQLog('Создание резервной копии БД...'); SQLiteBackup.Database := Connection.Params.Database; SQLiteBackup.DestDatabase := FileName; cs.Enter; try SQLiteBackup.Backup; finally cs.Leave; end; SQLog(sOK); except on e: Exception do begin SQLog(e.Message, True); end; end; end; Запускаю, работает, наполняю данными. Через несколько дней замечаю, что после ребута ПК служба не стартовала, в логах последняя запись "Валидация БД..." и все, похоже, что на валидации случился вылет. Комментирую код валидации, делаю ребут, теперь в логах все останавливается на "Vacuum...". Комментирую и вызов этого метода, служба успешно стартует после перезагрузок. Возвращаю оба метода, удаляю БД, чтобы служба создала ее самостоятельно, опять пару-тройку дней все работает и после очередного ребута те же грабли. ЧЯДНТ? Не так делаю валидацию, не так вызываю VACUUM (кстати, попробовал в Connection.Params.SQLiteAdvanced прописать auto_vacuum=1, но не заметил, чтобы файл БД после удаления записей уменьшился в размерах, а вот вызов аналогичного пункта меню в SQLiteStudio сразу сжал его раза в 3), не при том событии делаю бэкап, как-то повреждаю БД? Еще при тесте интенсивной одновременной работы нескольких клиентов словил ситуацию, что полученные от них данные в течение одной минуты от всех отсутствуют, хотя после записи в БД ответ всеми клиентами был получен. Все остальное время все писалось в БД хорошо, поочередно обрабатывались по 1 пакету от каждого клиента. При записи данных из каждого потока дергаю процедуру дата-модуля, динамически создающую TFDQuery и формирующую запрос, ну и вдобавок qr.ExecSQL снова обернут критической секцией. Переключил LockingMode и Synchronous на Normal, попробую еще потестировать. Или в службе с многопоточным доступом к БД не стоит использовать SQLite и лучше сразу мигрировать на FB? Вообщем, буду признателен за критику и советы. :) |
14 мар 19, 12:45 [21832387] Ответить | Цитировать Сообщить модератору |
PalychXX Member Откуда: Сообщений: 144 |
З.Ы. Да, еще на случай багов FireDac попробовал скомпилить проект в 10.1, а также дома на самой крайней 10.3.1 CE, во всех случаях ситуация ровно такая же. |
14 мар 19, 12:55 [21832399] Ответить | Цитировать Сообщить модератору |
wadman Member Откуда: Санкт-Петербург Сообщений: 26952 |
Ребуты жесткие?
Я-бы сказал, что такое "крайняя"... |
||||
14 мар 19, 12:57 [21832403] Ответить | Цитировать Сообщить модератору |
Игорь_UUS Member Откуда: г. Екатеринбург Сообщений: 680 |
Мучительно больно использовать TVP в mssql. Багов много... все тянуться с XE7! 1.Нельзя использовать более одной переменной табличного типа в MSSQL. Вторая заполненная данными табличная переменная попросту приходит пустой в хранимку mssql. 2.Если в хранимой процедуре используется тип NVARCHAR(MAX), и за ней идёт табличная переменная, то последняя запись внесённая в табличную переменную не доходит до MSSQL. Т.е. чтоб работало корректно, нужно чтоб все переменные хранимки табличного типа шли первыми а за ними уже все переменные имеющие тип NVARCHAR(MAX). 3.С драйвером "неатив11" табличные переменные и вовсе не работают!!! (ПРОСТО ЖЕСТЬ!!!). Чтоб обойти все эти баги приходиться придумывать всякие хитрости... табличные переменные сильно не доведены до ума. |
||
14 мар 19, 13:27 [21832456] Ответить | Цитировать Сообщить модератору |
Игорь_UUS Member Откуда: г. Екатеринбург Сообщений: 680 |
Когда я озвучивал Dmitry Arefiev данные баги года три назад, услышал в ответ, что это недоработка со стороны майкрасофт... теперь... заставить бы работать TVP ещё для последнего драйвера "неатив 11-го" |
||||
14 мар 19, 13:32 [21832471] Ответить | Цитировать Сообщить модератору |
PalychXX Member Откуда: Сообщений: 144 |
Раз в сутки в планировщике прописано задание "shutdown -r -f". Ну и обычная перезагрузка при тестах.
10.3.1 (Version 26.0.33219.4899). |
||||
14 мар 19, 13:34 [21832475] Ответить | Цитировать Сообщить модератору |
Michael Longneck Member Откуда: Москва Сообщений: 2326 |
На текущий момент я практически всё довёл до ума, и никаких проблем не ощущаю, 2 пункт не проверял. Исправлений пришлось сделать побольше чем я раньше описал. Native Client 11 сильно не новый драйвер. |
||
14 мар 19, 14:32 [21832627] Ответить | Цитировать Сообщить модератору |
Игорь_UUS Member Откуда: г. Екатеринбург Сообщений: 680 |
Что касается Native Client 11, новый/не новый... он идёт в комплекте установки mssql2016-2017... других просто не пробовал, и тут другой вопрос, идёт ли поддержка FD более нового чем 11-й драйвер?! |
||||
14 мар 19, 15:07 [21832682] Ответить | Цитировать Сообщить модератору |
Michael Longneck Member Откуда: Москва Сообщений: 2326 |
Не знаю. "Поддержка" это просто константы в файле. Дописал и у меня на XE7 поддерживается до ODBC Driver 17 включительно. |
14 мар 19, 15:15 [21832696] Ответить | Цитировать Сообщить модератору |
PalychXX Member Откуда: Сообщений: 144 |
Хочу для сравнения попробовать то же самое с FB, пока время позволяет. Правильно я понимаю, что если установить сервер FB, то FireDac из Delphi редакции Pro без купленного Client/Server пака не даст подключиться даже к серверу на 127.0.0.1 и в этом случае мне нужно работать через IBX или другие альтернативные компоненты? А то в табличке с редакциями Delphi фраза "Создание приложений для баз данных с локальным и встроенным подключением" вызывает вопрос, чем локальное подключение отличается от встроенного, является ли оно подключением к серверу на локалхосте или это что-то другое. |
15 мар 19, 09:43 [21833311] Ответить | Цитировать Сообщить модератору |
Vlad F Member Откуда: Сообщений: 1341 |
PalychXX, Говорят, что всеже даст, просто это будет нарушением соглашения. Но если это не смущает, то флаг те в руки проверить/доложить. |
15 мар 19, 10:18 [21833362] Ответить | Цитировать Сообщить модератору |
PalychXX Member Откуда: Сообщений: 144 |
А в случае с IBX не будет нарушением? Про ADO в свое время сотрудник Эмбаркадеры отвечал, что можно по сети. З.Ы. Наконец, словил на тестах в логах ошибку:
Мда, с SQLite в данном случае, видимо, лучше мигрировать на клиент-серверную БД... |
||||
15 мар 19, 10:24 [21833376] Ответить | Цитировать Сообщить модератору |
Vlad F Member Откуда: Сообщений: 1341 |
PalychXX, А в случае с IBX, говорят, что не будет.)) Да, и реализовывай в своих экспериментах сразу по отдельному подключению на каждый поток, что бы не дискредитировать попусту используемые библиотеки. |
15 мар 19, 10:37 [21833386] Ответить | Цитировать Сообщить модератору |
PalychXX Member Откуда: Сообщений: 144 |
Чудесно, тогда попробую FB + IBX, чтобы наверняка. Про отдельные подключения весьма дельный совет, спасибо! Так и сделаю. |
||
15 мар 19, 16:30 [21834048] Ответить | Цитировать Сообщить модератору |
Arioch Member Откуда: Сообщений: 11101 |
http://www.loginovprojects.ru/index.php?page=ibxfbutils |
||
15 мар 19, 18:23 [21834195] Ответить | Цитировать Сообщить модератору |
Vlad F Member Откуда: Сообщений: 1341 |
Мы ждем от тебя заключения.)) |
||
15 мар 19, 22:11 [21834367] Ответить | Цитировать Сообщить модератору |
PalychXX Member Откуда: Сообщений: 144 |
Спасибо, пул подключений самое то, что нужно для этой задачи!
Ну чтож.))) Наконец дошли руки сварганить несколько таблиц и пару хранимок в FB. Попробовал модули для IBX от Дмитрия Логинова, при первом знакомстве все понравилось. Без лишнего геммора в потоках получаю подключение из пула, выполняю запросы/хранимки и возвращаю подключение в пул, красота. По крайней мере на 500 одновременных потоках в клиент-серверной версии все писалось в базу на ура. Допишу модуль и попробую в боевом проекте. А что, IBX так до сих пор и не поддерживает x64 компиляцию? И у FireDac из коробки нет пула подключений (судя по докам на Эмбаркадере, с ним как раз нужно для каждого потока свой Connection создавать)? В данном проекте это без разницы, но в планах еще клиент-серверные приложухи, где билды под x32 и x64 очень желательны. Если понадобится FireDac с сеткой, к старой лицензии все еще можно докупить ДБ-аддон за 400 баксов или для сетевого FD чтобы ничгео ен нарушать катит только новая лицуха Enterprise/Architect? |
||||
20 мар 19, 16:48 [21838725] Ответить | Цитировать Сообщить модератору |
Arioch Member Откуда: Сообщений: 11101 |
PalychXX, это не мне, это вот этому вот - https://www.sql.ru/forum/memberinfo.aspx?mid=109526 |
20 мар 19, 17:46 [21838793] Ответить | Цитировать Сообщить модератору |
kenesg12 Member Откуда: Казахстан Сообщений: 24 |
Здравствуйте знатоки! Перешел на Firebird 3.0, и тут заметил что при выходе программа зависает и дальше ее вырубать только через диспетчер. Также Firebird необходимо перезапускать, т.к. уже не подключается к базе. При исследовании обнаружил, что зависание происходит в момент деактивации FDEventAlerter. Как только передаю значение false, все уходит в зависон. Подскажите как победить такую ситуацию, это баг или что настроить нужно? В 2.5 все работало как часы. |
17 апр 19, 20:49 [21865574] Ответить | Цитировать Сообщить модератору |
kenesg12 Member Откуда: Казахстан Сообщений: 24 |
kenesg12, Проблему решил. У меня динамически создаются обьекты и каждый объект добавляет ивент в список TFDEventsAlerter, так вот заметил, что если добавлять винтов больше 20-25, то данный компонент не работает корректно и при разрыве соединения зависает. Но если меньше то норм. В общем если ивентов становиться больше 10 то создаю динамически новый алертер и т.д. Работает стабильно. Вот такая особенность в FB3.0 |
20 апр 19, 09:53 [21867694] Ответить | Цитировать Сообщить модератору |
cptngrb Member Откуда: Сообщений: 663 |
В FireDac есть пул соединений. У пула есть два параметра POOL_CleanupTimeout The timeout (msecs) when FireDAC will remove connections unused more than POOL_ExpireTimeout time. Default value is 30000 msecs (30 secs).Время, через которое пул удаляет ненужное соединение. POOL_ExpireTimeout The time (msecs) after which the inactive connection may be deleted from the pool and destroyed. Default value is 90000 msecs (90 secs).Время, через которое пул может удалить неактивное соединение. А что такое ненужное и неактивное в нотации Oracle? |
7 июн 19, 16:51 [21904729] Ответить | Цитировать Сообщить модератору |
X-Cite Member Откуда: Минск Сообщений: 1810 |
Неважно какая нотация.. Пул приложений у FireDAC свой собственный велосипед и абстрагирован от СУБД. Он не использует пулы от ODBC и т.п. |
7 июн 19, 20:20 [21904924] Ответить | Цитировать Сообщить модератору |
X-Cite Member Откуда: Минск Сообщений: 1810 |
Из-за этого кстати могут возникать проблемы при переиспользовании. Например пул ODBC под MSSQL при каждом переиспользовании соединения вызывает sp_reset_connection, которая чистит весь контекст соединения от мусора который мог остаться при предыдущем вызове. Чего, как я понял FD не делает. И если вы забыли удалить временную таблицу, то при следующем переиспользовании соединения в другом месте может выйти это боком. |
7 июн 19, 20:23 [21904926] Ответить | Цитировать Сообщить модератору |
Dmitry Arefiev Member Откуда: Сообщений: 9923 |
Нужен тикет и тогда будет делать. |
7 июн 19, 20:25 [21904927] Ответить | Цитировать Сообщить модератору |
cptngrb Member Откуда: Сообщений: 663 |
X-Cite, хорошо, перефразирую А что такое ненужное и неактивное соединение в нотации FireDac? |
10 июн 19, 08:35 [21905651] Ответить | Цитировать Сообщить модератору |
Топик располагается на нескольких страницах: ←Ctrl назад 1 .. 39 40 41 42 43 [44] 45 46 47 48 .. 50 вперед Ctrl→ |
Все форумы / Delphi | ![]() |