web-dev-qa-db-fra.com

Ces deux requêtes se produiront-elles dans une impasse si elle est exécutée en séquence?

C'est presque certainement la cause de mon autre question , mais je pensais que cela valait la peine de séparer les deux, car j'ai une hypothèse basée sur le journal suivant que j'aimerais avoir falsifié ou vérifié.

Mon hypothèse est que le Autre blocage est le résultat des requêtes suivantes, avec la requête originale cachée en fonction de ma compréhension, le statut InnoDB ne montre que les transactions les plus récentes (est-ce correcte?).

Sur la base du journal, j'ai vérifié notre code et j'ai trouvé les deux requêtes suivantes exécutées en séquence:

db.Execute("UPDATE people SET iphone_device_id=NULL WHERE iphone_device_id=@0 AND people_id<>@1", DeviceID, m_User.people_id);
// I have hard coded this query in this snippet to simplify things
db.Execute("UPDATE people SET company_id = 444, name = 'Dad', password = '<pass>', temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@gmail.com', phone = NULL, mobile = NULL, iphone_device_id = 'iphone:<device_id_blah>', iphone_device_time = '2011-06-06 19:12:29', last_checkin = '2011-06-07 02:49:47', location_lat = <lat>, location_long = <lng>, gps_strength = 66, picture_blob_id = 1661, authority = 1, active = 1, date_created = '2011-03-20 19:18:34', last_login = '2011-06-07 11:15:01', panic_mode = 0, battery_level = 0.55, battery_state = 'unplugged' WHERE people_id = 666");

Où db.execute fait fondamentalement un exécutenonquery sur un système.Data dbcommand objet.

Donc, cette séquence de requêtes aura-t-elle entraîner une impasse? Mon hypothèse est que les deux ordonnances de champ différents dans les deux requêtes provoquent le problème? Puis-je envelopper les deux requêtes dans une transaction pour résoudre l'impasse?

------------------------
LATEST DETECTED DEADLOCK
------------------------
110607 11:15:01
*** (1) TRANSACTION:
TRANSACTION 0 45674214, ACTIVE 0 sec, OS thread id 2584 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1216, 2 row lock(s)
    MySQL thread id 109, query id 4044915 localhost 127.0.0.1 famdev Searching rows for update
    UPDATE people SET iphone_device_id=NULL WHERE iphone_device_id='iphone:<device_id_blah>' AND people_id<>666
    *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 0 page no 4611 n bits 152 index `PRIMARY` of table `family`.`people` trx id 0 45674214 lock_mode X locks rec but not gap waiting
    Record lock, heap no 7 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
    0: len 8; hex 8000000000000941; asc        A;; 1: len 6; hex 000002b8eedf; asc       ;; 2: len 7; hex 00000002801064; asc       d;; 3: len 8; hex 80000000000004c6; asc         ;; 4: len 3; hex 446164; asc Dad;; 5: len 30; hex <data0>; asc <data1>;...(truncated); 6: SQL NULL; 7: SQL NULL; 8: len 17; hex <data2>; asc <redacted>@gmail.com;; 9: SQL NULL; 10: SQL NULL; 11: len 30; hex <data3>; asc iphone:<data4>;...(truncated); 12: len 8; hex <data5>; asc    J]  };; 13: len 8; hex <data6>; asc    J]   ;; 14: len 8; hex <data7>; asc ~t  g C@;; 15: len 8; hex <data8>; asc G  I &S ;; 16: len 2; hex 8042; asc  B;; 17: len 8; hex <data9>; asc        };; 18: len 4; hex <data10>; asc     ;; 19: len 1; hex 81; asc  ;; 20: len 8; hex <data11>; asc    JL} Z;; 21: len 8; hex <data12>; asc    J]  M;; 22: len 1; hex 80; asc  ;; 23: len 8; hex <data13>; asc        ?;; 24: len 9; hex <data14>; asc unplugged;;

    *** (2) TRANSACTION:
    TRANSACTION 0 45674209, ACTIVE 0 sec, OS thread id 3804 starting index read, thread declared inside InnoDB 500
    mysql tables in use 1, locked 1
    5 lock struct(s), heap size 1216, 2 row lock(s), undo log entries 1
    MySQL thread id 110, query id 4044916 localhost 127.0.0.1 famdev Updating
    UPDATE people SET company_id = 444, name = 'Dad', password = '<pass>', temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@gmail.com', phone = NULL, mobile = NULL, iphone_device_id = 'iphone:<device_id_blah>', iphone_device_time = '2011-06-06 19:12:29', last_checkin = '2011-06-07 02:49:47', location_lat = <lat>, location_long = <lng>, gps_strength = 66, picture_blob_id = 1661, authority = 1, active = 1, date_created = '2011-03-20 19:18:34', last_login = '2011-06-07 11:15:01', panic_mode = 0, battery_level = 0.55, battery_state = 'unplugged' WHERE people_id = 666
    *** (2) HOLDS THE LOCK(S):
        RECORD LOCKS space id 0 page no 4611 n bits 152 index `PRIMARY` of table `family`.`people` trx id 0 45674209 lock mode S locks rec but not gap
        Record lock, heap no 7 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
        0: len 8; hex 8000000000000941; asc        A;; 1: len 6; hex 000002b8eedf; asc       ;; 2: len 7; hex 00000002801064; asc       d;; 3: len 8; hex 80000000000004c6; asc         ;; 4: len 3; hex 446164; asc Dad;; 5: len 30; hex <data0>; asc <data1>;...(truncated); 6: SQL NULL; 7: SQL NULL; 8: len 17; hex <data2>; asc <redacted>@gmail.com;; 9: SQL NULL; 10: SQL NULL; 11: len 30; hex <data3>; asc iphone:<data4>;...(truncated); 12: len 8; hex <data5>; asc    J]  };; 13: len 8; hex <data6>; asc    J]   ;; 14: len 8; hex <data7>; asc ~t  g C@;; 15: len 8; hex <data8>; asc G  I &S ;; 16: len 2; hex 8042; asc  B;; 17: len 8; hex <data9>; asc        };; 18: len 4; hex <data10>; asc     ;; 19: len 1; hex 81; asc  ;; 20: len 8; hex <data11>; asc    JL} Z;; 21: len 8; hex <data12>; asc    J]  M;; 22: len 1; hex 80; asc  ;; 23: len 8; hex <data13>; asc        ?;; 24: len 9; hex <data14>; asc unplugged;;

        *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
        RECORD LOCKS space id 0 page no 4611 n bits 152 index `PRIMARY` of table `family`.`people` trx id 0 45674209 lock_mode X locks rec but not gap waiting
        Record lock, heap no 7 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
        0: len 8; hex 8000000000000941; asc        A;; 1: len 6; hex 000002b8eedf; asc       ;; 2: len 7; hex 00000002801064; asc       d;; 3: len 8; hex 80000000000004c6; asc         ;; 4: len 3; hex 446164; asc Dad;; 5: len 30; hex <data0>; asc <data1>;...(truncated); 6: SQL NULL; 7: SQL NULL; 8: len 17; hex <data2>; asc <redacted>@gmail.com;; 9: SQL NULL; 10: SQL NULL; 11: len 30; hex <data3>; asc iphone:<data4>;...(truncated); 12: len 8; hex <data5>; asc    J]  };; 13: len 8; hex <data6>; asc    J]   ;; 14: len 8; hex <data7>; asc ~t  g C@;; 15: len 8; hex <data8>; asc G  I &S ;; 16: len 2; hex 8042; asc  B;; 17: len 8; hex <data9>; asc        };; 18: len 4; hex <data10>; asc     ;; 19: len 1; hex 81; asc  ;; 20: len 8; hex <data11>; asc    JL} Z;; 21: len 8; hex <data12>; asc    J]  M;; 22: len 1; hex 80; asc  ;; 23: len 8; hex <data13>; asc        ?;; 24: len 9; hex <data14>; asc unplugged;;
