SELECT FOR UPDATE mit SQL Server

79

Ich verwende eine Microsoft SQL Server 2005-Datenbank mit Isolationsstufe READ_COMMITTEDund READ_COMMITTED_SNAPSHOT=ON.

Jetzt möchte ich verwenden:

SELECT * FROM <tablename> FOR UPDATE

... damit andere Datenbankverbindungen blockieren, wenn versucht wird, auf dieselbe Zeile "FOR UPDATE" zuzugreifen.

Ich habe es versucht:

SELECT * FROM <tablename> WITH (updlock) WHERE id=1

... aber dies blockiert alle anderen Verbindungen, auch wenn eine andere ID als "1" ausgewählt wird.

Welches ist der richtige Hinweis SELECT FOR UPDATEfür Oracle, DB2, MySql?

EDIT 2009-10-03:

Dies sind die Anweisungen zum Erstellen der Tabelle und des Index:

CREATE TABLE example ( Id BIGINT NOT NULL, TransactionId BIGINT, 
    Terminal BIGINT, Status SMALLINT );
ALTER TABLE example ADD CONSTRAINT index108 PRIMARY KEY ( Id )
CREATE INDEX I108_FkTerminal ON example ( Terminal )
CREATE INDEX I108_Key ON example ( TransactionId )

Viele parallele Prozesse tun dies SELECT:

SELECT * FROM example o WITH (updlock) WHERE o.TransactionId = ?

EDIT 2009-10-05:

Zur besseren Übersicht habe ich alle erprobten Lösungen in der folgenden Tabelle aufgeführt:

Mechanismus | SELECT für verschiedene Zeilenblöcke | SELECT für dieselben Zeilenblöcke
----------------------- + -------------------------- ------ + --------------------------
ROWLOCK | nein | Nein
Updlock, Rowlock | ja | Ja
xlock, rowlock | ja | Ja
repeatableread | nein | Nein
DBCC TRACEON (1211, -1) | ja | Ja
Rowlock, Xlock, Holdlock | ja | Ja
Updlock, Holdlock | ja | Ja
UPDLOCK, READPAST | nein | Nein

Ich suche | nein | Ja
Tangens
quelle
Ich suche nicht nur nach Optimierungshinweisen. Eine andere mögliche Lösung könnte darin bestehen, die Isolationsstufe, die globalen Datenbankattribute usw. zu ändern. Alles (außer die Verwendung einer anderen Datenbank) ist möglich.
Tangens
4
Was versuchen Sie zu tun, das braucht eine solche Verriegelung. Es ist normalerweise besser, mit richtigen Abfragen zu lösen, als mit Server-Features
TFD
2
Können Sie bitte die von Ihnen verwendete Abfrage und die DDL der Tabelle (n) einschließlich aller Schlüssel und Indizes angeben?
RBarryYoung
Sind Sie sicher, dass Ihre andere Abfrage nicht nicht festgeschrieben ist?
Nathan Feger
1
Um dieses Problem zu umgehen, können Sie versuchen, zuerst ein einfaches Update für diese Zeile durchzuführen (ohne wirklich Daten zu ändern). Danach können Sie mit der Zeile fortfahren, wie in für die Aktualisierung ausgewählt wurde.
Vladimir

Antworten:

34

Vor kurzem hatte ich ein Deadlock-Problem, weil SQL Server mehr als nötig sperrt (Seite). Man kann nichts dagegen tun. Jetzt fangen wir Deadlock-Ausnahmen ein ... und ich wünschte, ich hätte stattdessen Oracle.

Bearbeiten: Wir verwenden mittlerweile die Snapshot-Isolation, die viele, aber nicht alle Probleme löst. Um die Snapshot-Isolation verwenden zu können, muss sie leider vom Datenbankserver zugelassen werden, was zu unnötigen Problemen beim Kunden führen kann. Jetzt fangen wir nicht nur Deadlock-Ausnahmen ab (die natürlich immer noch auftreten können), sondern auch Snapshot-Parallelitätsprobleme, um Transaktionen aus Hintergrundprozessen zu wiederholen (die vom Benutzer nicht wiederholt werden können). Dies ist jedoch immer noch viel besser als zuvor.

