![]() |
Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhindern
Hallihallo!
Ich steh grad ein wenig auf dem Schlauch. Ich habe clients, die auf eine MSSQL-tabelle zugreifen. Da drin befindet sich ein Tupel, der einen Integer-Wert beinhaltet. Die Clients sollen sich diesen Wert holen und ihn um 1 erhöhen. Das darf aber nicht gleiczeitig geschehen, weil evtl. sonst beide den gleichen wert holen, und beide ihn um 1 erhöhen. also letztendlich um 2 ;-) Ich habe keine ahnung,m wie ich das mit den beiden syncronen zugriffen simulieren soll. Gibt es eine möglichkeit, den gleichzeitigen zugriff schon mit einem SQL-Befehl zu verhindern? Oder reicht es schon, den befehl in einen BEGIN TRAN / COMMIT TRAN -Block einzuschließen? Erstmal habe ich es jetzt über eine paar umwege gelöst, was aber eher provisorisch ist. Vielen dank schonmal Jens |
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
Was ist denn Sinn dieses Integerwertes. In welchem Kontext wird der denn geändert.
Dem Server kannst du nicht sagen "Junge, jetzt pause mal bis du mit mir fertig bist, und dann bedienst du den nächsten Client". Das ist ja auch nicht Sinn eines SQL-Servers. Der Lösungsweg führt wahrscheinlich über Transaktionen. Die sind erst mal für die anderen Clients unsichtbar, bis du ein Commit an die DB schickst. |
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
Aber genau das muss ich ihm sagen.
Ein integerwert darf nicht zweimal an einen client gehen. Sozusagen ein GetAndInc eines Wertes. Eine geschlossene Transaktion, die den Tupel solange sperrt, bis dieser fertig ausgelesen und incrementiert ist. Ich weiss, das es nicht der sinn einen SQL servers ist ;-) Ich glaube ich beschäftige mich mal mit dem sperren von tabellen ;-) Danke, jens |
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
Muss der Integer Wert in einer Tabelle gespeichert sein. Vielleicht kannst du auch über globale Variablen gehen ( @@Wert ). Habs aber noch nie probiert.
|
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
Hmm.. nee.. das funzt so net.
was ist,wenn ich folgenden sql befehl habe: BEGIN TRAN SELECT wert FROM t_werte where bezeichner like 'testwert' with (xlock) UPDATE t_werte SET wert=wert+1 bezeichner like 'testwert' COMMIT TRAN kann ein anderer Client zwischen dem select und Update den wert ebenfalls holen? oder ist der dann gespeert? Ist der für die komplette transaktion gesperrt? das wäre die möglichkeit, die ich eigendlich suche. gruss jens |
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
durch das update setzt du nur in deiner Transaktion einen neuen Wert. Also auch nach dem Update liest ein anderer User nicht den für dich aktuellen Wert, sondern den gleichen wie du auch gelesen hast. Erst durch das Commit wird die Tabelle t_werte endgültig aktualisiert, und auch die anderen Benutzer kriegen davon mit.
|
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
Hi ihr,
kleiner Nachtrag: mit dem Befehl BEGIN TRAN SELECT wert FROM t_werte where bezeichner like 'testwert' with (rowlock) UPDATE t_werte SET wert=wert+1 bezeichner like 'testwert' COMMIT TRAN klappt das einwandfrei. während der transaktion ist die zeile gesperrt und es kommt nicht vor, das andere clients den selben wert auslesen, ohne das er hochgezählt wird. Gruss Jens |
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
Zitat:
die Tabelle eingefügt werden muss. Meines Wissens schlägt dann das UPDATE fehl. Gruß, Christoph |
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
hi pertzschc,
in dem fall würde ich warscheinlich anstatt einem RowLock ein XLock nehmen. sowas in der art wie: begin tran insert into TestTabelle with (XLOCK) (testwert) VALUES (1) commit tran Allerdings weiss ich nicht, wie sich das ding dann in einem fehlerfall verhält. müßte man mal ausprobieren. //edit: klammern vergessen |
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
Brauchst du vielleicht einen Generator ?
Ein Generator liefert einen eindeutigen Integerwert zurück. Dabei wird sichergestellt, dass kein anderer Client den gleichen Wert erhalten kann. MSSQL unterstützt von sich aus keine Generatoren (Firebird kann's aber ![]() diese lassen sich aber nachbauen. Zuerst die Tabelle Generators:
SQL-Code:
Dann noch folgende SP:
CREATE TABLE [dbo].[Generators] (
[IdGenerator] [varchar] (20) NOT NULL , [CurrentValue] [int] NOT NULL ) ON [PRIMARY] GO
SQL-Code:
Create procedure generator_id ( @IdGenerator varchar(20))
as begin declare @ID integer SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRANSACTION SP_GEN_ID select @ID = CurrentValue from Generators where IdGenerator =@IdGenerator IF @@ERROR <> 0 GOTO LBL_ERROR update Generators set CurrentValue =CurrentValue + 1 where IdGenerator=@IdGenerator IF @@ERROR <> 0 GOTO LBL_ERROR COMMIT TRANSACTION SP_GEN_ID return @ID LBL_ERROR: ROLLBACK TRANSACTION SP_GEN_ID return 0 end |
Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
Cool!
Ist auch ne möglichkeit, das ganze zu lösen.Und ist eine gute Idee, das ganze in eine SP zu packen ;-) Danke. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz