2015-01-27 6 views
0

У меня такой же вопрос, как описано here, а также я думаю, что ответ https://stackoverflow.com/a/22343265/297487 - хорошее решение, но у меня есть еще один вопрос об этом ответе.Является ли этот MySQL триггером потокобезопасным?

Является ли следующий триггер (скопированный из ответа) потокобезопасным? Я имею в виду, если две параллельные записи, вставленные в таблицу, столбец «приоритет» (как описано в вопросе) имеет постоянное значение (то же значение, что и id)?

delimiter // 
drop trigger if exists bi_table_name // 

create trigger bi_table_name before insert on table_name 
for each row begin 
    set @auto_id := (SELECT AUTO_INCREMENT 
       FROM INFORMATION_SCHEMA.TABLES 
       WHERE TABLE_NAME='table_name' 
        AND TABLE_SCHEMA=DATABASE()); 
set new.priority= @auto_id; 
end; 
// 

delimiter ; 

Как мы интерпретируем предложение «для каждой строки»? Предположим, что MySQL хочет вставить две параллельные строки. Как работает этот триггер?

Одно из объяснений заключается в следующем:

MySQL блокирует таблицу и перед вставкой одной из строк (одна из параллельной записи) начинается триггер MySQL и получает текущее значение AUTO_INCREMENT, и устанавливает его в столбец «приоритет», а затем вставляет запись. После этого MySQL начинает вставлять другую запись, и тогда такая же ситуация применима к новой записи.

Другая интерпретация может быть следующим:

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

Какая из приведенных выше интерпретаций верна?

Обновление:

У меня есть следующие таблицы:

CREATE TABLE `t_file` (
     `id` bigint(20) NOT NULL AUTO_INCREMENT, 
     `name` varchar(255) COLLATE utf8_persian_ci NOT NULL, 
     `p_name` bigint(20) DEFAULT NULL, 
     PRIMARY KEY (`id`), 
     UNIQUE KEY `p_name_2` (`p_name`) 

    ) ENGINE=InnoDB AUTO_INCREMENT=206284 DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci; 

Я хочу, чтобы вставить значение p_name так же, как id, когда строка вставлена.

The trigger, который устанавливает значение p_name выглядит следующим образом (копируется из вашего кода)

delimiter $$ 
    drop trigger if exists file_p_name $$ 

    create trigger file_p_name before insert on t_file 
    for each row begin 
     set @id := (SELECT AUTO_INCREMENT 
         FROM INFORMATION_SCHEMA.TABLES 
         WHERE TABLE_NAME='t_file' 
          AND TABLE_SCHEMA=DATABASE()); 
     set new.p_name= @id; 
    end; 
    $$ 

    delimiter ; 

В нашем приложении, я окружать код, который вставляет в t_file таблицу с try catch, почти всегда все в порядке, но иногда (в параллельной вставки в t_file таблицу), я вижу следующее исключение в журнале нашего приложения:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry \'387456\' for key \'p_name_2\'' 

кажется trigger работает не так, как ожидалось, или, может быть, я ошибаюсь !!!

ответ

0

answer referred in your question был отправлен мной некоторое время назад.

В то время как в "For Each Row", The NEW является соответствующей новой строкой, вставляются в контексте. И set new.xxx применим только для этой строки, но не 'for all rows' в партия. Таким образом, столкновения не будет, и вопрос об отказе не должен возникать.

Я также ответил на аналогичный вопрос How does “for each row” work in triggers in mysql?. Просьба привести примеры, приведенные в ответе.

Обратитесь к документации:

+0

кажется ваш ОК, но я загрузил этот код в системе с одной и той же ситуацией, которая имеет много одновременного users.I проинформирует вы о результатах. – Khosro

+0

Я пытаюсь проверить выше триггер в параллельной системе, я создал уникальное ограничение для столбца «приоритет». После трех дней я видел некоторые исключения, указывающие на то, что дублирование столбца «приоритет» в указанной таблице. Так что это кажется выше триггера не является потокобезопасным и имеет некоторые проблемы в параллельной системе. – Khosro

+0

Очень плохо, что MySQL не «после триггера» для обновления строки после ее вставки. – Khosro

Смежные вопросы