Stefan Steinegger
quelle
Ich fürchte, das ist wahr. Ich habe keine Möglichkeit gefunden, ein funktionierendes "SELECT FOR UPDATE" zu erhalten. Meine Lösung besteht nun darin, "SELECT FOR UPDATE" aufzugeben und ein einfaches, nicht blockierendes "SELECT" durchzuführen und gleichzeitig mit einem Update-Zähler ("UPDATE WHERE id =? Und updateCount =?") Auf gleichzeitige "UPDATES" zu prüfen.
Tangens
1
SQL 2008 bietet zwei neue optimistische Isolationsstufen, ähnlich wie Oracle
Chris Bednarski
@ChrisBednarski Ich habe WITH (ROWLOCK) in SQL Server 2008 R2 verwendet und es hat immer noch mehr als eine Zeile gesperrt !!!
Können
2
@bjan: Schnappschuss-Isolation nachschlagen. Einige Infos hier msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.80).aspx
Chris Bednarski
1
@ChrisBednarski danke für den Link, diese beiden Befehle haben Tag und Nacht einen Unterschied gemacht: ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON; ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON; siehe auch MichaelBuens Antwort auf diese Frage.
László van den Hoek
22

Ich habe ein ähnliches Problem, ich möchte nur 1 Zeile sperren. Soweit ich weiß, UPDLOCKsperrt SQLSERVER mit der Option alle Zeilen, die gelesen werden müssen, um die Zeile abzurufen. Wenn Sie also keinen Index für den direkten Zugriff auf die Zeile definieren, werden alle vorhergehenden Zeilen gesperrt. In Ihrem Beispiel:

Angenommen, Sie haben eine Tabelle mit dem Namen TBL mit einem idFeld. Sie möchten die Zeile mit sperren id=10. Sie müssen einen Index für die Feld-ID definieren (oder für alle anderen Felder, die an Ihrer Auswahl beteiligt sind):

CREATE INDEX TBLINDEX ON TBL ( id )

Und dann lautet Ihre Abfrage, NUR die von Ihnen gelesenen Zeilen zu sperren:

SELECT * FROM TBL WITH (UPDLOCK, INDEX(TBLINDEX)) WHERE id=10.

Wenn Sie die Option INDEX (TBLINDEX) nicht verwenden, muss SQLSERVER alle Zeilen vom Anfang der Tabelle lesen, um Ihre Zeile mit zu finden id=10, damit diese Zeilen gesperrt werden.

ManuelConde
quelle
+1 für die Angabe der Grundursache, warum SQL Server die Rowlock-Direktive "ignoriert". Ich habe diesen Ansatz unter meiner App verwendet und tatsächlich erreicht, was Tangens verlangt
Shmil The Cat
-1 Ich hatte einen Clustered-Index und das Einfügen in die Hinweise machte keinen Unterschied. Das Updlock + Rowlock + Holdlock funktionierte hervorragend, als ich feststellte, dass ich versehentlich andere Datensätze nach der SELECT-Sperranweisung in meinem SP berührte (es fehlte eine Bedingung für IDs, die in der ursprünglichen Auswahl vorhanden waren).
MoonStom
8

Sie können nicht gleichzeitig eine Snapshot-Isolierung durchführen und Lesevorgänge blockieren. Der Zweck der Snapshot-Isolierung besteht darin, das Blockieren von Lesevorgängen zu verhindern .

Christian Hayter
quelle
5

Versuchen Sie es (Updlock, Rowlock)

BlueMonkMN
quelle
Ja, ich habe Rowlock versucht (ohne Kombination mit anderen Hinweisen), aber ein gleichzeitiges SELECT FOR UPDATE derselben Zeile blockiert nicht.
Tangens
OK, ich habe es versucht (Updlock, Rowlock), aber ein zweites SELECT FOR UPDDATE blockiert, selbst wenn auf eine andere Zeile zugegriffen wird.
Tangens
(xlock, rowlock) blockiert auch andere Zeilen.
Tangens
Warum denkst du, dass es blockieren sollte?
RBarryYoung
1
Das ist pessimistische Parallelität. Wenn Sie das wollen, warum geben Sie dann eine optimistische Parallelität an?
RBarryYoung
5

Die vollständige Antwort könnte sich mit den Interna des DBMS befassen. Dies hängt davon ab, wie die Abfrage-Engine (die den vom SQL-Optimierer generierten Abfrageplan ausführt) funktioniert.

