PDO, mysql, transactions e bloqueio de mesa

Por diversão, estou substituindo a extensão mysqli no meu aplicativo por DOP.

De vez em quando eu preciso usar transactions + bloqueio de mesa.

Nessas situações, de acordo com o manual mysql, a syntax precisa ser um pouco diferente. Em vez de chamar START TRANSACTION, você faz isso assim …

SET autocommit=0; LOCK TABLES t1 WRITE, t2 READ, ...; ... do something with tables t1 and t2 here ... COMMIT; UNLOCK TABLES; 

( http://dev.mysql.com/doc/refman/5.0/en/lock-tables-and-transactions.html )

Minha pergunta é, como isso interage com o PDO :: beginTransaction? Posso usar PDO :: beginTransaction neste caso? Ou devo enviar manualmente o sql “SET autocommit = 0; … etc”.

Obrigado pelo conselho,

No MySQL, iniciar uma transação é diferente de desligar o autocommit, devido a como o LOCK / UNLOCK TABLES funciona. No MySQL, LOCK TABLES cometeu quaisquer transactions abertas, mas desativar o autocommit não está realmente iniciando uma transação. O MySQL é engraçado dessa maneira.

Na PDO, iniciar uma transação usando beginTransaction na verdade não inicia uma nova transação, ele simplesmente desliga o autocommit. Na maioria dos bancos de dados, isso é sano, mas pode ter efeitos colaterais com o comportamento mencionado pelo MySQL.

Você provavelmente não deve confiar neste comportamento e como ele interage com as peculiaridades do MySQL. Se você estiver lidando com o comportamento do MySQL para bloqueio de mesa e DDL, você deve evitá-lo. Se desejar que o autocommit, desligue-o manualmente. Se você deseja abrir uma transação, abra uma transação à mão.

Você pode misturar livremente os methods da API PDO para trabalhar com transactions e comandos SQL quando não estiver trabalhando com as curiosidades do MySQL.

Quando você liga para PDO :: beginTransaction () , ele desativa a confirmação automática.

Então você pode fazer:

 $db->beginTransaction(); $db->exec('LOCK TABLES t1, t2, ...'); # do something with tables $db->commit(); $db->exec('UNLOCK TABLES'); 

Após um commit () ou rollBack (), o database voltará no modo de confirmação automática.

Passei uma grande quantidade de tempo correndo em torno desta questão, e a documentação do PHP nesta área é vaga, na melhor das hipóteses. Algumas coisas que encontrei, executando o PHP 7 com uma tabela MySQL InnoDB:

PDO :: beginTransaction não apenas desliga o autocommit , tendo testado a resposta fornecida por Olhovsky com código que falha, as reversões não funcionam; não há comportamento transacional. Isso significa que não pode ser tão simples.

Começando, uma transação pode bloquear as tabelas usadas … Espero ansiosamente por alguém que me diga que eu estou errado com isso, mas aqui estão os motivos que podem ser: Esse comentário , que mostra uma tabela inacessível quando uma transação começou , sem ser trancado. Esta página de documentação PHP , que se desliza no final:

… enquanto a transação está ativa, você está garantido que ninguém mais pode fazer alterações enquanto estiver no meio do seu trabalho

Para mim, esse comportamento é bastante inteligente, e também fornece espaço suficiente para a DOP para lidar com cada database, o que é depois de todo o objective. Se isso é o que está acontecendo, é apenas massivamente documentado e deveria ter sido chamado outra coisa para evitar confusões com uma transação de database verdadeira, o que não implica bloqueio.

A resposta de Charles acho que é provavelmente o melhor se você tiver certeza de uma carga de trabalho que exigirá alta concorrência; faça-o manualmente usando consultas explícitas no database, então você pode passar pela documentação do database.

Atualização Eu tive um servidor de produção funcionando usando as funções de transação do PDO por um tempo agora, usando recentemente o database Aurora da AWS (totalmente compatível com o MySQL, mas construído para escala automática etc.). Tenho provado estes dois pontos para mim:

  • As transactions (puramente habilidade para confirmar todas as mudanças de database em conjunto) funcionam usando o PDO :: beginTransaction (). Em suma, eu sei que muitos scripts falharam a meio caminho do database selecionado / atualizações e a integridade dos dados foi mantida.
  • Bloqueio de tabela não está acontecendo, eu tive um erro de duplicação de índice para provar isso.

Então, para continuar minha conclusão, parece que o comportamento dessas funções parece mudar com base no mecanismo de database (e possivelmente em outros fatores). Tanto quanto eu posso dizer tanto pela experiência quanto pela documentação, não há como saber de forma programática o que está acontecendo … whoop …

    Intereting Posts