ВЫБРАТЬ ... ДЛЯ ОБНОВЛЕНИЯ и МАКС. () - PullRequest
4 голосов
/ 06 июля 2011

Do SELECT ... FOR UPDATE в этом запросе блокирует строки в этой таблице?

Таблица находится в InnoDB, а запрос находится внутри транзакции

select max(id) from table1 FOR UPDATE

У меня есть этот код, и кажется, SELECT ... FOR UPDATE не блокирует строки.

Ответы [ 5 ]

2 голосов
/ 06 июля 2011

SELECT ... FOR UPDATE блокирует выполнение других сеансов SELECT ... LOCK IN SHARE MODE

Используйте вместо SELECT ... LOCK IN SHARE MODE который

устанавливает блокировку общего режима для строк читать. Блокировка общего режима позволяет другим сеансы читать строки, но не изменить их. Прочитанные строки являются последний доступный, так что если они принадлежат еще одна транзакция, которая еще не совершено, чтение блоков до этого транзакция заканчивается.

См. В документах .

1 голос
/ 24 апреля 2019

Я тоже наткнулся на это и проверил этот случай.

CREATE TABLE `test1` (
  `user_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `ds_id` mediumint(8) unsigned NOT NULL,
  `producer_id` mediumint(8) unsigned NOT NULL DEFAULT 0,
  PRIMARY KEY (`user_id`,`ds_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `test1` VALUES
(3, 4, 2),
(17, 1, 1),
(18, 1, 9);

Тема 1:

begin;
select max(ds_id) from test1 where user_id=3 for update;
+------------+
| max(ds_id) |
+------------+
|          3 |
+------------+

Тема 2:

begin;
select max(ds_id) from test1 where user_id=3 for update;
... waiting ...

Тема 1:

insert into test1 set user_id=3, ds_id=4, producer_id=1;
commit;

Поток 2:

+------------+
| max(ds_id) |
+------------+
|          3 |
+------------+

Похоже, InnoDB не блокирует пробел при использовании групповой функции, а только блокирует существующие записи.Без групповой функции поток 2 возвращает 2 строки, включая новую, как и ожидалось.

1 голос
/ 06 июля 2011

возможно, это будет работать?:

select id from table where id IN (select max(id) from table1) FOR UPDATE
0 голосов
/ 26 июля 2016

SELECT MAX(id) FROM table1 FOR UPDATE - не блокирует строки, так как фактически не сканирует строки.Необходимая информация извлекается из индекса таблицы.

Это подсказка, если вы добавляете к запросу DESCRIBE, отображая:

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
'1', 'SIMPLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'Select tables optimized away'

SELECT id FROM table1 WHERE id = (SELECT MAX(id) FROM table1) FOR UPDATE - заблокирует одна строка , которая соответствует MAX(id), поскольку вы явно извлекаете эту строку.

SELECT id FROM table1 ORDER BY id DESC LIMIT 1 FOR UPDATE - заблокирует все строки и получит MAX(id), используя комбинацию ORDER BYи LIMIT 1.

Это снова будет объяснено запросом DESCRIBE.

0 голосов
/ 06 августа 2015

Как в документации Oracle Этот пункт подлежит следующим ограничениям: Вы не можете указать это предложение со следующими другими конструкциями: оператор DISTINCT, выражение CURSOR, операторы set, group_by_clause или агрегатные функции.

...