Атомный счетчик с MySql - PullRequest
0 голосов
/ 16 мая 2019

В MySql 8.0 я работаю с «атомным счетчиком» (в хранимой процедуре) и этот простой обходной путь (я не могу использовать транзакции) прекрасно работает для моей цели:

CREATE PROCEDURE xxx...
   ...
   UPDATE cnt SET value = (@val := value + 1) where id = 1;
   ...

но когда я компилирую процедуру, я получаю это предупреждение

Setting user variables within expressions is deprecated and will be removed in a future release. ...

Как мне избежать предупреждения? (Я не могу найти "новый" синтаксис)

Ответы [ 2 ]

1 голос
/ 16 мая 2019

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

repeat 
  select value + 1 into @value from cnt where id = 1;
  update cnt set value = @value where id = 1 and value = @value - 1;
until (select row_count()) > 0 end repeat;

На самом деле это не атомарный (так как другой сеанс может увеличить счетчик между select и update), но он будет обновляться только в том случае, если этого не произошло, в противном случае он будет повторяться (потенциально бесконечно, если у вас действительно очень занятый счетчик).row_count() используется для проверки того, произошло ли это обновление.

Для этой устаревшей функции "новый синтаксис" отсутствует - намеренно больше не будет возможности делать это в MySQL9 (таким образом, предупреждение), см. журнал изменений .Основным вариантом использования для установки пользовательских переменных в выражениях было моделирование CTE (например, рекурсивный иерархический запрос или rank() оконная функция ) и с поддержкой CTE в MySQL 8 , можно было отказаться от этой функциональности.

Для контекста, предполагаемое поведение вашего синтаксиса - заставить

UPDATE cnt SET value = value + 1 where id = 1; 
SELECT value INTO @val from cnt where id = 1; 

вести себя атомарно.

Очевидно, что ожидаемый способ добиться этого - использовать транзакцию, поэтому не будет нового синтаксиса для замены вашего поведения, как это требовалось для CTE;однако вы можете проверить, не была ли причина, по которой вы не можете использовать транзакцию, в более новой версии MySQL (с потенциально новыми возможностями).

0 голосов
/ 16 мая 2019

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

   START TRANSACTION;
   UPDATE cnt SET value = value + 1 where id = 1;
   SELECT value INTO @val FROM cnt WHERE id =1;
   COMMIT;

Это не приведет к риску состояния гонки, если вы начнете транзакцию до UPDATE и выполните SELECT в том же самомсделка.Блокировка, полученная с помощью UPDATE, не позволит другому параллельному сеансу обновить ту же строку, прежде чем вы сможете выбрать значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...