Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Блокировка записи (строки), Блокировка записи (строки) 
:(
    Опции темы
_prishelec_
Дата 29.12.2010, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 24.11.2007

Репутация: нет
Всего: нет



Всем добрый день!
Имеем к примеру таблицу:
Код

id|name|state
12|Вася|0



Поле state принимает одно из двух значений: 0/1; Оно отвечает за то, обрабатывается ли в данный момент времени текущая запись. Нечто вроде флага блокировки.

У меня имеется два оператора:
Код

SELECT …;    
UPDATE …;


Смысл должен быть такой: если мы находим запись, то должны эту запись по ее id заблокировать. 

------

К примеру нам select вернул запись с id = 1. Мы должны сделать  “
Код

update table_name set state = 0 where id = 1
”.

Клиентов большое множество, которые работают с текущей БД. Как сделать так чтобы никакой другой клиент не вклинился между select и update?
Пробовал транзакции (таблицы соответственно перевел в innodb).
Транзакция
Код

START TRANSACTION;
...
COMMIT;

Не помогает.

Запись должна быть заблокирована, до тех пор, пока она обрабатывается. А потом тот же клиент (прога , который ее обработает, устанавливает поле state в 1.

Раньше делал наоборот, сначала update по определенному условию (в дополнительное поле записывал уникальный GUID сгенеренный клиентом), и поэтому GUID делал выборку. Было все ок. Но ощущулась нагрузка на БД.

Заранее спасибо!


PM MAIL WWW ICQ Skype   Вверх
Akina
Дата 29.12.2010, 14:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(_prishelec_ @  29.12.2010,  14:42 Найти цитируемый пост)
Как сделать так чтобы никакой другой клиент не вклинился между select и update?

Самое простое - собрать два запроса в один.
Или нормально настроить транзакции, задать уровень изоляции.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Zloxa
Дата 29.12.2010, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 33
Всего: 161



Цитата(Akina @  29.12.2010,  14:45 Найти цитируемый пост)
задать уровень изоляции. 

при serializable, емнип, на блокировке должен будет встать апдейт а не конкурирующий селект


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Akina
Дата 29.12.2010, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(Zloxa @  29.12.2010,  16:29 Найти цитируемый пост)
при serializable, емнип, на блокировке должен будет встать апдейт а не конкурирующий селект 

в
Код

start transaction;
select ... ;
update ... ;
commit;

?  smile 


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
_prishelec_
Дата 29.12.2010, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 24.11.2007

Репутация: нет
Всего: нет



Цитата(Akina @ 29.12.2010,  14:45)
Цитата(_prishelec_ @  29.12.2010,  14:42 Найти цитируемый пост)
Как сделать так чтобы никакой другой клиент не вклинился между select и update?

Самое простое - собрать два запроса в один.
Или нормально настроить транзакции, задать уровень изоляции.

Не выйдет .Все это находиться в хранящейся процедуре.

Добавлено @ 17:02
Цитата(Akina @ 29.12.2010,  14:45)
Цитата(_prishelec_ @  29.12.2010,  14:42 Найти цитируемый пост)
Как сделать так чтобы никакой другой клиент не вклинился между select и update?

Самое простое - собрать два запроса в один.
Или нормально настроить транзакции, задать уровень изоляции.

Пробовал
Код

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
[color=green]SELECT ...;
UPDATE ...;    [/color]
COMMIT;


Тоже непомогает.

вобще сама процедура вот

Код

// procedure
DELIMITER |
CREATE PROCEDURE select_domain (IN ip VARCHAR(15), OUT domain_id INT, OUT host VARCHAR(150), OUT transfers INT, OUT template_link VARCHAR(50), OUT user_id INT)
BEGIN
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
    START TRANSACTION;
    SELECT domains.id, domains.host, domains.transfers, parkings.link, users.id INTO domain_id, host, transfers, template_link, user_id FROM
 domains 
JOIN parkings ON domains.parking_id = parkings.id
JOIN users ON domains.user_id = users.id
WHERE parkings.state = '1' AND domains.state = '1' AND domains.domen_lock = '0' AND domains.clicks < domains.limit_clicks AND users.state = '1' AND users.credits > '0'
AND domains.id NOT IN (SELECT list_ip_clicks.domain_id FROM list_ip_clicks WHERE list_ip_clicks.ip = ip) ORDER BY RAND() LIMIT 0,1;

    IF (domain_id > 0) THEN
        UPDATE domains SET domen_lock = '1' WHERE id = domain_id;
    END IF;
    COMMIT;
END;
|
DELIMITER ;


Правда ее разбирать не советую, а то еще мозг сломается перед НГ. smile 
Я ее так для сюда вставил.


Это сообщение отредактировал(а) _prishelec_ - 29.12.2010, 17:09
PM MAIL WWW ICQ Skype   Вверх
Zloxa
Дата 29.12.2010, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 33
Всего: 161



Цитата(Akina @ 29.12.2010,  16:15)
Цитата(Zloxa @  29.12.2010,  16:29 Найти цитируемый пост)
при serializable, емнип, на блокировке должен будет встать апдейт а не конкурирующий селект 

в
Код

start transaction;
select ... ;
update ... ;
commit;

?  smile

Да, если я правильно помню,  при сериалайзе

сессия 1 select
сессия 2 select
сессия 1 update - встает потому что сессия 2 накинула шаредлок.
сессия 2 update - встает потому что сессия 1 накинула шаредлок.

дедлок.

Добавлено @ 17:11
чота я засомневался что именно так и будтет, но в том что чтения не будут блокировать чтения я еще не усомнился  smile .

Добавлено через 11 минут и 24 секунды
единственное что мне приходит в голову - фиктивный аптдейт с целью блокировки записи.
но я абсолютно не знаком с матчастью и бестпрактис - маськи.

Это сообщение отредактировал(а) Zloxa - 29.12.2010, 17:13


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Akina
Дата 29.12.2010, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(_prishelec_ @  29.12.2010,  17:56 Найти цитируемый пост)

SELECT ... users.id INTO domain_id ...
...
IF (domain_id > 0) THEN
  UPDATE domains SET domen_lock = '1' WHERE id = domain_id;
END IF;

Я так понимаю, что domain_id > 0 - это проверка, найдена запись или нет, верно? тогда почему бы не
Код

UPDATE domains 
SET domen_lock = '1' 
WHERE id = (SELECT users.id ... );

?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
_prishelec_
Дата 29.12.2010, 22:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 24.11.2007

Репутация: нет
Всего: нет



Цитата(Akina @ 29.12.2010,  17:41)
Цитата(_prishelec_ @  29.12.2010,  17:56 Найти цитируемый пост)

SELECT ... users.id INTO domain_id ...
...
IF (domain_id > 0) THEN
  UPDATE domains SET domen_lock = '1' WHERE id = domain_id;
END IF;

Я так понимаю, что domain_id > 0 - это проверка, найдена запись или нет, верно? тогда почему бы не
Код

UPDATE domains 
SET domen_lock = '1' 
WHERE id = (SELECT users.id ... );

?

Мне тогда придется два раза использовать сложные запросы.
domain_id > 0 - это проверка, найдена запись или нет Да, верно.
У меня так раньше и было.

Добавлено через 37 секунд
Цитата(Zloxa @ 29.12.2010,  17:09)
Цитата(Akina @ 29.12.2010,  16:15)
Цитата(Zloxa @  29.12.2010,  16:29 Найти цитируемый пост)
при serializable, емнип, на блокировке должен будет встать апдейт а не конкурирующий селект 

в
Код

start transaction;
select ... ;
update ... ;
commit;

?  smile

Да, если я правильно помню,  при сериалайзе

сессия 1 select
сессия 2 select
сессия 1 update - встает потому что сессия 2 накинула шаредлок.
сессия 2 update - встает потому что сессия 1 накинула шаредлок.

дедлок.

Добавлено @ 17:11
чота я засомневался что именно так и будтет, но в том что чтения не будут блокировать чтения я еще не усомнился  smile .

Добавлено @ 17:20
единственное что мне приходит в голову - фиктивный аптдейт с целью блокировки записи.
но я абсолютно не знаком с матчастью и бестпрактис - маськи.

Т.е. у меня вложенный второй select рубит транзакцию?
PM MAIL WWW ICQ Skype   Вверх
Akina
Дата 29.12.2010, 22:34 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(_prishelec_ @  29.12.2010,  23:10 Найти цитируемый пост)
Мне тогда придется два раза использовать сложные запросы.

Гм... это ещё почему? я вижу ОДИН основной апдейт, и внутри него ОДИН вложенный селект... где второй?

PS. Вас не учили цитировать только то, что действительно нужно, а не всё, что сказано?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
_prishelec_
Дата 30.12.2010, 01:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 24.11.2007

Репутация: нет
Всего: нет



Цитата(Akina @ 29.12.2010,  22:34)
Цитата(_prishelec_ @  29.12.2010,  23:10 Найти цитируемый пост)
Мне тогда придется два раза использовать сложные запросы.

Гм... это ещё почему? я вижу ОДИН основной апдейт, и внутри него ОДИН вложенный селект... где второй?

PS. Вас не учили цитировать только то, что действительно нужно, а не всё, что сказано?

Кста не факт, что в процедуре такая фишка прокатит. Но попробую.
У меня в первый селект вложен второй.Но суть чтоб это прокатило в процедуре.

Добавлено @ 01:43
Не пашет, что и следовало ожидать
Код

DELIMITER |
CREATE PROCEDURE select_domain (IN ip VARCHAR(15), OUT domain_id INT, OUT host VARCHAR(150), OUT transfers INT, OUT template_link VARCHAR(50), OUT user_id INT)
BEGIN
    UPDATE domains (SELECT domains.id, domains.host, domains.transfers, parkings.link, users.id INTO domain_id, host, transfers, template_link, 
user_id FROM domains JOIN parkings ON domains.parking_id = parkings.id JOIN users ON domains.user_id = users.id WHERE parkings.state = '1' 
AND domains.state = '1' AND domains.domen_lock = '0' AND domains.clicks < domains.limit_clicks AND users.state = '1' AND users.credits > '0' AND 
domains.id NOT IN (SELECT list_ip_clicks.domain_id FROM list_ip_clicks WHERE list_ip_clicks.ip = ip) ORDER BY RAND() LIMIT 0,1) AS usr SET domen_lock = '1' WHERE id = 1;
END;
|
DELIMITER ;


Это сообщение отредактировал(а) _prishelec_ - 30.12.2010, 01:44
PM MAIL WWW ICQ Skype   Вверх
Akina
Дата 30.12.2010, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(_prishelec_ @  30.12.2010,  02:36 Найти цитируемый пост)
У меня в первый селект вложен второй.Но суть чтоб это прокатило в процедуре.

Пока не вижу оснований для возникновения проблем...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
_prishelec_
Дата 5.1.2011, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 24.11.2007

Репутация: нет
Всего: нет



Цитата(Akina @ 30.12.2010,  09:18)
Цитата(_prishelec_ @  30.12.2010,  02:36 Найти цитируемый пост)
У меня в первый селект вложен второй.Но суть чтоб это прокатило в процедуре.

Пока не вижу оснований для возникновения проблем...

Всех с новым годом!

Это я имел ввиду провотэто:
Да, если я правильно помню,  при сериалайзе

сессия 1 select
сессия 2 select
сессия 1 update - встает потому что сессия 2 накинула шаредлок.
сессия 2 update - встает потому что сессия 1 накинула шаредлок.

Всех с новым годом!

Это я имел ввиду провотэто:
Да, если я правильно помню,  при сериалайзе

PM MAIL WWW ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MySQL | Следующая тема »


 




[ Время генерации скрипта: 0.1004 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.