Кажется, я вспоминаю эту проблему из-за многолетней работы над базой данных INGRES. В те дни не было никаких последовательностей, поэтому лучшие умы INGRES дня приложили немало усилий, чтобы найти лучшее решение для масштабирования этой проблемы. Мне посчастливилось работать вместе с ними, так что, хотя мой разум ничтожно мал, чем у любого из них, близость = остаточный аффект, и я кое-что сохранил. Это была одна из вещей. Дай посмотреть, смогу ли я вспомнить.
1) for each counter you need row in a work table.
2) each time you need a number
a) lock the row
b) update it
c) get its new value (you use returning for this which I avoid like the plague)
d) commit the update to release your lock on the row
Причиной коммита является попытка получить некоторую масштабируемость. Всегда будет ограничение, но вы не сериализуетесь для получения номера в течение любого периода времени.
В мире оракулов мы улучшили бы ситуацию, используя функцию, определенную как AUTONOMOUS_TRANSACTION, чтобы получить следующий номер. Если вы думаете об этом, это решение требует, чтобы пробелы были разрешены, что вы сказали, что все в порядке. Отправляя обновление номера независимо от основной транзакции, вы получаете масштабируемость, но вводите зазор.
Вы должны будете принять тот факт, что ваша масштабируемость резко снизится в этом сценарии. Это связано как минимум с двумя причинами:
1) последовательность update / select / commit делает все возможное, чтобы уменьшить время, в течение которого строка KEY блокируется, но она все еще не равна нулю. Под большой нагрузкой вы будете сериализованы и в конечном итоге будете ограничены.
2) вы делаете каждый ключ. Фиксация - это дорогостоящая операция, требующая много действий по управлению памятью и файлами со стороны базы данных. Это также ограничит вас.
В конце концов, вы, вероятно, ожидаете снижения нагрузки на три транзакции на три или более порядков, поскольку последовательности не используются. Я основываю это на своем прошлом опыте.
Но если ваш клиент этого требует, что вы можете сделать правильно?
Удачи. Я не проверял код на наличие синтаксических ошибок, я оставляю это вам.
create or replace function get_next_key (key_name_p in varchar2) return number is
pragma autonomous_transaction;
kev_v number;
begin
update key_table set key = key + 1 where key_name = key_name_p;
select key_name into key_name_v from key_name where key_name = key_name_p;
commit;
return (key_v);
end;
/
show errors