Eine mögliche Erklärung (die zumindest für einige Versionen eines DBMS gilt - nicht unbedingt für MS SQL Server) ist jedoch, dass die ID-Spalte keinen Index enthält, sodass jeder Prozess, der versucht, eine Abfrage mit ' WHERE id = ?' darin zu bearbeiten , am Ende ausgeführt wird Ein sequentieller Scan der Tabelle, und dieser sequentielle Scan trifft die Sperre, die Ihr Prozess angewendet hat. Sie können auch auf Probleme stoßen, wenn das DBMS standardmäßig Sperren auf Seitenebene anwendet. Durch das Sperren einer Zeile werden die gesamte Seite und alle Zeilen auf dieser Seite gesperrt.

Es gibt einige Möglichkeiten, wie Sie dies als Problemquelle entlarven können. Sehen Sie sich den Abfrageplan an. studiere die Indizes; Versuchen Sie Ihr SELECT mit der ID 1000000 anstelle von 1 und prüfen Sie, ob andere Prozesse noch blockiert sind.

Jonathan Leffler
quelle
Es hängt also von MS SQL Server ab. Vielleicht werden Sperren im Index nicht übersprungen. Ich schlage vor, den Test 'ID = <Große-Nummer>' an einem Datensatz zu versuchen, der groß genug ist, um mehrere Seiten zu verwenden. Sie könnten einen Unterschied sehen; du könntest nicht. Sie können versuchen, die "anderen Prozesse" auf einer Isolationsstufe "Dirty Read" auszuführen. Dies sollte Sie zum Lesen an den Schlössern vorbei bringen - ist aber im Allgemeinen keine sehr gute Lösung.
Jonathan Leffler
Alle Prozesse lesen dasselbe: Sie wählen "ihren" Datensatz aus und aktualisieren den Status am Ende des Vorgangs.
Tangens
1
Der Wert für ID ist also für jeden Prozess gleich? Oder verwenden sie jeweils eine andere ID? Letzteres nehme ich an. Und die Frage ist, ob das DBMS ausreichend unterschiedliche ID-Werte zulässt, um Sperren zu umgehen. Meine Spekulation ist, dass wenn die ID-Werte unterschiedlich genug sind, Sie an Sperren vorbei kommen. Aber nicht, wenn zum Beispiel der Index für ID nicht verwendet wird. Haben Sie sich die Abfragepläne schon angesehen?
Jonathan Leffler
Entschuldigung, ich konnte noch nicht herausfinden, wie das geht. Und ja, jeder Prozess verwendet eine andere ID.
Tangens
Ich habe mir den Abfrageplan ja angesehen, aber nichts Besonderes gesehen.
Tangens
5

Vielleicht könnte es gelöst werden, wenn mvcc permanent ist (im Gegensatz zu nur einer bestimmten Charge: SET TRANSACTION ISOLATION LEVEL SNAPSHOT):

ALTER DATABASE yourDbNameHere SET READ_COMMITTED_SNAPSHOT ON;

[EDIT: 14. Oktober]

Nach dem Lesen: Bessere Parallelität in Oracle als SQL Server? und dies: http://msdn.microsoft.com/en-us/library/ms175095.aspx

Wenn die Datenbankoption READ_COMMITTED_SNAPSHOT auf ON gesetzt ist, werden die zur Unterstützung der Option verwendeten Mechanismen sofort aktiviert. Beim Setzen der Option READ_COMMITTED_SNAPSHOT ist nur die Verbindung in der Datenbank zulässig, die den Befehl ALTER DATABASE ausführt. Es darf keine andere offene Verbindung in der Datenbank bestehen, bis ALTER DATABASE abgeschlossen ist. Die Datenbank muss sich nicht im Einzelbenutzermodus befinden.

Ich bin zu dem Schluss gekommen, dass Sie zwei Flags setzen müssen, um das MVCC von mssql dauerhaft in einer bestimmten Datenbank zu aktivieren:

ALTER DATABASE yourDbNameHere SET ALLOW_SNAPSHOT_ISOLATION ON;
ALTER DATABASE yourDbNameHere SET READ_COMMITTED_SNAPSHOT ON;
Michael Buen
quelle
Nachdem ich den Kommentar von @Chris Bednarski unter der akzeptierten Antwort gelesen hatte, kam ich zu dem gleichen Schluss wie Sie, Michael. Dies scheint einen Großteil unserer festgefahrenen Probleme zu lösen. Wenn Sie das Datenbankeigenschaften-Dialogfeld von SQL Server Management Studio verwenden, werden Sie aufgefordert, alle Clients zu trennen, und es ist kein Neustart erforderlich.
László van den Hoek
3

OK, eine einzelne Auswahl verwendet standardmäßig die Transaktionsisolation "Read Committed", die das Schreiben in diesen Satz sperrt und daher stoppt. Sie können die Transaktionsisolationsstufe mit ändern

Set Transaction Isolation Level { Read Uncommitted | Read Committed | Repeatable Read | Serializable }
Begin Tran
  Select ...
Commit Tran

Diese werden in SQL Server BOL ausführlich erläutert

Ihr nächstes Problem ist, dass SQL Server 2K5 die Sperren standardmäßig eskaliert, wenn Sie mehr als ~ 2500 Sperren haben oder mehr als 40% des "normalen" Speichers in der Sperrtransaktion verwenden. Die Eskalation geht zur Seite und dann zur Tabellensperre

Sie können diese Eskalation ausschalten, indem Sie das "Trace-Flag" 1211t setzen. Weitere Informationen finden Sie unter BOL

TFD
quelle
Vielen Dank, das klingt so, als ob es die Lösung sein könnte. Ich werde es am Montag versuchen.
Tangens
Ich habe es versucht, aber es hat nicht funktioniert. Ein zweites SELECT blockiert immer noch, wenn auf eine andere Zeile zugegriffen wird.
Tangens
3

Erstellen Sie ein gefälschtes Update, um den Rowlock zu erzwingen.

UPDATE <tablename> (ROWLOCK) SET <somecolumn> = <somecolumn> WHERE id=1

Wenn das Ihre Reihe nicht sperrt, weiß Gott, was wird.

Nach diesem " UPDATE" können Sie Ihre SELECT (ROWLOCK)und nachfolgende Updates durchführen.

Feu
quelle
Ich frage mich, ob dies schlechter abschneidet als die Alternative, bei der nur eine Auswahl mit einem Xlock-Hinweis durchgeführt wird. Rowlock ist nicht unbedingt zuverlässig, da SQL Server keine Zeilen sperrt, sondern 6-Byte-Hashes von Zeilen sperrt, sodass die Gefahr einer Kollision mit einer großen Anzahl von Datensätzen in der Tabelle besteht. Da Rowlock ein "Hinweis" ist, kann nicht garantiert werden, dass keine Sperreneskalation auftritt, obwohl Sie dieses Risiko wahrscheinlich minimieren können, indem Sie die Sperreneskalation für die Tabelle deaktivieren.
Triynko
2

Ich gehe davon aus, dass Sie nicht möchten, dass eine andere Sitzung die Zeile lesen kann, während diese spezielle Abfrage ausgeführt wird ...

Wenn Sie SELECT in eine Transaktion einschließen, während Sie den Sperrhinweis WITH (XLOCK, READPAST) verwenden, erhalten Sie die gewünschten Ergebnisse. Stellen Sie einfach sicher, dass diese anderen gleichzeitigen Lesevorgänge NICHT WITH (NOLOCK) verwenden. Mit READPAST können andere Sitzungen dasselbe SELECT ausführen, jedoch in anderen Zeilen.

BEGIN TRAN
  SELECT *
  FROM <tablename> WITH (XLOCK,READPAST) 
  WHERE RowId = @SomeId

  -- Do SOMETHING

  UPDATE <tablename>
  SET <column>=@somevalue
  WHERE RowId=@SomeId
COMMIT
ewoo
quelle
2

Frage - Ist dieser Fall nachweislich das Ergebnis einer Sperreneskalation (dh wenn Sie mit dem Profiler nach Sperreneskalationsereignissen suchen, ist dies definitiv der Grund für die Blockierung)? In diesem Fall gibt es eine vollständige Erklärung und eine (ziemlich extreme) Problemumgehung, indem ein Ablaufverfolgungsflag auf Instanzebene aktiviert wird, um eine Eskalation der Sperren zu verhindern. Siehe http://support.microsoft.com/kb/323630 Trace-Flag 1211

Dies wird jedoch wahrscheinlich unbeabsichtigte Nebenwirkungen haben.

Wenn Sie eine Zeile absichtlich sperren und über einen längeren Zeitraum sperren, ist die Verwendung des internen Sperrmechanismus für Transaktionen nicht die beste Methode (zumindest in SQL Server). Die gesamte Optimierung in SQL Server ist auf kurze Transaktionen ausgerichtet - einsteigen, aktualisieren, aussteigen. Das ist in erster Linie der Grund für die Eskalation von Sperren.

Wenn Sie also eine Zeile über einen längeren Zeitraum "auschecken" möchten, verwenden Sie anstelle der Transaktionssperre am besten eine Spalte mit Werten und eine einfache alte Aktualisierungsanweisung, um die Zeilen als gesperrt zu kennzeichnen oder nicht.

onupdatecascade
quelle
Einverstanden, obwohl ich lieber einen optimistischen Sperransatz für die Erstellung von Zeilenversionen wählen möchte , wie dies in ORMs / Persistenz-Layern wie Hibernate der Fall ist , siehe: codippa.com/… Dies setzt eine kontrollierte Umgebung voraus, in der Aktualisierungen über eine bestimmte Anwendung erfolgen. oder dass mehrere Anwendungen denselben Ansatz verfolgen. Dieser Artikel behandelt die meisten Szenarien, einschließlich des spezifischen SQL Server-Datentyps "Rowversion": simple-talk.com/sql/t-sql-programming/…
Kamal
2

Anwendungssperren sind eine Möglichkeit, Ihre eigenen Sperren mit benutzerdefinierter Granularität zu rollen und gleichzeitig eine "hilfreiche" Eskalation von Sperren zu vermeiden. Siehe sp_getapplock .

Constantin
quelle
App-Sperren helfen leider nicht immer, wenn es um Deadlock-Probleme geht. Unabhängig davon, was Sie mit sp_getapplock sperren, müssen Sie beim tatsächlichen Ändern von Datenbankeinträgen damit rechnen, dass die Engine aufgrund von Kollisionen mit Seiten- oder Tabellensperren Zeilen sperrt und versehentlich nicht verwandte Zeilen sperrt bei gleichzeitigen Transaktionen. Deaktivieren Sie am besten die Sperreneskalation und geben Sie exklusive Zeilensperrhinweise an. Sperren Sie die Zeilen in einer definierten Sperrreihenfolge, um Deadlocks so weit wie möglich zu vermeiden.
Triynko
Ich würde mich lieber für einen optimistischen Sperransatz für die Erstellung von Zeilenversionen entscheiden, wie dies in ORMs / Persistenz-Layern wie Hibernate der Fall ist (siehe: codippa.com/…). Dies setzt eine kontrollierte Umgebung voraus, in der Aktualisierungen eine bestimmte Anwendung durchlaufen oder mehrere Anwendungen verfolgen den gleichen Ansatz. Dieser Artikel behandelt die meisten Szenarien, einschließlich des spezifischen SQL Server-Datentyps "Rowversion" und Ihres eigenen Vorschlags für sp_getapplock
Kamal,
1

Versuchen Sie es mit:

SELECT * FROM <tablename> WITH ROWLOCK XLOCK HOLDLOCK

Dies sollte die Sperre exklusiv machen und für die Dauer der Transaktion halten.

RMorrisey
quelle
(Rowlock, Xlock, Holdlock) blockiert auch andere Zeilen.
Tangens
Gibt es eine Möglichkeit, zu verhindern, dass andere Zeilen blockiert werden? Ich habe momentan keine SQL Server-Instanz vor mir, mit der ich sie testen kann. Vielleicht UPDLOCK XLOCK HOLDLOCK?
RMorrisey
(updlock, xlock) sind inkompatible Hinweise.
Tangens
Versuchen Sie dann einfach UPDLOCK HOLDLOCK?
RMorrisey
(Updlock, Holdlock) blockiert auch andere Zeilen.
Tangens
1

Gemäß diesem Artikel besteht die Lösung darin, den WITH-Hinweis (REPEATABLEREAD) zu verwenden.

erikkallen
quelle
Schöner Artikel, danke. Jetzt verstehe ich die Dinge etwas besser. Leider blockiert der Hinweis (repeatableread) keine zweite Auswahl derselben Zeile.
Tangens
tangens: Warum denkst du, dass es sollte?
RBarryYoung
Weil das das Verhalten ist, nach dem ich suche.
Tangens
Ja, aber warum sollten die von Ihnen verwendeten Einstellungen Ihrer Meinung nach dieses bestimmte Verhalten aufweisen?
RBarryYoung
6
Das glaube ich nicht. Ich suche nach einer Lösung, die mir das gewünschte Verhalten gibt.
Tangens
1

