2010-06-24 27 views
14

Para divertirme, estoy reemplazando la extensión mysqli en mi aplicación con PDO.PDO, mysql, transacciones y bloqueo de tabla

De vez en cuando necesito usar transacciones + bloqueo de tablas.

En estas situaciones, de acuerdo con el manual de mysql, la sintaxis debe ser un poco diferente. En lugar de llamar START TRANSACTION, lo haces así ...

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)

Mi pregunta es, ¿cómo interactuar con este PDO :: beginTransaction? ¿Puedo usar PDO :: beginTransaction en este caso? O debería enviar manualmente el sql "SET autocommit = 0; ... etc".

Gracias por el consejo,

Respuesta

4

En MySQL, a partir de una transacción es diferente a la de apagar confirmación automática, debido a cómo funciona TABLAS bloquear/desbloquear. En MySQL, LOCK TABLES confirma cualquier transacción abierta, pero desactivar el autocommit no es iniciar una transacción. MySQL es divertido de esa manera.

En PDO, iniciar una transacción con beginTransaction no inicia una nueva transacción, simplemente desactiva el compromiso automático. En la mayoría de las bases de datos, esto es sensato, pero puede tener efectos secundarios con el comportamiento mencionado de MySQL.

Probablemente no deba confiar en este comportamiento y en cómo interactúa con las peculiaridades de MySQL. Si va a tratar el comportamiento de MySQL para el bloqueo de tablas y DDL, debe evitarlo. Si quiere el autocommitido apagado, apáguelo a mano. Si desea abrir una transacción, abra una transacción a mano.

Puede mezclar libremente los métodos de la API de PDO para trabajar con transacciones y comandos SQL cuando no esté trabajando con las rarezas de MySQL.

+0

"Comenzar una transacción es diferente que desactivar el compromiso automático" No con PDO no está 't. Cuando llama [PDO :: beginTransaction()] (http://php.net/manual/en/pdo.begintransaction.php), desactiva la confirmación automática. – Olhovsky

+0

Buen punto, he actualizado mi respuesta en consecuencia. Espero ansiosamente el día en que MySQL gane un buen DDL y bloquee el comportamiento dentro de las transacciones ... Bueno, tal vez no. Hice el cambio a Postgres hace un tiempo. – Charles

+0

¿Podría comprobar este hilo? https://stackoverflow.com/questions/47810114/php-pdo-mysql-and-how-does-it-really-deal-with-mysql-transactions Todavía no puedo entender la diferencia entre usar 'PDO :: beginTransaction() 'con y sin' $ this-> pdo-> setAttribute (PDO :: ATTR_AUTOCOMMIT, 0); '. ¿Podrias ayudarme por favor? ¡Muchas gracias! – tonix

9

Cuando llama al PDO::beginTransaction(), desactiva la confirmación automática.

Así que usted puede hacer:

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

Después de un modo commit() o rollback(), la base de datos estará de vuelta automático comprometerse.

+2

Esto no ha sido mi experiencia (usando mysql 5.6.27 con tablas InnoDB), el comando 'LOCK TABLES' básicamente confirma la transacción iniciada previamente, y todos los comandos subsecuentes son individualmente comprometidos (es decir, sin comportamiento de transacción) – mils

3

He pasado una gran cantidad de tiempo corriendo alrededor de este problema, y ​​la documentación de PHP en esta área es vaga en el mejor de los casos. Unas pocas cosas que he encontrado, corriendo PHP 7 con una tabla de MySQL InnoDB:

PDO :: beginTransaction no sólo tiene que desactivar la confirmación automática, después de haber probado la respuesta proporcionada por Olhovsky con código que falla, reversiones no funcionan ; no hay comportamiento transaccional Esto significa que no puede ser así de simple.

partir de una transacción puede ser el bloqueo de las tablas utilizadas ... Espero con impaciencia a que alguien me diga que estoy equivocado con esto, pero aquí están las razones podría ser: This comment, que muestra una tabla siendo inaccesibles cuando una transacción ha comenzado, sin estar bloqueada. This PHP documentation page, que se desliza en el extremo:

...mientras la transacción está activa, se le garantiza que nadie más puede hacer cambios mientras se encuentra en el centro de su trabajo

Para mí este comportamiento es bastante inteligente, y también proporciona suficiente margen de maniobra para la DOP para hacer frente a cada base de datos, que es, después de todo, el objetivo. Sin embargo, si esto es lo que está sucediendo, está muy poco documentado y debería haber sido llamado de otra forma para evitar confusiones con una transacción de base de datos verdadera, lo que no implica un bloqueo.

La respuesta de Charles, creo que es probablemente la mejor si se tiene certeza con una carga de trabajo que requerirá una alta concurrencia; hágalo a mano usando consultas explícitas a la base de datos, luego puede ir por la documentación de la base de datos.

actualización he tenido un servidor de producción en funcionamiento el uso de las funciones de transacción DOP desde hace un tiempo, recientemente utilizando la base de datos de AWS Aurora (totalmente compatible con MySQL, pero construido a escala automática, etc.). He probado estos dos puntos para mí:

  • Las transacciones (puramente la capacidad de confirmar todos los cambios de la base de datos juntas) funcionan usando PDO :: beginTransaction(). En resumen, sé que muchos scripts han fallado a la mitad de su selección de base de datos/actualizaciones y se ha mantenido la integridad de los datos.
  • Bloqueo de tabla no está sucediendo, he tenido un error de duplicación de índice para probar esto.

Por lo tanto, para ampliar mi conclusión, parece que el comportamiento de estas funciones parece cambiar en función del motor de la base de datos (y posiblemente de otros factores). Por lo que puedo decir tanto de la experiencia como de la documentación, no hay manera de saber qué está pasando programáticamente ... whoop ...