Блокировки. Классика.

Sync

Новичок
Блокировки. Классика.

Задача.
Есть таблица InnoDB с полем last_id.
Клиенты считывают значение, используют его в своих целях, инкрементируют его и обновляют поле.
Проблема заключается в дублировании этого значения, что нежелаемо.
То есть клиент1 взял 1. Поиграл с ним записал 2.
В это же время клиент2 взял 1 (хотя должен был подождать и взять 2).

Читал про select ... for update, select ... lock in share mode.
Насколько я понял это мне не поможет. Мне надо поставить блокировку на чтение. То есть не LOCK READ, а так чтобы другие клиенты даже читать не могли пока первый не изменит значение.
Каким инструментов стоит пользоватся в данном случае?

И каким образом в InnoDB можно выполнить блокировку на уровне строки?

Спасибо.
 

Sync

Новичок
client 1
start transaction;

client 2
select id from test; // дает 3, то есть он уже его взял! что не подходит. то есть как на этом этапе запретить чтение этой строки?

client 1
select id from test;
update test set id=4;

client 2
select id from test; // ну да, 3 как и ожидалось, коммита не было

client 1
commit;

client 2
select id from test; // 4, ура

-~{}~ 09.06.09 20:40:

пока что добился следующего:


LOCK TABLES test WRITE;
SELECT id FROM test LOCK IN SHARE MODE;
UPDATE test SET id=10
UNLOCK TABLES;

Но вот не хочеться блокировать таблицу целиком :(

И какие грабли у такого подхода?

Да, mysql 5.1.34
 

Sync

Новичок
korchasa
Добавить поле read_lock и анализировать его значение?
Не та ситуация. Ну прочитает клиент read_lock=1 и что сделает дальше? while(true) делать? :)

Я может не разобрался до конца, но этот построчный лок (FOR UPDATE) не блокирует чтение.
А мне именно надо его заблокировать.

Грубо говоря есть блок операций, вначале которого надо заблокировать строку (таблицу) на чтение, в конце - разблокировать.

Решение которое я написал выше работает хорошо. Но блокируется таблица.
 

Gas

может по одной?
но этот построчный лок (FOR UPDATE) не блокирует чтение
не знаю как ты пробовал, но я хоть и был уверен что блокирует, взял и проверил из 2-х консольных клиентов - отлично всё работает, пока транзакция с for update не будет закомичена, вторая (начтение) висит и ждёт снятия лока.
Твой вариант я понял, но LOCK TABLES это уж слишком, когда есть другие инструменты.
for update как раз для твоего случая и был придуман.

p.s. может ты просто не заметил эту приписку в мане:
Locking of rows for update using SELECT FOR UPDATE only applies when autocommit is disabled (either by beginning transaction with START TRANSACTION or by setting autocommit to 0. If autocommit is enabled, the rows matching the specification are not locked.
?
 
Сверху