Überprüfen Sie alle Ihre Abfragen erneut. Möglicherweise haben Sie eine Abfrage, die ohne ROWLOCK / FOR UPDATE-Hinweis aus derselben Tabelle ausgewählt wurde, in der Sie SELECT FOR UPDATE haben.


MSSQL eskaliert diese Zeilensperren häufig zu Sperren auf Seitenebene (selbst Sperren auf Tabellenebene, wenn Sie keinen Index für das Feld haben, das Sie abfragen). Weitere Informationen finden Sie in dieser Erklärung . Da Sie nach FOR UPDATE fragen, kann ich davon ausgehen, dass Sie eine Robustheit auf Transacion-Ebene (z. B. Finanzen, Inventar usw.) benötigen. Der Rat auf dieser Website gilt also nicht für Ihr Problem. Es ist nur eine Einsicht, warum MSSQL Sperren eskaliert .


Wenn Sie bereits MSSQL 2005 (und höher) verwenden, sind diese MVCC-basiert. Ich denke, Sie sollten kein Problem mit der Sperre auf Zeilenebene haben, wenn Sie den ROWLOCK / UPDLOCK-Hinweis verwenden. Wenn Sie jedoch bereits MSSQL 2005 und höher verwenden, versuchen Sie, einige Ihrer Abfragen zu überprüfen, die dieselbe Tabelle abfragen, die Sie FOR UPDATE möchten, wenn sie Sperren eskalieren, indem Sie die Felder in ihrer WHERE-Klausel überprüfen, wenn sie einen Index haben.


PS
Ich benutze PostgreSQL, es verwendet auch MVCC haben FOR UPDATE, ich stoße nicht auf das gleiche Problem. Sperreneskalationen werden von MVCC gelöst. Daher wäre ich überrascht, wenn MSSQL 2005 weiterhin Sperren für Tabellen mit WHERE-Klauseln eskalieren würde, die keinen Index für ihre Felder haben. Wenn dies (Sperreneskalation) bei MSSQL 2005 immer noch der Fall ist, versuchen Sie, die Felder in den WHERE-Klauseln zu überprüfen, wenn sie einen Index haben.

Haftungsausschluss: Meine letzte Verwendung von MSSQL ist nur Version 2000.

Michael Buen
quelle
Danke für den Link zum Artikel. Ich habe einen Junit-Test geschrieben, der genau das tut, was ich brauche, und ich kann die fehlenden oder eskalierten Sperren mit nur wenigen Anweisungen reproduzieren. So kann ich garantieren, dass es keine Mischung von Abfragen mit und ohne ROWLOCK gibt.
Tangens
1

Sie müssen die Ausnahme zum Zeitpunkt des Festschreibens behandeln und die Transaktion wiederholen.


quelle
1

Ich habe das Rowlock-Problem auf ganz andere Weise gelöst. Mir wurde klar, dass SQL Server eine solche Sperre nicht zufriedenstellend verwalten konnte. Ich habe mich entschieden, dies aus programmatischer Sicht mithilfe eines Mutex zu lösen ... waitForLock ... releaseLock ...

jessn
quelle
4
Das funktioniert, solange nur ein Server die Datenbank aktualisieren muss.
Andrew Swan
0

Haben Sie READPAST ausprobiert?

Ich habe UPDLOCK und READPAST zusammen verwendet, um eine Tabelle wie eine Warteschlange zu behandeln.

Gratzy
quelle
Ich habe es versucht, aber dann findet eine zweite Auswahl den Datensatz nicht. Das ist nicht das Verhalten, das ich suche. Ich möchte, dass die zweite Auswahl blockiert wird, bis die erste seine Transaktion beendet.
Tangens
0

Wie wäre es, wenn Sie zuerst versuchen würden, ein einfaches Update für diese Zeile durchzuführen (ohne wirklich Daten zu ändern)? Danach können Sie mit der Zeile fortfahren, in der die Aktualisierung ausgewählt wurde.

UPDATE dbo.Customer SET FieldForLock = FieldForLock WHERE CustomerID = @CustomerID
/* do whatever you want */

Bearbeiten : Sie sollten es natürlich in eine Transaktion einschließen

Bearbeiten 2 : Eine andere Lösung besteht darin, die Isolationsstufe SERIALIZABLE zu verwenden

Vladimir
quelle
Diese Lösung ist die gleiche wie zuvor von Feu am 14. Juni 2011. Keine Punkte für Sie.
Barrypicker