![]() |
|
Модераторы: Akella |
![]()
|
|
| ksili |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
Такая проблема: несколько потоков удаляют записи из одной таблицы, используют для этого хранимую процедуру CUT_SMS, которая возвращает значения полей удалённой записи. И если вдруг два потока хватаются за одну запись, то, насколько я понял, происходит deadlock: один из них успевает удалить запись, а второй не может удалить уже удалённую запись.
При запуске из-под Билдера ситуация выглядит следующим образом: вылетает длинное сообщение об исключении, в котором есть слово deadlock, имя процедуры CUT_SMS, а также слова о конфликтующих апдейтах. Если продолжить выполнение программы, то она работает, но один из потоков перестает работать (то есть обращаться к таблице). Если просто запустить приложение из-под Винды, то никакого сообщения не выскакивает, но видно, что один поток перестаёт работать, и записи из таблицы удаляет только другой поток. Пробовал исправить проблему так. В БД создал таблицу, в которой хранится флаг занятости таблицы. Если он равен 1, то таблица занята другим потоком и сейчас из неё ничего читать и удалять не надо. При этом в начале процедуры CUT_SMS добавил:
где catch_sms_buffer - это процедура, которая просто устанавливает этот флаг в 1. Ну и соответственно в конце процедуры CUT_SMS освобождаю таблицу:
Но это проблемы не решило: теперь вылетает такое же сообщение, но именами двух процедур: CUT_SMS и CATCH_SMS_BUFFER. Я в этих блокировках не очень понимаю, но по-моему проблему можно решить как-то просто. Объясните мне пожалуйста, что я в этой ситации могу сделать. Это сообщение отредактировал(а) ksili - 3.7.2007, 06:12 -------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
||||
|
|||||
| ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
Вот суть сообщения об исключении:
Добавлено через 2 минуты и 6 секунд Сейчас заметил, что оно может возникнуть даже если в таблице не было ни одной записи. -------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
Оствляй на сервере в таблице или в контекстной переменной какое-то значение в удаляющем потоке, мол идёт удаление, и перед удалением во втором потоке проверяй значение
|
|||
|
||||
| ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
Дык я по-моему так и делаю:
В первой строке смотрим "на сервере в таблице" значение флага Во второй проверяем его и если он равен 1, значит сейчас с таблицей работает другой поток и ничего делать нельзя - exit Иначе сами занимаем таблицу (процедура catch_sms_buffer устанавливает значение флага в 1) и дальше читаем и удаляем, будучи уверенными, что другой поток в это время не сделает то же самое. Каждый поток выполняет эту проверку перед удалением. НО ПОЧЕМУ-ТО ТАКАЯ РУЧНАЯ БЛОКИРОВКА ТАБЛИЦЫ НЕ РАБОТАЕТ Меня вот ещё смущает, что вся моя процедура выполняется в контексте одной транзакции, соответственно, может то, что я занимаю таблицу (catch_sms_buffer) на самом деле не отображается сразу в базе и из-за этого блокировки не происходит. Хотя я же это делаю вызовом отдельной процедуры... -------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
||||
|
||||
| ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
И как это сделать? У меня такой код:
Пытался ещё поставить в процедуре CUT_SMS commit после установки флага в единицу и перед удалением записи, но в PSQL видимо такой команды нет. Добавлено через 9 минут и 53 секунды Ещё я забабашил компонент TpFIBErrorHandler. При возникновении вышеописанной конфликтной ситуации он постоянно выводит сообщение, которое я уже приводил. То есть раньше ещё можно было продолжать работать, но без одного потока, теперь же вообще нельзя, так как постоянно выскакивает MessageBox. Вот было бы неплохо в этом обработчике не только выводить сообщение об ошибке, но и подтверждать или откатывать закосяченную транзакцию, поскольку проблема-то, как я понял, в незавершённой транзакции. Вот только загвоздка в том, что компонент этот на главной форме приложения, а косяк происходит в отдельном потоке, заранее неизвестно каком. Это сообщение отредактировал(а) ksili - 3.7.2007, 08:28 -------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
| ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
Решил тут попробовать заблокировать запись:
Но что-то на with lock ругается. Говорит, не знаю такого... Добавлено через 1 минуту и 50 секунд Версия сервера: 2.0 -------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
| ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
Изменил тип транзакции c NO WAIT на WAIT. Ничего не изменилось, только в сообщении об ошибке исчезла строка
-------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
| ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
Вроде получилось. Поставил парметры транзакции:
Пока работает без косяков. Дальше посмотрим -------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
у тебя что, несколько потоков в одной транзакции работают?
Это сообщение отредактировал(а) Akella - 3.7.2007, 14:18 |
|||
|
||||
| ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
Нет, у меня несколько одинаковых потоков. В каждой кверя со своей транзакцией
-------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
а если всё в одну транзакцию впихнуть?
|
|||
|
||||
| ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: нет Всего: 17 |
А как это сделать?
Поместить на главной форме pFIBTransaction и у каждой квери в других потоках указывать эту транзакцию как основную? Но ведь тогда придётся наверно каждое обращение к Query запихивать в Synchronize -------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
| Akella |
|
|||
![]() Творец ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 18485 Регистрация: 14.5.2003 Где: Корусант Репутация: 20 Всего: 329 |
можно не на главную, а в DataModule, ну и запихивай, а что здесь плохого?
|
|||
|
||||
![]()
|
| Правила форума "Interbase" | |
|
|
Обязательно указание: 1. Версию InterBase (Firebird, Yaffil) 2. Способа доступа (ADO, BDE, IBX и т.д.)
Если Вам понравилась атмосфера форума, заходите к нам чаще! С Уважением, Akella. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Firebird, Interbase | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |