J'ai une application C # qui insère des données dans une table SQL Server (2008) à l'aide d'une procédure stockée. J'utilise le multi-threading pour le faire. La procédure stockée est appelée depuis le thread . Ma procédure stockée utilise maintenant "tablock" lors de l'insertion de données . Lors de l'exécution de ce code, l'erreur suivante s'affiche: "Transaction (ID de processus) a été bloqué sur les ressources de verrouillage avec un autre processus et a été choisi comme victime du blocage. Relancez la transaction. "
Quelqu'un peut-il m'aider s'il vous plaît avec n'importe quelle solution à cela?
Cela se produit lorsque deux processus SQL Server accèdent aux mêmes ressources, mais dans un ordre différent. Par conséquent, ils finissent tous les deux par attendre l'autre processus, ce qui est une impasse.
Il existe un certain nombre de moyens pour le prévenir, notamment:
with (nolock)
pour les requêtes, le cas échéant.Par exemple. si Proc1 verrouille table1 puis table2, mais que Proc2 verrouille table2 puis table1, le problème peut survenir. Vous pouvez réécrire l'un ou l'autre proc pour prendre des verrous dans le même ordre afin d'éviter ce problème.
Vous pouvez encapsuler votre requête dans un bloc TRY CATCH et intercepter des numéros d'erreur (liés aux verrous).
Ensuite, vous pouvez automatiser les tentatives, jusqu’à un certain nombre. Vous feriez donc quelque chose comme ce qui suit:
DECLARE @RetryNo Int = 1
,@RetryMaxNo Int = 5;
WHILE @RetryNo < @RetryMaxNo
BEGIN
BEGIN TRY
-- put your query that generates locks here....
SELECT @RetryNo = @RetryMaxNo;
END TRY
BEGIN CATCH
IF ERROR_NUMBER() IN (1204, 1205, 1222)
BEGIN
SET @RetryNo += 1;
-- it will wait for 10 seconds to do another attempt
WAITFOR DELAY '00:00:10';
END
ELSE
THROW;
END CATCH
END
Vous pouvez également utiliser des indicateurs de table tels que UPDLOCK .
Soyez sûr du champ que vous allez mettre à jour ou insérer, ce champ a un index non clusterisé. S'il n'est pas disponible, vous pouvez d'abord créer un index non clusterisé de ce champ sur cette table, puis créer les étapes ci-dessous.
Faites un clic droit sur la table et sélectionnez les propriétés.
Sélectionnez Option dans le panneau de droite dans les propriétés.
Dans l'onglet Verrou, autoriser le verrouillage de page, indiquez 'Faux' et Autoriser le verrouillage de ligne, la valeur étant 'True', puis appuyez sur OK.
Voici une solution de MSDN par S Kumar Dubey
Exécutez SP: SP_LOCK dans les résultats, vous obtiendrez SPID, DBID, OBJID, INDID, TYPE, RESSOURCE, MODE, ÉTAT Maintenant, vérifiez la colonne d’état, si elle est montrant attendre puis tuez ce SPID. Pour tuer un SPID particulier, exécutez SP: Kill 65 (où 65 est SPID)
Il semble que vous ayez besoin d'être l'administrateur du serveur SQL pour résoudre ce problème.
vous pouvez utiliser depuis l'objet Lock
static object _lock = new object();
public static void _main()
{
lock (_lock)
{
_bulkcopy(myData);
}
}
public static void _bulkcopy(DataTable dt)
{
try
{
using (var connection = new SqlConnection(ConfigurationSettings.AppSettings.Get("DBConnection")))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
{
bulkCopy.BatchSize = 100;
bulkCopy.DestinationTableName = "dbo.MyTable";
try
{
bulkCopy.WriteToServer(dt);
}
catch (Exception)
{
transaction.Rollback();
connection.Close();
}
}
transaction.Commit();
}
}
catch { }
}
vous devez concevoir des modules de base de données de manière à minimiser les risques de blocages. Voici quelques conseils utiles sur la façon de procéder: Assurez-vous que les applications accèdent à tous les objets partagés dans le même ordre.
Ici, vous pouvez en voir plus et apprendre beaucoup de moyens utiles pour éviter une impasse