Ich habe eine gespeicherte Prozedur in mysql das ist eine Aufgabe, die so synchronisiert werden muss, dass, wenn zwei Anwendung ruft die gespeicherte Prozedur, nur einer kann auf einen Abschnitt des Codes zugreifen, um die Aufgabe auszuführen Der andere wird so lange blockiert, bis der erste die Aufgabe beendet hat.Synchronisierte gespeicherte Prozedur Ausführung in Mysql
DELIMITER $$
CREATE PROCEDURE SP_GEN_ID(IN NAME VARCHAR(20))
BEGIN
DECLARE maxLen int default 0;
START TRANSACTION;
#the section of code that needs to be synchronized
COMMIT
END;
$$
DELIMITER ;
Also, wenn zwei Anwendungen die gespeicherte Prozedur gleichzeitig aufrufen, muss die Aufgabe synchronisiert werden.
a. Aber Starten TRANSACTION und COMMIT synchronisiert nicht die Ausführung.
b. Und LOCK TABLES tableA kann nicht in gespeicherten Prozedur verwendet werden, um die Synchronisierung zu gewährleisten.
c. Ich habe versucht, den Aufruf der gespeicherten Prozedur auf Anwendungsebene zu synchronisieren. Ich verwendete
boost_interprocess scoped_lock lock();
Es funktionierte völlig in Ordnung im Boost 1,41
Aber Mutex Inter Verriegelung wird nicht in der Boost-1,34-Bibliothek unterstützt, das ist das, was in meinem Fall zur Verfügung steht.
Gibt es eine Möglichkeit, den Codeabschnitt der gespeicherten Prozedur so zu synchronisieren, dass bei zwei gleichzeitig ausgeführten Anrufen blockiert wird, bevor der andere ausgeführt wird?
(hinzugefügt die folgenden) bearbeitet Code: um eine Idee zu geben, was ich im synchronisierten Block der gespeicherten Prozedur ausführen möchte.
Er erhält die zuletzt zugewiesene ID, erhöht sie um eins und prüft, ob sie nicht für einen anderen 'Name'-Datensatz verwendet wird. Wenn eine gültige ID gefunden wird, aktualisieren Sie die zuletzt zugewiesene ID-Datensatztabelle und ordnen Sie diese dann dem angegebenen 'Namen' zu.
DELIMITER $$
CREATE PROCEDURE SP_GEN_ID(IN NAME VARCHAR(20))
BEGIN
DECLARE maxLen int default 0;
START TRANSACTION;
#the section of code that needs to be synchronized
SELECT lastid into lastgenerated FROM DB_last_id WHERE key = 'NAME_ID';
findid_loop:
LOOP
set lastid = lastid + 1;
#this is to check whether it was assigned with someother name before.
IF not EXISTS (SELECT 1 FROM user_name_id WHERE name_id = lastgenerated) then
set nameid = lastgenerated;
set found = true;
LEAVE findid_loop;
END IF;
#for loop limit check
IF (counter < loopLimit) then
set counter = counter + 1;
ITERATE findid_loop;
ELSE
#reached the limit and not found.
LEAVE findid_loop;
END IF;
END LOOP findid_loop;
#if a valid id, update last id and assign to name.
IF (found) THEN
#update the id.
update DB_last_id set lastid = nameid where key = 'NAME_ID';
insert into user_name_id values (nameid ,name);
ELSE
#return an empty string for the application to take action on the failure.
set nameid = '';
END IF;
#end transaction here.
COMMIT
END;
$$
DELIMITER ;
Welche Speicher-Engine verwenden Ihre Tabellen?Sie müssen InnoDB sein, damit Transaktionen/Sperren funktionieren. – eggyal
Die Speicher-Engine ist InnoDB für die Tabellen. Aber es scheint immer noch nicht zu funktionieren. Um dies zu überprüfen, habe ich geschlafen (15), um direkt nach START TRANSACTION auf 15 Sekunden zu warten. Wenn ich die gespeicherte Prozedur gleichzeitig anrufe, scheinen beide nach 15 Sekunden wieder herauszukommen. Wenn START TRANSACTION die Synchronisierung sicherstellt, sollte der zweite Aufruf der gespeicherten Prozedur nach 30 Sekunden oder so enden. Recht? (15 Sekunden für den ersten Anruf, um zu überholen, dann geht der zweite in die START TRANSACTION und schläft für 15 Sekunden) –
Was genau ist der Code, den Sie synchronisieren möchten? Wenn Sie möchten, dass SQL-Operationen nur atomar sind, sollte dies durch Ausführen in einer Transaktion erreicht werden. Wenn Sie einen anderen Status wie Systemvariablen beeinflussen, müssen Sie eine Sperre für eine Tabelle/einen Datensatz erhalten, die diesem Zweck zugewiesen sind. Und das Fehlen einer Verzögerung bei Ihrem zweiten Anruf ist nicht notwendigerweise ein Hinweis darauf, dass die Sperre fehlgeschlagen ist (es könnten beispielsweise Cache-Probleme auftreten, die den zweiten Anruf schneller ausführen als der erste, oder der zweite Anruf könnte eine andere Ausführung annehmen Weg zum ersten). Bitte geben Sie den vollständigen Code an. – eggyal