Maison  >  Questions et réponses  >  le corps du texte

python多线程爬虫往mysql里面写数据导致死锁

我在爬虫里面用的是MySQLdb这个包进行insert操作,我一开始是所有子线程公用一个mysql连接,结果发现数据写不进去,然后我又试过所有子线程公用一个cursor游标,出现了只有部分数据写进去了,而且自增id居然还自增了。(也就是数据没有写入进去,但是自增id的自增数增加了),最后我干脆每个子线程在每一次写入的时候创建一个连接句柄,然后就出现了如图症状,请问这该怎么办啊?有什么优化方法吗?

PHP中文网PHP中文网2741 Il y a quelques jours396

répondre à tous(3)je répondrai

  • 怪我咯

    怪我咯2017-04-18 10:12:53

    Merci pour l'invitation. Metadata Lock (MDL) a été introduit dans le mécanisme de protection des métadonnées de MySQL dans la version 5.5. 5.5 La protection des métadonnées se situe au niveau de la transaction et le MDL n'est publié qu'une fois la transaction terminée.
    Lorsqu'une session effectue une opération DML dans la base de données principale et n'a pas encore été soumise, une autre session effectue une opération DDL telle que supprimer une table sur le même objet. Puisque le journal binaire de MySQL est enregistré en fonction de l'ordre de soumission des transactions, donc dans. Lors d'une application à partir de la bibliothèque, il y aura une situation dans laquelle la table sera d'abord supprimée puis insérée dans la table, provoquant une erreur dans l'application à partir de la bibliothèque. Par conséquent, MySQL a introduit le verrou des métadonnées après la version 5.5.3. Le verrou des métadonnées ne sera libéré qu'après la fin de la transaction, de sorte que les opérations DDL ne peuvent pas être effectuées avant que la transaction ne soit validée ou annulée.
    Les causes de l'attente du verrouillage des métadonnées de la table sont généralement les scénarios simples suivants :
    Scénario 1 : longue transaction en cours d'exécution, bloquant DDL, puis bloquant toutes les opérations ultérieures sur la même table
    Scénario 2 : La transaction n'est pas soumise, bloquant DDL, puis bloquant toutes les opérations ultérieures sur la même table

    Alors comment le résoudre ?
    Afficher tous les verrous de transaction en attente d'état bloqué

    USE INFORMATION_SCHEMA
    SELECT * 
    FROM INNODB_LOCKS 
    WHERE LOCK_TRX_ID IN (SELECT BLOCKING_TRX_ID FROM INNODB_LOCK_WAITS);
    

    Ou vous pouvez cibler directement une table spécifique

    SELECT * FROM INNODB_LOCKS 
    WHERE LOCK_TABLE = db_name.table_name;

    La suppression directe des enregistrements concernés devrait déverrouiller le verrou.

    Suggestion : utilisez un pool de connexions au lieu de partager une connexion pour tous les threads, et n'oubliez pas de valider ou d'annuler chaque transaction.
    Référence recommandée :
    https://dev.mysql.com/doc/ref...
    http://www.cnblogs.com/cchust...
    https://gold .xitu.io/entry/57...
    http://www.cnblogs.com/digdee...

    répondre
    0
  • 天蓬老师

    天蓬老师2017-04-18 10:12:53

    Le tableau provient d'Innodb, mais la soumission automatique n'est pas activée et il n'y a pas de soumission manuelle.

    répondre
    0
  • 黄舟

    黄舟2017-04-18 10:12:53

    Tout d'abord, plusieurs threads partagent une seule connexion, ce qui équivaut à la concurrence. De nombreux threads doivent attendre.
    Le taux d'utilisation d'une connexion par thread n'est pas élevé, il s'agit donc généralement d'un pool de connexions. Il n'y a pas besoin de recyclage et la connexion est toujours maintenue, évitant ainsi les déconnexions fréquentes.

    Avec photos, si le sujet a ouvert la transaction

    répondre
    0
  • Annulerrépondre