InnoDB работает автоматически:
В InnoDB вам вообще не нужно ничего блокировать, поскольку MySQL работает на уровне изоляции транзакции REPEATABLE READ.Когда вы начинаете транзакцию, а затем ВЫБИРАЕТЕ что-то, при первом запуске ВЫБРАТЬ транзакция запускается, и так как это ПОВТОРЯЕМОЕ ЧТЕНИЕ, ваше представление данных будет согласованным и неизменным до тех пор, пока вы не ПРИМИТЕ.
Это означает, что НАЧАТЬ,SELECT, SELECT, COMMIT в InnoDB REPEATABLE READ отличается от SELECT, SELECT.
MyISAM - это блокировки таблиц:
В MyISAM вы бы LOCK TABLES a, b, c READ, d WRITE
установили блокировки чтения для таблиц, которые вы используете.блокирует чтение и чтение / запись таблиц, в которые вы пишете.Невозможно построить список блокировок постепенно с помощью LOCK TABLES, поэтому вы должны заблокировать все, к чему вы хотите прикоснуться, за один раз, и вы не можете касаться чего-либо, что не заблокировали, пока вы UNLOCK TABLES
.LOCK TABLES требует дополнительной привилегии, и не имеет смысла предоставлять SELECT priv без LOCK priv в MyISAM.
Универсальная оптимистическая блокировка:
В MyISAM и в InnoDB без транзакций операторы выполняютсяатомарно.Этого достаточно для реализации оптимистической блокировки.При оптимистической блокировке предположим, что у вас есть строка с первичным ключом и данными.Добавьте к нему столбцы state
и owner
.
root@localhost [kris]> create table d ( id serial, d varchar(20), state enum('unclaimed', 'claimed', 'done') not null, owner integer unsigned not null);
Query OK, 0 rows affected (0.51 sec)
root@localhost [kris]> insert into d values (1, 'one', 'unclaimed', 0), (2, 'two','unclaimed', 0);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
root@localhost [kris]> select * from d;
+----+------+-----------+-------+
| id | d | state | owner |
+----+------+-----------+-------+
| 1 | one | unclaimed | 0 |
| 2 | two | unclaimed | 0 |
+----+------+-----------+-------+
2 rows in set (0.00 sec)
Теперь вы можете запросить одну или несколько строк для вашего процессора:
root@localhost [kris]> update d
set owner = 1, state = 'claimed'
where
state = 'unclaimed'
order by id limit 1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Предупреждение утверждает, что этот оператор являетсяне безопасно для репликации, но ORDER BY
должно сделать LIMIT
безопасным для репликации.В результате мы запросили одну строку для владельца с идентификатором владельца 1. Это безопасно при параллельном доступе, потому что UPDATE выполняется атомарно:
root@localhost [kris]> select * from d;
+----+------+-----------+-------+
| id | d | state | owner |
+----+------+-----------+-------+
| 1 | one | claimed | 1 |
| 2 | two | unclaimed | 0 |
+----+------+-----------+-------+
2 rows in set (0.00 sec)
Нам нужно выбрать то, что мы в данный моментработаем над ним и обрабатываем его:
root@localhost [kris]> select id, d from d where state = 'claimed' and owner = 1;
+----+------+
| id | d |
+----+------+
| 1 | one |
+----+------+
1 row in set (0.00 sec)
Нам также нужно сделать это, когда мы закончим:
root@localhost [kris]> update d set state = 'done', owner = 0 where id = 1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0