Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhindern (https://www.delphipraxis.net/31678-gleichzeitigen-zugriff-bei-mssql-auf-einen-tupel-verhindern.html)

Zottel 12. Okt 2004 16:19


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

Jelly 12. Okt 2004 17:13

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.

Zottel 12. Okt 2004 17:53

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

Jelly 12. Okt 2004 18:22

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.

Zottel 13. Okt 2004 17:44

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

Jelly 13. Okt 2004 17:53

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.

Zottel 11. Nov 2004 18:43

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

pertzschc 21. Sep 2005 15:45

Re: Gleichzeitigen Zugriff bei MSSQL auf einen Tupel verhind
 
Zitat:

Zitat von Zottel
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.

Wie würdest Du es machen, wenn die Zeile noch nicht in der Tabelle enthalten ist, also mit INSERT erst in
die Tabelle eingefügt werden muss. Meines Wissens schlägt dann das UPDATE fehl.

Gruß,
Christoph

Zottel 21. Sep 2005 17:15

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

shmia 21. Sep 2005 17:38

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
http://www.fingerbird.de/generatorgu...erators_stored );
diese lassen sich aber nachbauen.
Zuerst die Tabelle Generators:
SQL-Code:
CREATE TABLE [dbo].[Generators] (
   [IdGenerator] [varchar] (20) NOT NULL ,
   [CurrentValue] [int] NOT NULL
) ON [PRIMARY]
GO
Dann noch folgende SP:
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

Zottel 21. Sep 2005 20:41

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