Très novice sur le travail DB, alors appréciez votre patience avec une question de base. J'exécute SQL Server 2014 sur ma machine locale et j'ai une petite table et une application client de base pour tester différentes approches avec. J'obtiens ce qui semble être un verrou de table pendant les instructions INSERT INTO
et UPDATE
. Le client est une application ASP.NET avec le code suivant:
OleDbConnection cn = new OleDbConnection("Provider=SQLNCLI11; server=localhost\\SQLEXPRESS; Database=<my db>; user id=<my uid>; password=<my pwd>");
cn.Open();
OleDbTransaction tn = cn.BeginTransaction();
OleDbCommand cmd = new OleDbCommand("INSERT INTO LAYOUTSv2 (LAYOUTS_name_t, LAYOUTS_enabled_b, LAYOUTS_data_m) VALUES ('name', '-1', 'data')", cn, tn);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
int newkey = Decimal.ToInt32((decimal)cmd.ExecuteScalar());
Console.WriteLine("Created index " + newkey);
Thread.Sleep(15000);
tn.Commit();
tn = cn.BeginTransaction();
cmd.CommandText = "UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key='" + newkey + "'";
cmd.Transaction = tn;
cmd.ExecuteNonQuery();
Console.WriteLine("updated row");
Thread.Sleep(15000);
tn.Rollback();
cn.Close();
Je lance ce code, puis depuis le studio de gestion que je dirige SELECT * FROM LAYOUTSv2
. Dans les deux cas, lorsque le thread client est suspendu (c'est-à-dire avant la validation / restauration), la requête SELECT se bloque jusqu'à ce que la validation / restauration se produise.
La table a le champ LAYOUTS_key affecté comme clé primaire. Dans la fenêtre des propriétés, il montre qu'il est unique et en cluster, avec les verrous de page et les verrous de ligne autorisés. Le paramètre d'escalade de verrouillage pour la table est Désactiver ... J'ai essayé les deux autres paramètres disponibles de Table et AUTO sans aucun changement. J'ai essayé SELECT ... WITH (NOLOCK)
et cela renvoie un résultat immédiatement, mais comme cela est bien mis en garde ici et ailleurs, ce n'est pas ce que je devrais faire. J'ai essayé de ROWLOCK
donner un indice aux déclarations INSERT
et UPDATE
, mais rien n'a changé.
Le comportement que je recherche est le suivant: avant de valider un INSERT
, les requêtes provenant d'autres threads lisent toutes les lignes sauf celle en cours de INSERT
modification. Avant de valider une UPDATE
requête à partir d'autres threads, lisez la version de départ de la ligne en cours d' UPDATE
édition. Existe-t-il un moyen de le faire? Si je dois fournir d'autres informations pour clarifier mon cas d'utilisation, veuillez me le faire savoir. Merci.
la source
WHERE LAYOUTS_key='" + newkey + "'
est un non-non complet pour diverses raisons, y compris l'injection SQL, vous devez utiliser des requêtes paramétrées.newkey
"something';DELETE FROM LAYOUTSv2 --
". Votre mise à jour se terminerait correctement, puis viderait la table car l'utilisateur a manipulé la requête en insérant une apostrophe. Normalement, une requête paramétrée ressemble à quelque choseUDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?
, après quoi vous attribuez séparément des valeurs au?
(le paramètre) dans votre code.Réponses:
Il y a de fortes chances qu'il ne verrouille pas la "table entière".
Il verrouille une ligne dans le tableau mais votre
SELECT * FROM LAYOUTSv2
essaie de lire le tableau entier est donc nécessairement bloqué par ce verrou.Pour le cas d'insertion, vous pouvez simplement spécifier le
READPAST
conseil pour ignorer la ligne verrouillée, mais cela ne donnera pas le résultat souhaité pour leUPDATE
cas (il sautera à nouveau la ligne sans lire la version de départ de la ligne).Si vous configurez la base de données pour l' isolement des instantanés validés en lecture, cela donnera l'effet souhaité dans les deux cas (au détriment d'une utilisation accrue de
tempdb
)la source
SNAPSHOT
isolement pour le laisser désactivé, puis activez-le si vous décidez par la suite que cela vous serait utile.Les instructions d'insertion et de mise à jour sont censées créer des verrous au niveau des lignes. Toutefois, lorsque le nombre de verrous dans une transaction est de 5 000 ou plus, une escalade de verrous se produit et crée un verrou au niveau de la table. Veuillez voir ci-dessous.
https://technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx
la source