Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como usar corretamente as transações e bloqueios para garantir a integridade do banco de dados?


Até aí tudo bem, isso pelo menos impedirá que o usuário faça o checkout em várias sessões (várias vezes tentando fazer o checkout do mesmo cartão - bom para lidar com cliques duplos).

Como você verifica? Com um padrão SELECT ou com um SELECT ... FOR UPDATE ? Com base na etapa 5, suponho que você esteja verificando uma coluna reservada no item ou algo semelhante.

O problema aqui é que o SELECT ... FOR UPDATE na etapa 2 NÃO aplicará o FOR UPDATE bloqueio para todo o resto. Ele está se aplicando apenas ao que é SELECT ed:o cart-item tabela. Com base no nome, esse será um registro diferente para cada carrinho/usuário. Isso significa que outras transações NÃO serão impedidas de prosseguir.

Seguindo o acima, com base nas informações que você forneceu, você pode acabar com várias pessoas comprando o mesmo item, se você não estiver usando SELECT ... FOR UPDATE na etapa 3.

Solução sugerida

  1. Iniciar transação
  2. SELECT ... FOR UPDATE o cart-item tabela.

Isso bloqueará a execução de um clique duplo. O que você seleciona aqui deve ser algum tipo de coluna "pedido no carrinho". Se você fizer isso, uma segunda transação irá pausar aqui e esperar que a primeira termine, e então ler o resultado que a primeira salvou no banco de dados.

Certifique-se de encerrar o processo de checkout aqui se o cart-item mesa diz que já foi encomendado.
  1. SELECT ... FOR UPDATE a tabela onde você registra se um item foi reservado.

Isso impedirá que OUTROS carrinhos/usuários possam ler esses itens.

Com base no resultado, se os itens não estiverem reservados, continue:

  1. UPDATE ... a tabela na etapa 3, marcando o item como reservado. Faça qualquer outro INSERT s e UPDATE s que você precisa, também.

  2. Faça o pagamento. Emita uma reversão se o serviço de pagamento disser que o pagamento não funcionou.

  3. Registre o pagamento, se for bem-sucedido.

  4. Confirmar transação

Certifique-se de não fazer nada que possa falhar entre as etapas 5 e 7 (como enviar e-mails), senão você pode acabar com eles fazendo um pagamento sem que ele seja registrado, caso a transação seja revertida.

O passo 3 é o passo importante no que diz respeito a garantir que duas (ou mais) pessoas não tentem pedir o mesmo item. Se duas pessoas tentarem, a segunda pessoa acabará tendo sua página da web "travada" enquanto processa a primeira. Então, quando o primeiro terminar, o 2º lerá a coluna "reservado", e você poderá retornar uma mensagem ao usuário de que alguém já comprou aquele item.

Pagamento na transação ou não


Isso é subjetivo. Geralmente, você deseja fechar as transações o mais rápido possível, para evitar que várias pessoas sejam impedidas de interagir com o banco de dados de uma só vez.

No entanto, neste caso, você realmente quer que eles esperem. É apenas uma questão de quanto tempo.

Se você optar por confirmar a transação antes do pagamento, precisará registrar seu progresso em alguma tabela intermediária, executar o pagamento e registrar o resultado. Esteja ciente de que, se o pagamento falhar, você precisará desfazer manualmente os registros de reserva de itens atualizados.

SELECT ... FOR UPDATE em linhas inexistentes


Apenas uma palavra de aviso, caso o design da sua tabela envolva a inserção de linhas onde você precisa SELECT ... FOR UPDATE :Se uma linha não existir, essa transação NÃO fará com que outras transações esperem, se elas também SELECT ... FOR UPDATE a mesma linha inexistente.

Portanto, certifique-se de sempre serializar suas solicitações fazendo um SELECT ... FOR UPDATE em uma linha que você sabe que existe primeiro. Então você pode SELECT ... FOR UPDATE na linha que pode ou não existir ainda. (Não tente fazer apenas um SELECT na linha que pode ou não existir, pois você estará lendo o estado da linha no momento em que a transação foi iniciada, não no momento em que você executar o SELECT . Então, SELECT ... FOR UPDATE em linhas inexistentes ainda é algo que você precisa fazer para obter as informações mais atualizadas, apenas esteja ciente de que não fará com que outras transações aguardem.)