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