У меня был запрос в SQL-сервер, который выглядит примерно так:Postgresql эквивалент с (XLock, уключин)
DECLARE @someIncrementalField int;
set @someIncrementalField = select max(SomeField) from SomeTable with (xlock, rowlock) where field1 = 1 and field2 = 2 and field3 = 3;
таблица SQL Server был уникальный индекс ключа на поле1, field2, field3.
Идея заключалась в том, чтобы заблокировать часть таблицы в соответствии с индексом и выбрать максимальное значение и использовать max + 1 для вставки в ту же таблицу.
Теперь я пытаюсь перейти на PostgreSql, как это сделать, это postgres? Я не могу сделать
FOR UPDATE
с агрегированным запросом на выбор. Если я сделаю
LOCK table IN ROW EXCLUSIVE MODE
будет блокировать всю таблицу или часть таблицы, которая индексируется с использованием полей?
EDIT: НЕ ДЕЛАЕТ ЭТО ДЛЯ ПОСЛЕДОВАТЕЛЬНОСТИ. У меня есть отдельное поле идентификации на столе.
EDIT 2:
id a b(date) c trace
1 1 6/1/2016 1 100001
2 1 6/1/2016 1 100002
3 1 6/1/2016 1 100003
4 1 6/1/2016 1 100004
5 1 6/1/2016 2 100001
6 1 6/1/2016 2 100002
7 1 6/1/2016 3 100001
8 1 6/1/2016 3 100002
Позволяет сказать, что это таблица, столбец трассировки вращается от 100000 - 999999. Следующая запись была (1, 6/1/2016, 1),
Я хочу, чтобы заблокировать часть таблицы, где а = 1, Ь = 6/1/2016, с = 1.
Получить максимум колонки трассировки из эта часть.
Добавить (1, 6/1/2016, 1, (макс с шага 2) + 1)
Освободить замок.
Когда это происходит, я хочу, чтобы другие вставки и обновления проходили очень хорошо в других частях таблицы.
Могу ли я создать циклическую последовательность для столбца трассировки на основе a, b и c?
EDIT 3: Я хотел бы поблагодарить a_horse_with_no_name за объяснение подхода к использованию триггера. Я многое узнал из этого. Сначала я применил ваше решение, после чего установил отладчик и пробовал некоторые другие вещи, и для меня работало следующее решение.
Я сделал что-то подобное, чтобы достичь того, что искал. Я использую расширение pldbgapi (debugger), чтобы убедиться, что он не блокирует всю таблицу, и не было никаких повторяющихся ошибок ввода.
create or replace function insert_new(IN a_in integer, IN, b_in integer, IN c_in integer)
returns integer
as
$func$
declare new_trace integer;
begin
--this locks the max value until the function ends and other concurrent inserts would wait here until the function holding the lock is done
perform trace from my_table where a=a_in and b=b_in and c=c_in order by trace desc limit 1 for update;
select trace from my_table where a=a_in and b=b_in and c=c_in into new_trace order by trace desc limit 1;
SELECT CASE WHEN new_trace IS 999999 THEN 100001 ELSE new_trace + 1 END INTO new_trace;
insert into my_table values(a, b, c, new_trace);
return query select new_trace;
end;
$func$
language plpgsql;
«* Идея заключалась в том, чтобы зафиксировать часть таблицы в соответствии с индексом и выберите максимальное значение и используйте max + 1 для вставки в ту же таблицу * «сделайте *** НЕ *** сделайте это! Он не будет масштабироваться вообще и будет работать только корректно, если вы действительно заблокируете всю таблицу. Почему, по-вашему, вам это нужно в первую очередь? Почему бы просто не использовать последовательность для генерации идентификаторов? –
Вы слышали о свойстве ['IDENTITY'] (https://msdn.microsoft.com/en-us/library/ms186775.aspx) в SQL Server. –
У меня есть поле идентификации в таблице, это инкрементное поле, о котором я говорю, должно основываться на field1, field2 (это поле даты) и поле3, и оно идет от 1 ... 999999 и снова вращается. Также не пытайтесь полностью заблокировать всю таблицу. Я пытаюсь заблокировать часть таблицы, где field1 = что-то, field2 = something и field3 = что-то, и получить максимальное значение этого инкрементного поля. – dtksmsl