Locking mit Select for Update

Locking mit Select for Update

am 11.04.2007 19:37:28 von Yaya Diawara

Hi,

Ich moechte mit 2 Prozessen den Inhalt einer Tablelle bearbeiten und dabei
vermeiden dass den zwei Prozessen dieselben eintraege zugeteilt werden. Es
sollte auch kein Problem darstellen wenn die zwei Prozesse 'gleichzeitig'
starten.

Die Struktur der Tabelle sieht folgendermassen aus:

Test_Table (InnoDB)
=============
ID int
ProzessID INT,
Processed TINYINT


Dabei soll der erster prozess eine bestimte Anzahl von Eintraegen
reservieren, bearbeiten und dann als Processed markieren.
Der Zweite soll dann die nexten 10 eintraegen bearbeiten.
Ich habe das folgendermassen versucht:

1) select ID from Test_Table where processed is NULL for update
2) Update Test_Table SET processed=1 where ID IN obiger liste

Ich habe das gefuehl Mysql lockt die ganze Tabelle anstatt nur die rows zu
locken die bettrofen sind.

Viellecht kann mir Jemand eine bessere methode vorstellen.

Danke im Vorraus.

PS: Mysql Version ist 5.1.15 Beta OS is Suse10


Yaya.

Re: Locking mit Select for Update

am 11.04.2007 20:07:05 von Axel Schwenke

"Yaya Diawara" wrote:
>
> Ich moechte mit 2 Prozessen den Inhalt einer Tablelle bearbeiten und dabei
> vermeiden dass den zwei Prozessen dieselben eintraege zugeteilt werden. Es
> sollte auch kein Problem darstellen wenn die zwei Prozesse 'gleichzeitig'
> starten.
>
> Die Struktur der Tabelle sieht folgendermassen aus:
>
> Test_Table (InnoDB)
> =============
> ID int
> ProzessID INT,
> Processed TINYINT
>
> Dabei soll der erster prozess eine bestimte Anzahl von Eintraegen
> reservieren, bearbeiten und dann als Processed markieren.
> Der Zweite soll dann die nexten 10 eintraegen bearbeiten.
> Ich habe das folgendermassen versucht:
>
> 1) select ID from Test_Table where processed is NULL for update
> 2) Update Test_Table SET processed=1 where ID IN obiger liste

Ist das ein Wettbewerb, eine Anwendung für SELECT ... FOR UPDATE zu
finden?

> Viellecht kann mir Jemand eine bessere methode vorstellen.

Mach eine Spalte processor INT, wo die Prozeß-Id des Bearbeitungs-
prozesses drin steht. Setz die für neue Einträge auf NULL. Dann
reserviert sich jeder Bearbeiter ein paar Einträge per

UPDATE ... SET processor= WHERE processor IS NULL LIMIT 10

anschließend kann er die bearbeiten (er erkennt "seine" daran, daß
seine PID in processor steht).


Und warum eigentlich in Batches a 10 Stück? Einzeln ist doch viel
hypscher: UPDATE ... SET processor=, id=LAST_INSERT_ID(id) WHERE
processor IS NULL LIMIT 1. Anschließend liefert SELECT LAST_INSERT_ID()
die id seines Datensatzes. Bzw. gleich eingesetzt:

SELECT ... FROM weitere_job_daten WHERE job_id = LAST_INSERT_ID()


XL