2010-11-01 15 views
7

Been me gratter la tête sur ce pendant un certain temps ....PDO :: ATTR_AUTOCOMMIT ne tient pas compte INSERT/UPDATE non transactionnel

J'ai un objet AOP avec pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0); que je veux utiliser FOR UPDATE avec quelques tables InnoDB. La lecture de la documentation MySQL, FOR UPDATE ne fera que verrouiller les lignes lues si:

  1. Vous êtes dans une transaction
  2. Vous êtes pas dans une transaction et set autocommit=0 a été émis

Alors, je suis en utilisant ATTR_AUTOCOMMIT pour autoriser l'objet PDO à verrouiller des lignes. Dans les deux cas, les instructions INSERT et UPDATE ne s'appliquent pas. Ces instructions n'ont rien à voir avec FOR UPDATE, elles ne font que parcourir le même objet PDO avec des instructions préparées.

Mon journal MySQL requête ressemble:

xxx Connect [email protected] 
xxx Query  set autocommit=0 
xxx Query  INSERT INTO foo_tbl (bar, baz) VALUES ('hello','world') 
xxx Quit 

PHP/PDO ne se plaint pas, mais la sélection de la table indique que les données n'a pas été écrite.

Les requêtes que j'exécute ont été exécutées des milliers de fois avant; seul le changement ATTR_AUTOCOMMIT a été fait. Supprimer cette option fait que tout fonctionne à nouveau. Les transactions fonctionnent également avec l'option autocommit=0.

Y a-t-il d'autres appels à effectuer sur l'objet PDO (commit() se plaint, à juste titre, qu'il ne s'agit pas d'une transaction) pour que les modifications soient prises en compte? Fondamentalement, je veux un objet PDO simple mais avec l'option de verrouiller les lignes en dehors des transactions pour les tables InnoDB (l'arrière-plan de pourquoi est trop long et ennuyeux pour ici).

Je suis sûr que ce soit quelque chose de stupide je manque grattant la tête

+0

Ne vous inquiétez pas, nous manquons tous des choses parfois! Je sais que cela m'arrive beaucoup plus que ce que je voudrais admettre :-) – Josh

Répondre

6
$db = new PDO('mysql:dbname=test'); 
    $db->setAttribute(PDO::ATTR_AUTOCOMMIT,0); 
    var_dump($db->query('SELECT @@autocommit')->fetchAll()); //OK 
    $db->query("INSERT INTO foo (bar) VALUES ('a');"); 
    $db->query("COMMIT;");//do by SQL rather then by interface/PDO-method 

Mais essentiellement, vous êtes dans une transaction (vous avez tout simplement pas commencé avec AOP), un rollback etc. est également toujours disponible. Il est assez discutable s'il s'agit d'un bug (ne pas être en mesure d'appeler commit() directement).

+0

+1 - Je dirais que c'est un bug ... mais bon, il y a des priorités plus élevées quand on parle d'API PHP borked: P Bonne réponse. –

+0

Ce n'est pas un bogue, c'est juste un nom trompeur car beaucoup de gens lient le mot "commit" aux transactions. Cela ne signifie pas que vos transactions en attente sont automatiquement validées ou non, cela signifie simplement que vos requêtes qui n'ont pas été lancées par des transactions sont automatiquement "validées" ou non. Par défaut, elles sont techniquement activées. . –