Реклама на сайте Advertise with us

InnoDB. блокировка строки на чтение

Расширенный поиск по форуму
 
Новая тема Новая тема   
Автор
Поиск в теме:

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 31/03/11 в 19:29       Ответить с цитатойцитата 

Товарищи как строку на чтение заблокировать? Скрипт выбирает строку из базы. ее локает. потом разлокает.

типа:
select * from table where id=1
далее лок (чтобы второй такой же скрипт не смог прочитать эту строку).
далее разлок.

как быть?

Нашел такое:
Создать БД "TEST"
mysql -u root
use TEST;
CREATE TABLE t (a INT KEY) ENGINE = InnoDB;
INSERT INTO t VALUES (1), (2);

1. клиент
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
SELECT * FROM t WHERE a=1 FOR UPDATE;
+---+
| a |
+---+
| 1 |
+---+
1 row in set (0.00 sec)


2. клиент
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
SELECT * FROM t WHERE a=1 FOR UPDATE;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

Ну и пока в первом клиенте "COMMIT;" не сделать, то второй клиент не может прочитать строку.

Усложним запрос. Выборка рандомно одного из значений(в обоих клиентах):
SELECT * FROM t ORDER BY RAND() LIMIT 1 FOR UPDATE;
По идее одно из значений выбирается, второе значение по идее должно выбираться во втором клиенте. но результат тот же.

Или я не тем путем иду?

пришел к победе коммунистического труда

0
 

programmer

С нами с 08.12.02
Сообщения: 7607
Рейтинг: 5752

Ссылка на сообщениеДобавлено: 31/03/11 в 21:00       Ответить с цитатойцитата 

а вот если гипотетически скрипт в процессе прервет выполнение. строка так и останется локнутой?

крипта на ByBit

5
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 31/03/11 в 21:32       Ответить с цитатойцитата 

разлочит

пришел к победе коммунистического труда

0
 

www.phpdevs.com

С нами с 24.10.02
Сообщения: 16633
Рейтинг: 16105


Передовик Master-X (01.09.2005) Передовик Master-X (16.09.2005) Передовик Master-X (01.10.2005) Передовик Master-X (16.08.2006) Передовик Master-X (16.10.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 31/03/11 в 21:40       Ответить с цитатойцитата 

http://dev.mysql.com/doc/refman/5.0/en/innodb-lock-modes.html
оно ?
Или чего ты хочешь добиться в результате ? При старте транзакции данные лочатся вроде сами по умолчанию.

Пишу на php/mysql/django за вменяемые деньги.
Обращаться в личку.

5
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 31/03/11 в 21:58       Ответить с цитатойцитата 

ну хочу выбрать селектом строку. ее залочить. чтобы другой экземпляр скрипта эту же строку не выбрал.

крон:
*/5 * * * * php script1.php
*/5 * * * * php script2.php

база:
10 строк в таблице

script1.php:
берет рандомно одну строку.
лочит.
с ней работает.
разлочивает.

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

за линк спасибо. курю

пришел к победе коммунистического труда

0
 



С нами с 20.02.06
Сообщения: 248
Рейтинг: 366

Ссылка на сообщениеДобавлено: 31/03/11 в 23:42       Ответить с цитатойцитата 

Так а при чём тут это? Лок строки не помешает второму клиенту выбрать ту же самую строку, он просто будет ждать освобождения лока. Тут надо действовать по-другому. Например, в каком-нибудь файле или даже в бд записать id выбранной первым скриптом строки, а во втором сделать условие (SELECT ... WHERE id != ид_выбранное_первым_скриптом). Как-то так, если я правильно понял задачу

5
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 01/04/11 в 11:31       Ответить с цитатойцитата 

CABMIT писал:
Тут надо действовать по-другому. Например, в каком-нибудь файле или даже в бд записать id выбранной первым скриптом строки, а во втором сделать условие (SELECT ... WHERE id != ид_выбранное_первым_скриптом). Как-то так, если я правильно понял задачу

ну это самый простой вариант. добавить в таблицу поле
`lock` ENUM('0','1') NOT NULL DEFAULT '0' COMMENT '1-лок, 0-разлок'
и при выборке строки - сразу эту же строку апдейтить и ставить lock=1. а потом снова апдейтить и снимать. Хотел на базу повесить геморой этот. Но видимо не получиться.

Для варианта:
1. клиент
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT a FROM t WHERE a=1 FOR UPDATE;

2. клиент
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT a FROM t WHERE a=2 FOR UPDATE;

все прекрасно работает. второй клиент не прочитает строку a=1.

Но, уже для такого запроса:
SELECT a FROM t ORDER BY RAND() LIMIT 1 FOR UPDATE;
уже не работает.

И даже для такого:
SELECT * FROM t WHERE a=(SELECT a FROM t ORDER BY RAND() LIMIT 1) FOR UPDATE;

Т.е. надо рандомно выбрать 1 строку. и ее локнуть. Видимо внутреннее устройство таково что сначала выбираются все строки, а потом из них выбирается одна. Последним селектом вот я одну строку выбрал. и локнулись все сразу
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

пришел к победе коммунистического труда

0
 

programmer

С нами с 08.12.02
Сообщения: 7607
Рейтинг: 5752

Ссылка на сообщениеДобавлено: 01/04/11 в 12:28       Ответить с цитатойцитата 

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

крипта на ByBit

5
 



С нами с 05.04.07
Сообщения: 1661
Рейтинг: 1090


Передовик Master-X (01.04.2011)
Ссылка на сообщениеДобавлено: 01/04/11 в 12:53       Ответить с цитатойцитата 

а так не пройдёт чтоли?
Код:
SELECT * FROM t WHERE id=(SELECT id FROM t WHERE lockFiled=0 ORDER BY RAND() LIMIT 1) FOR UPDATE;

True хостинг

5
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 01/04/11 в 22:20       Ответить с цитатойцитата 

taj: да это понятно. с локом то. Запрос
SELECT * FROM t WHERE a=(SELECT a FROM t ORDER BY RAND() LIMIT 1) FOR UPDATE;
это типа: сначала делаю нужный мне рандомный простой селект одной строки, потом ее конкретно выбираю селектом уже с локом. но не прокатило.

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

пришел к победе коммунистического труда

0
 
Новая тема Новая тема   

Текстовая реклама в форме ответа
Заголовок и до четырех строчек текста
Длина текста до 350 символов
Купить рекламу в этом месте!


Перейти:  



Спонсор раздела Стань спонсором этого раздела!

Реклама на сайте Advertise with us

Опросы

Рецепт новогоднего блюда 2022



Обсудите на форуме обсудить (11)
все опросы »