Em uma tabela onde cada linha possui um contador (apenas um valor inteiro), preciso pegar o valor atual e aumentá-lo ao mesmo tempo .
Efetivamente, eu quero fazer isso:
SELECT counter FROM table WHERE id=123
UPDATE table SET counter=counter+1 WHERE id=123
Mas fazer isso como duas consultas obviamente não é seguro para threads: vários processos fazendo a mesma coisa (na mesma linha) podem obter o mesmo valor de contador. Preciso que todos sejam únicos, para que cada processo obtenha o valor atual real e o aumente em um.
Posso pensar em uma construção onde implemento um bloqueio manual por linha, mas gostaria de saber se existe uma maneira mais fácil de fazer isso?
As instruções de atualização funcionam perfeitamente sem o select antes! Como instruções únicas são seguras por definição, mesmo duas consultas UPDATE executadas ao mesmo tempo resultarão na linha incrementada duas vezes.
Se você realmente deseja selecionar o valor para seu script PHP, fazer algo com ele e depois atualizar esse valor exato do contador, você pode fazer o seguinte:
Isso inicia uma nova transação, seleciona as linhas que deseja atualizar e as bloqueia exclusivamente. Você pode atualizá-los com segurança sem se preocupar com outros clientes alterando seu conteúdo ou até mesmo acessando as linhas bloqueadas. Finalmente, você precisa confirmar suas alterações.
Você também deve ler algo sobre níveis de isolamento . Você provavelmente não deseja um valor como
READ UNCOMMITTED
nível de isolamento. Todo o resto deve estar bem para este caso de uso.