2015-03-03 7 views
0

У меня есть веб-приложение (JSP/Tomcat on MySQL), которое предлагает функциональные возможности для заполнения онлайн-контракта и должно возвращать в конце уникальный счетчик или идентификатор для клиента в качестве протокола для договора. Если два клиента подтверждают форму одновременно, SELECT MAX (COUNTER) на db не защищает от конфликтов идентификаторов.Получить уникальный идентификатор от MySQL

У меня есть таблица, которая отслеживает следующий идентификатор доступных для клиента для каждого типа контракта:

CONTRACT_TYPE COUNTER 
A     21 
B     13 

Метод, чтобы получить следующий идентификатор:

public int getNewCounter(String contractType) { 
    query1 = SELECT (COUNTER + 1) AS NEW_COUNTER from mytable WHERE CONTRACT_TYPE = 'A' 
    query2 = UPDATE mytable SET COUNTER = <counter_returned_on_previous> WHERE CONTRACT_TYPE = 'A' 
    return NEW_COUNTER; 
} 

Это возникает проблема, что одновременные клиенты могут получить один и тот же идентификатор, если они отправят форму в тот же момент, и этого я бы хотел избежать.

Другими словами с 2 одновременных клиентов это может произойти:

client1-query1 
client1-query2 
client2-query1 
client2-query2 

, что это правильное поведение, но я могу также это:

client1-query1 
client2-query1 
client1-query2 
client2-query2 

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

Большое спасибо!

+0

'UPDATE туЬаЫе SET счетчик = счетчик + 1 WHERE contract_type =«A'' – Alex

+0

* уникальный СЧЕТЧИК присваивается каждому клиенту * почему счетчик должен быть уникальным? – Alex

+0

Поскольку счетчик представляет номер протокола по договору – Jacor99

ответ

0

Вам не нужно 2 запросов.

Решение также просто, как:

UPDATE table1 SET counter = counter+1 WHERE contract_type = 'A'; 

Вы можете играть с fiddle

0

Я ответил на мой собственный вопрос. Задача генерирования уникального идентификатора в MysSQL в параллельной среде можно осуществить 2 способами:

1) Использование таблицы InnoDB с сделки и SELECT FOR UPDATE режима блокировки:

START TRANSACTION (or set autocommit to 0);  
SELECT COUNTER FROM mytable WHERE contract_type = 'A' FOR UPDATE; 
UPDATE mytable SET COUNTER = COUNTER + 1 WHERE contract_type = 'A';  
COMMIT; 

A SELECT. .. FOR UPDATE читает последние доступные данные, устанавливая эксклюзивные блокировки для каждой прочитанной строки.

2) С помощью одного доступа к таблице:

UPDATE myTable SET COUNTER = LAST_INSERT_ID(COUNTER + 1) WHERE contract_type = 'A'; 
SELECT LAST_INSERT_ID(); 

моды здесь является то, что оператор SELECT, просто извлекает информацию идентификатора (специфичная для текущего соединения). Он не имеет доступа к таблице!

Источник: http://dev.mysql.com/doc/refman/5.5/en/innodb-locking-reads.html

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