Sehr viel ein Neuling auf DB-Arbeit, also schätzen Sie Ihre Geduld mit einer grundlegenden Frage. Ich führe SQL Server 2014 auf meinem lokalen Computer aus und habe eine kleine Tabelle und eine grundlegende Clientanwendung, mit der ich verschiedene Ansätze testen kann. Ich erhalte , was scheint , während sowohl eine Tabellensperre zu sein INSERT INTO
und UPDATE
Anweisungen. Der Client ist eine ASP.NET-Anwendung mit dem folgenden Code:
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();
Ich führe diesen Code aus, dann aus dem Management Studio, das ich ausführe SELECT * FROM LAYOUTSv2
. In beiden Fällen, in denen der Client-Thread angehalten wurde (dh vor dem Festschreiben / Zurücksetzen), bleibt die SELECT-Abfrage hängen, bis das Festschreiben / Zurücksetzen erfolgt.
Der Tabelle ist das Feld LAYOUTS_key als Primärschlüssel zugewiesen. Im Eigenschaftenfenster wird angezeigt, dass es eindeutig und gruppiert ist, wobei sowohl Seitensperren als auch Zeilensperren zulässig sind. Die Sperren-Eskalationseinstellung für die Tabelle ist Deaktivieren ... Ich habe beide verfügbaren Einstellungen von Tabelle und AUTO ohne Änderungen ausprobiert. Ich habe es versucht SELECT ... WITH (NOLOCK)
und das gibt sofort ein Ergebnis zurück, aber wie hier und an anderen Orten gut gewarnt wird, ist es nicht das, was ich tun sollte. Ich habe versucht, den ROWLOCK
Hinweis auf die INSERT
und UPDATE
-Anweisungen zu setzen, aber nichts hat sich geändert.
Das Verhalten, nach dem ich suche, ist das Folgende: Vor dem Festschreiben von INSERT
lesen Abfragen von anderen Threads alle Zeilen mit Ausnahme derjenigen, die INSERT
bearbeitet werden. UPDATE
Lesen Sie vor dem Festschreiben von Abfragen aus anderen Threads die Startversion der zu bearbeitenden Zeile UPDATE
. Kann ich das auf irgendeine Weise tun? Wenn ich weitere Informationen zur Klärung meines Anwendungsfalls benötige, lassen Sie es mich bitte wissen. Vielen Dank.
quelle
WHERE LAYOUTS_key='" + newkey + "'
ist ein komplettes Nein-Nein aus verschiedenen Gründen, einschließlich SQL-Injection, sollten Sie parametrisierte Abfragen verwenden.newkey
auf "something';DELETE FROM LAYOUTSv2 --
". Ihre Aktualisierung wurde erfolgreich abgeschlossen und die Tabelle anschließend geleert, da der Benutzer die Abfrage durch Einfügen eines Apostrophs manipuliert hat. Normalerweise sieht eine parametrisierte Abfrage wie folgt aus: DanachUDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?
weisen Sie dem?
(dem Parameter) in Ihrem Code separat Werte zu .Antworten:
Wahrscheinlich wird nicht der gesamte Tisch gesperrt.
Es wird eine Zeile in der Tabelle
SELECT * FROM LAYOUTSv2
gesperrt, aber Sie versuchen, die gesamte Tabelle zu lesen, sodass diese Sperre zwangsläufig blockiert wird.Für das Einfügen von Groß- und Kleinschreibung können Sie lediglich den
READPAST
Hinweis zum Überspringen der gesperrtenUPDATE
Zeile angeben. Dies ergibt jedoch nicht das gewünschte Ergebnis für die Groß- und Kleinschreibung (es wird die Zeile erneut übersprungen und nicht die Startversion der Zeile gelesen).Wenn Sie die Datenbank für die Read Committed Snapshot-Isolation konfigurieren , erhalten Sie in beiden Fällen den gewünschten Effekt (auf Kosten einer stärkeren Verwendung von
tempdb
).quelle
SNAPSHOT
Isolation nicht explizit verwenden , lassen Sie sie am besten deaktiviert und aktivieren Sie sie dann, wenn Sie sich später dazu entschließen, dass dies für Sie nützlich ist.Mit den Anweisungen insert und update sollen Sperren auf Zeilenebene erstellt werden. Wenn die Anzahl der Sperren in einer Transaktion jedoch 5.000 oder mehr beträgt, tritt eine Sperreneskalation auf und es wird eine Sperre auf Tabellenebene erstellt. Siehe unten.
https://technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx
quelle