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

MySQL:transações vs tabelas de bloqueio


Bloquear tabelas impede que outros usuários de banco de dados afetem as linhas/tabelas que você bloqueou. Mas os bloqueios, por si só, NÃO garantirão que sua lógica saia em um estado consistente.

Pense em um sistema bancário. Quando você paga uma conta online, há pelo menos duas contas afetadas pela transação:Sua conta, da qual o dinheiro é retirado. E a conta do destinatário, para a qual o dinheiro é transferido. E a conta do banco, na qual eles depositarão alegremente todas as taxas de serviço cobradas na transação. Dado (como todos sabem hoje em dia) que os bancos são extraordinariamente estúpidos, digamos que o sistema deles funcione assim:
$balance = "GET BALANCE FROM your ACCOUNT";
if ($balance < $amount_being_paid) {
    charge_huge_overdraft_fees();
}
$balance = $balance - $amount_being paid;
UPDATE your ACCOUNT SET BALANCE = $balance;

$balance = "GET BALANCE FROM receiver ACCOUNT"
charge_insane_transaction_fee();
$balance = $balance + $amount_being_paid
UPDATE receiver ACCOUNT SET BALANCE = $balance

Agora, sem bloqueios e sem transações, esse sistema está vulnerável a várias condições de corrida, sendo a maior delas vários pagamentos realizados em sua conta ou na conta do destinatário em paralelo. Embora seu código tenha seu saldo recuperado e esteja fazendo o enorme_overdraft_fees() e outros enfeites, é totalmente possível que algum outro pagamento esteja executando o mesmo tipo de código em paralelo. Eles vão recuperar seu saldo (digamos, $ 100), fazer suas transações (tirar os $ 20 que você está pagando e os $ 30 com os quais eles estão atrapalhando você), e agora ambos os caminhos de código têm dois saldos diferentes:$ 80 e $ 70. Dependendo de quais terminarem por último, você terminará com um desses dois saldos em sua conta, em vez dos US$ 50 que deveria ter (US$ 100 - US$ 20 - US$ 30). Neste caso, "erro bancário a seu favor".

Agora, digamos que você use fechaduras. O pagamento da sua conta (US$ 20) chega primeiro, então vence e bloqueia o registro da sua conta. Agora você tem uso exclusivo, e pode deduzir os $20 do saldo, e devolver o novo saldo em paz... e sua conta acaba com $80 como esperado. Mas... uhoh... Você tenta atualizar a conta do destinatário, e ela está bloqueada, e bloqueada por mais tempo do que o código permite, expirando sua transação... Estamos lidando com bancos estúpidos, então em vez de ter o erro adequado manipulação, o código apenas puxa um exit() , e seus $ 20 desaparecem em uma nuvem de elétrons. Agora você está sem $ 20, e você ainda deve $ 20 ao receptor, e seu telefone é recuperado.

Então... insira as transações. Você inicia uma transação, debita $ 20 em sua conta, tenta creditar o destinatário com $ 20... e algo explode novamente. Mas desta vez, em vez de exit() , o código pode apenas fazer rollback , e puf, seus $ 20 são magicamente adicionados de volta à sua conta.

No final, resume-se a isto:

Os bloqueios impedem que qualquer outra pessoa interfira nos registros do banco de dados com os quais você está lidando. As transações evitam que erros "depois" interfiram com coisas "anteriores" que você fez. Nenhum dos dois sozinho pode garantir que as coisas funcionem bem no final. Mas juntos, eles fazem.

na lição de amanhã:A Alegria dos Impasses.