Синхронизированное выполнение хранимой процедуры в mysql

У меня есть хранимая процедура в 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 ;

Таким образом, если два приложения вызывают хранимую процедуру одновременно, задача должна быть синхронизирована.

а. Но Start TRANSACTIONи COMMITНЕ синхронизировали выполнение.

б. И LOCK TABLES tableA нельзя использовать в хранимой процедуре для обеспечения синхронизации.

в.Я попытался синхронизировать вызов хранимой процедуры на уровне приложения. Я использовал

boost_interprocess scoped_lock lock();

Это прекрасно работало в boost 1.41.

Но мьютекс межпроцессной блокировки не поддерживается в библиотеке boost 1.34, которая доступна в моем случае.

Есть ли способ синхронизировать раздел кода хранимой процедуры таким образом, чтобы при одновременном выполнении двух вызовов один блокировался до того, как будет выполнен другой?

(добавлено следующее) отредактированный код: чтобы дать представление о том, что я пытаюсь выполнить в синхронизированном блоке хранимой процедуры.

Он получает последний назначенный идентификатор, увеличивает его на единицу и проверяет, не используется ли он для какой-либо другой записи «имя». Когда действительный идентификатор найден, обновите последнюю назначенную таблицу записей идентификаторов, а затем свяжите ее с заданным «именем».

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 ;
8
задан Flying Dutchman 12 May 2012 в 11:31
поделиться