Question

Je cherche une bonne stratégie de faire face à la base de données à partir d'une des interblocages application Java 6; plusieurs fils parallèles pourraient, potentiellement, écrire dans la même table en même temps. La base de données (SGBDR Ingres) va tuer au hasard une des sessions si elle détecte une impasse.

Quelle serait une technique acceptable pour faire face à la situation de blocage, compte tenu des exigences suivantes?

  • le temps total écoulé doit être maintenu aussi petite que possible
  • tuer une session encourra une significatif (mesurable) rollback
  • threads temps ont aucun moyen de
    communiquer les uns avec les autres à savoir le stratégie devrait être autonome

Jusqu'à présent, la stratégie que je suis venu avec quelque chose le long de ces lignes:

short attempts = 0;
boolean success = false;
long delayMs = 0;

Random random = new Random();
do {
    try {
        //insert loads of records in table 'x'
        success = true;
    } catch (ConcurrencyFailureException e) {
        attempts++;
        success = false;
        delayMs = 1000*attempts+random.nextInt(1000*attempts);

        try {
                Thread.sleep(delayMs);
            } catch (InterruptedException ie) {
        }
    }
} while (!success);

Peut-il être amélioré de quelque façon? par exemple. en attente d'un montant fixe (nombre magique) de secondes. Y at-il une autre stratégie qui produira de meilleurs résultats?

Remarque: Plusieurs techniques de niveau base de données seront utilisées pour assurer résolution des blocages, dans la pratique, très rare. En outre, l'application tentera d'éviter les discussions de planification qui écrivent dans la même table en même temps. La situation ci-dessus sera juste un « pire scénario ».

Remarque: Le tableau dans lequel les enregistrements sont insérés est organisé comme une table partitionnée en tas et n'a pas d'index; chaque thread insérer des enregistrements dans sa propre partition.

Était-ce utile?

La solution

Une approche couramment utilisée est une certaine forme de back-off exponentielle. Plutôt que de votre aproche de 1000*attempts+random, faire le retard d'une fonction exponentielle du nombre de tentatives. Cela garantit une latence minimale dans les premiers un ou deux tentatives, où il aurait pu tout simplement été mauvaise chance que vous IMPASSE, mais vous donne des retards beaucoup plus importants plus tard, quand il est clair que la connexion est vraiment encombré.

Bien sûr, une autre approche serait d'essayer d'organiser votre base de données afin que les accès sont moins susceptibles blocages de se produire. Mais sans savoir ce que vos requêtes font (et comment, et quand ils sont exécutés), il est impossible de dire si cela peut être fait

Autres conseils

C'est la façon dont nous l'avons fait. Boucle et recommencez l'opération jusqu'à ce qu'elle se termine.

Nous ne avons rien changé avec des retards aléatoires.

En outre, nous avons l'commettons dans le bloc try et le rollback dans le gestionnaire d'exception.

Lorsque vous avez plusieurs ressources verrouillables et plusieurs opérations simultanées, l'impasse est inévitable. Il est une conséquence logique de discorde pour les serrures.

Si vous éviter les conflits pour les serrures (à savoir, verrouillage au niveau de la table pessimiste), alors vous avez tendance aussi à prévenir la concurrence. Si vous pouvez définir la transaction qui ne prétend pas pour les serrures, vous pouvez éviter une impasse. accès simultané à la même table, cependant, est à peu près la définition de l'impasse.

Lors du chargement, inserts (Especial dans une table HEAP) peuvent (souvent) se dérouler en parallèle sans beaucoup de problèmes de contention. Si vous retardez la construction des indices, alors il n'y a pas d'autres mises à jour en cours pendant l'insertion.

Alors, vous pourriez être en mesure d'éviter en laissant tomber les indices, en changeant l'organisation à un tas, chargement avec plusieurs processus simultanés (ou threads, il est généralement plus rapide d'avoir plusieurs processus), puis construire vos indices (et peut-être réorganiser le tableau), vous pouvez être en mesure d'éviter les blocages.

Lorsque vous effectuez des mises à jour ou suppressions, pas beaucoup aide.

Si vous n'avez pas besoin d'avoir un accès simultané à la base de données une solution simple pourrait être de l'enlever et utiliser une file d'attente de traitement des tâches pour mettre à jour la base de données au lieu, sérialisation accès à la base de données via la file d'attente. Je sais que cela va introduire un élément asynchrone à votre application, et ainsi ne serait pas adapté à la plupart des applications initiées par l'utilisateur ou web-apps en ligne, mais pourrait être utile d'envisager pour une application de type batch / hors ligne (je me rends compte probablement pas la réponse à votre recherche pour bien).

Avec une base de données comme Ingres vous obtiendrez toujours des blocages, vous devez supposer que toute insertion, mise à jour ou supprimer échouera et une stratégie de nouvelle tentative en place (comme dans votre exemple). Vous devez concevoir votre base de données de telle sorte que contention est réduite au minimum et ne se produit que rarement les blocages. Si vous obtenez toujours des transactions défaillantes, même après plusieurs tentatives, cela est un signe que vous aurez à faire une refonte majeure de la base de données (ou de passer à un système comme Oracle où il est généralement possible de concevoir des applications pour éviter les blocages par l'utilisation appropriée de verrouillage de ligne).

comment est-ce?

short attempts = 0;
boolean success = false;
long delayMs = 0;

Random random = new Random();
do {
try {
     synchronized(ClassName.class) {
         //insert loads of records in table 'x'
      }

    success = true;
} catch (ConcurrencyFailureException e) {
    attempts++;
    success = false;
    delayMs = 1000*attempts+random.nextInt(1000*attempts);

    try {
                    Thread.sleep(delayMs);
            } catch (InterruptedException ie) {
    }
  }
} while (!success);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top