Транзакции всем хороши, но под нагрузкой приводят к замедлению работы приложения и иногда, если не правильно работать с запросами к deadlock-м.
Можно создать отдельную таблицу в которую записывать запросы пользователей на получение ресурса, например так:
идентификатор пользователя, идентификатор ресурса, статус заявки (в очереди, обработана, отклонена), дата и время заявки с точностью до миллисекунд (ну или числовое поле с автонумерацией).
При нажатии на "купить товар" операция выполняется в два шага, первый шаг - помещаем заявку пользователя в эту таблицу. (несколько пользователей могут придти за одним ресурсом и приоритет будет у того кто пришел первым)
Таблица нужна, чтобы не накладывать блокировок на таблицы БД (блокировки могут быть из-за открытой транзакции)
Далее второй шаг - запускаем процедуру получения статуса заявки (она должна вернуть ответ получил пользователь свой ресурс или нет, т.е. обработана его заявка успешно или отклонена).
Обработка заявок - это отдельный серверный процесс, он берет заявки по очереди поступления и обрабатывает (изменяет состояние ресурса в БД и состояние заявки) до тех пор пока у выбранного ресурса хватает количества, все пользователи которым не хватило ресурса получают сообщение о невозможности получить ресурс.