“FOR UPDATE” v / s “LOCK IN SHARE MODE”: permite que os threads simultâneos leiam o valor atualizado do estado da linha bloqueada

Tenho o seguinte cenário:

usuário X faz login no aplicativo a partir do local lc1: chame-o Ulc1Usuário X (foi hackeado, ou algum amigo dele conhece sua credencial de logon, ou ele apenas efetua login a partir de um navegador diferente em sua máquina, etc. isto Ulc2

Estou usando um servlet principal que:
- obtém uma conexão do pool de banco de dados
- define a confirmação automática como false
- executa um comando que passa pelas camadas do aplicativo: se tudo tiver êxito, defina a confirmação automática como true em uma declaração "finalmente" e feche a conexão. Caso contrário, se uma exceção acontecer, rollback ().

No meu banco de dados (mysql / innoDb), tenho uma tabela "history", com colunas de linha:
id (chave primária) | nome de usuário | data | tópico | bloqueado

A coluna "bloqueado" tem por padrão o valor "falso" e serve como um sinalizador que marca se uma linha específica está bloqueada ou nã
ada linha é específica para um usuário (como você pode ver na coluna do nome de usuári

Volte ao cenário:
-> Ulc1 envia o comando paraatualiza sua história do banco de dados para a data "D" e o tópico "T"

-> Ulc2 envia omesm comando paraatualiza histórico do banco de dados para omesm data "D" emesm tópico "T" no exatamente no mesmo horári

Quero implementar um sistema de bloqueio mysql / innoDB que permita que qualquer thread que chegue faça a seguinte verificação:

coluna "bloqueada" para esta linha é verdadeira ou não?

se verdadeiro, retorne uma mensagem ao usuário que "ele já está atualizando os mesmos dados de outro local"se não for verdadeiro (isto é, não bloqueado): sinalize-o como bloqueado e atualize-o e redefina-o como falso quando termina

Qual dessas duas técnicas de bloqueio do mysql permitirá que o segundo thread de chegada leia o valor "atualizado" da coluna bloqueada para decidir qual ação toma

Devo usar "PARA ATUALIZAÇÃO" ou "BLOQUEAR NO MODO COMPARTILHAR"?

Este cenário explica o que eu quero realizar:
- O segmento Ulc1 chega primeiro: a coluna "bloqueada" é falsa, defina-a como verdadeira e continue atualizando o processo
- O segmento Ulc2 chega enquanto a transação do Ulc1 ainda está em processo e, embora a linha esteja bloqueada pelas funcionalidades do innoDb, ela não precisa esperar, mas na verdade lê o "novo" valor da coluna bloqueada que é "verdadeiro" e portanto, na verdade, não é necessário aguardar até que a transação Ulc1 se comprometa a ler o valor da coluna "bloqueada" (de qualquer maneira, nesse momento, o valor dessa coluna já terá sido redefinido para false

Não tenho muita experiência com os dois tipos de mecanismos de bloqueio, o que entendo até agora é que o LOCK IN SHARE MODE permite que outras transações leiam a linha bloqueada enquanto FOR UPDATE nem sequer permite a leitura. Mas essa leitura obtém o valor atualizado? ou o segundo thread de chegada precisa aguardar o primeiro thread a ser confirmado para depois ler o valor?

Quaisquer recomendações sobre qual mecanismo de bloqueio usar para esse cenário são apreciada
Além disso, se houver uma maneira melhor de "verificar" se a linha foi bloqueada (além de usar um sinalizador de coluna verdadeiro / falso), informe-m
obrigad

SOLUÇÃ
(Exemplo de pseudocódigo Jdbc baseado em@ Darhazer responda

Table: [id (chave primária) | nome de usuário | data | tópico | bloqueado]

connection.setautocommit(false);
//transaction-1
PreparedStatement ps1 = "Select locked from tableName for update where id="key" and   locked=false);
ps1.executeQuery();

//transaction 2
PreparedStatement ps2 = "Update tableName set locked=true where id="key";
ps2.executeUpdate();
connection.setautocommit(true);// here we allow other transactions threads to see the new value

connection.setautocommit(false);
//transaction 3
PreparedStatement ps3 = "Update tableName set aField="Sthg" where id="key" And date="D" and topic="T";
ps3.executeUpdate();

// reset locked to false
 PreparedStatement ps4 = "Update tableName set locked=false where id="key";
ps4.executeUpdate();

//commit
connection.setautocommit(true);

questionAnswers(2)

yourAnswerToTheQuestion