12
RedBlueThing

Il s'avère donc que ces deux requêtes étaient au moins une partie du problème que nous avions. Nous avons modifié ces deux requêtes de:

db.Execute("UPDATE people SET iphone_device_id=NULL WHERE iphone_device_id=@0 AND people_id<>@1", DeviceID, m_User.people_id);
db.Execute("UPDATE people SET company_id = 444, name = 'Dad', password = '<pass>', temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@gmail.com', phone = NULL, mobile = NULL, iphone_device_id = 'iphone:<device_id_blah>', iphone_device_time = '2011-06-06 19:12:29', last_checkin = '2011-06-07 02:49:47', location_lat = <lat>, location_long = <lng>, gps_strength = 66, picture_blob_id = 1661, authority = 1, active = 1, date_created = '2011-03-20 19:18:34', last_login = '2011-06-07 11:15:01', panic_mode = 0, battery_level = 0.55, battery_state = 'unplugged' WHERE people_id = 666");

à:

db.Execute("UPDATE people SET iphone_device_id=NULL WHERE iphone_device_id=@0 AND people_id<>@1", DeviceID, m_User.people_id);
db.Execute("UPDATE people SET iphone_device_id=@0, iphone_device_time=@1, last_login=@1 WHERE people_id=@2", DeviceID, System.DateTime.UtcNow, m_User.people_id);

Nous ne mettrons donc plus à jour l'ensemble de l'enregistrement (sur plusieurs touches) et nous mettons à jour les champs dans le même ordre. Depuis que nous avons fait le changement, nos blocages ont disparu.

4
RedBlueThing

Même si les déclarations sont exécutées en séquence, si elles existent à l'intérieur de la même transaction, vous devez émettre une sorte de point de contrôle entre requêtes ou tweek le niveau d'isolement de transaction avant démarrer la transaction.

Il y a quatre valeurs pour tx_isolation:

Vous pouvez définir l'isolement de la transaction trois (3) façons:

Ecrivez ceci dans /etc/my.cnf et redémarrez MySQL

[mysqld]
autocommit=0
transaction-isolation = READ-UNCOMMITTED

ou vous pouvez le définir dans la connexion DB elle-même avant de commencer toute nouvelle transaction:

db.Execute("SET tx_isolation = 'READ-UNCOMMITTED'");
db.Execute("SET autocommit = 0");

ou désactiver l'autocommande à l'aide de protocoles .NET (Disclaimer: Je ne suis pas un développeur .NET)

Bien que je me penche vers la lecture non engagée pour permettre des "lectures sales", vous devez expérimenter d'autres niveaux d'isolation de transaction à un moment donné pour voir lequel a l'effet souhaité.

Essaie !!!

7
RolandoMySQLDBA