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.
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 chose UDPATE 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.
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.