![]() |
|
Модераторы: LSD |
![]()
|
|
| Гость_Станислав |
|
|||
|
Unregistered |
Небольшой Callcenter. Агенты при помощи клиентской программы получают контактные телефоны.
Само собой разумеется, различным агентам не должны попасть одинаковые телефоны одновремменно. Хорошо. Выбираем строку из таблицы, запираем ее(id агента в столбец, скажем "lock_agent_id") и говорим этот агент ее выбрал. Результат разговора сохраняется и телефон больше не выбирается. Тут все нормально. Но, сам выбор: допустим BEGIN SELECT phone_id,name,phone INTO @phone_id,@name,@phone FROM phones WHERE lock_agent_id IS NULL.... LIMIT 1 FOR UPDATE; UPDATE phones SET lock_agent_id=@agent_id WHERE phone_id = @phone_id; ... RETURN END Агенты не получат одновременно один и тот же номер, но если одновременно несколько агентов выбирают из таблицы, то один из них действительно получает номер, а остальные пустую строку. Кажется, выход только один,- запереть всю таблицу (LOCK TABLE) во время выбора. Правда, тогда всем остальным придется ждать, пока первый закончит операцию, потом другой и так далее. Нужеле нет другого выхода? Мне кажется, что это стандартная проблема, но к сожалению, я с ней столкнулся впервые. Может быть кто-то подскажет. Заранее благодарен. |
|||
|
||||
| Akina |
|
||||
|
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 13 Всего: 454 |
Сделай наоборот - сперва
-------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
||||
|
|||||
| LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 24 Всего: 538 |
Akina не сработает.
В Oracle первый запрос
Проходит нормально, а второй встает до тех пор пока первый не завершит транзакцию. И после этого меняет туже самую строку, что и первый запрос независимо от того как завершилась транзакция. А в Firebird, поведние не лучше. Второй запрос тоже встает, но после commita вываливается с deadlock -update conflicts with concurrent update. Здесь можно попробовать использовать select for update, если база поддерживает. Это сообщение отредактировал(а) LSD - 26.7.2005, 10:09 -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
| Гость_Станислав |
|
|||
|
Unregistered |
"SELECT FOR UPDATE". Пробовал самом начале в Postgres. Результат, как я и написал, - у второго выходит пустая строка, на "READ COMMITTED". На "SERIALIZABLE", - то, что описал LSD.
На MSSQL пробовал "REPEATABLE READ", - тот же результат. |
|||
|
||||
| Akina |
|
|||
|
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 13 Всего: 454 |
LSD
??? я тебя просто совсем не понимаю... так и должно быть! Что нужно автору? не налететь... поэтому первый запрос резервирует первую свободную строку БД за текущим челом, а второй просто ищет что именно зарезервировалось - мало занять, надо же сказать что именно было занято... Знать бы, где это происходит... на MS SQL (с соотв. правкой синтаксиса) это должно работать без проблем на одновременно поступающих запросах, лочить надо (и то - надо ли?) только изменяемую в первом запросе запись, причем что в хранимке, что в триггере, что отдельными запросами... -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
| LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 24 Всего: 538 |
Твой первый и второй запрос, выполняются в одной сессии. А я говорил про другое: если первый запрос, который пытается захватить строку, будет одновременно выполнен из разных сессий, то в зависимости от уровня изоляции транзакции мы получим разные результаты, или ошибку во второй транзакции или захват той же самой строки. Причем вторая сессия стоит до тех пор пока первая не завершит транзакцию. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
| Akina |
|
|||
|
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 13 Всего: 454 |
а-а-а...
-------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
| LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 24 Всего: 538 |
Кстати Станислав а какая СУБД? В Oracle например такой код работает:
-------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
| Guest |
|
||||
|
Unregistered |
База Postgres
В этом случае у первого проходит все нормально, второй, ждет конца трансакции первого, и в конце концов из функции получает строку, но она пустая.
В этом случае, второй, не обращая внимания на уже выполненный UPDATE первого, переписывает LOCK_AGENT_ID и выбирает эту же строку.
Это было на "READ COMMITTED". На "SERIALIZABLE" у второго ошибка "ERROR: could not serialize access due to concurrent update" в первом случае. Второй случай на "SERIALIZABLE" не пробовал. Сейчас попробую |
||||
|
|||||
| Гость_Станислав |
|
|||
|
Unregistered |
Забыл ввести свое имя в предыдущем сообщении...
|
|||
|
||||
| Гость_Станислав |
|
|||
|
Unregistered |
Во втором случае на serializable тот же результат: ERROR: could not serialize access due to concurrent update
|
|||
|
||||
| Stampede |
|
|||
![]() Гносеолог ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 963 Регистрация: 25.4.2005 Где: Calgary, Alberta, Canada Репутация: нет Всего: 144 |
Да ну и запирай на здоровье. Там вся транзакция - на микросекунду. Помни о заветах дядьки Оккама -------------------- "If you want something done right, do it yourself" По секрету: выучить английский - реально! |
|||
|
||||
| LSD |
|
||||||||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 24 Всего: 538 |
А если попробовать:
Полностью блокировок избежать не удастся. У нас есть некий общий ресурс (номера телефонов), на который претендуеют несколько пользователей. Добавлено @ 09:50
Зарегистрируйся и заходи почаще Это сообщение отредактировал(а) LSD - 28.7.2005, 09:48 -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
||||||||
|
|||||||||
| Гость_Станислав |
|
|||
|
Unregistered |
LSD
declare ...
Запирается вся таблица, вернее те строки, где пустой "LOCK_AGENT_ID". Т.е. те строки которые имеет уже номер агента остаются открытым. Следовательно агенты, которые в данный момент разговаривают по телефону смогут без проблем сохранить результат, и сказать номер отработат, - эту уже лучше, чем запирать всю таблицу. Но нужно еще проверить, пока что сомневаюсь, что сработает. |
|||
|
||||
| LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 24 Всего: 538 |
Я не написал, но после update PHONES..., должен идити commit. Т.е. Все свободняе номера телефонов, запираются только на момент "захвата" очередного номера, как только номер "захвачен" блокировка снимается.
-------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
![]()
|
| Правила форума "Общие вопросы по базам данных" | |
|
|
Данный форум предназначен для обсуждения вопросов о базах данных не попадающих под тематику других форумов:
Данный форум не предназначен для:
Если вы не соблюдаете эти правила, не удивляйтесь потом не найдя свою тему/сообщение.
Полезные советы: Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, LSD, Zloxa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | СУБД, общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |