Я разрабатываю сервер, который должен получать ночные отчеты от сотен подразделений. В настоящее время отчеты представляют собой зашифрованные csv-файлы. В общей сложности отчеты должны составлять от 500 000 до 1 000 000 записей каждый день, которые сохраняются в базе данных для последующего использования.
Я создал набор PreparedStatements для каждой передачи. Эти операторы используются для пакетирования 50 записей перед выполнением и фиксацией. Каждая запись может вызывать до 20 вставок базы данных. Все хорошо, когда передачи ставятся в очередь и обрабатываются один за другим.
Когда я пытался сделать это одновременно, я заметил, что разные потоки получили одинаковые экземпляры PreparedStatements. Это вызвало следующую проблему
- Несколько потоков добавили операторы в один пакет
- Пакеты выполнялись, когда один из потоков решил, что пришло время сделать это
- Коммит был вызван, когда база данных не соответствовала ограничениям, поскольку некоторые потоки не успели использовать некоторые операторы
Вопрос: Есть ли способ заставить подготовленный оператор быть созданным вместо повторного использования существующего из кэша операторов?
Если нет лучшего способа справиться с ситуацией, чем
- создание отдельного источника данных для пакетов, у которых нет пула операторов / соединений
- удаление ограничений из базы данных; порядок вставки больше не имеет значения
- принудительная последовательная обработка
Редактировать: попытка выяснить проблему
Пусть будут темы T1 и T2.
Пусть будут подготовлены утверждения S1 и S2.
Пусть будут партии B1 и B2.
Каждый раз, когда используется S1, он добавляется к B1. Каждый раз, когда используется S2, он добавляется в B2.
При фиксации S1 должен быть зафиксирован до S2 для ограничения внешнего ключа.
Проблема возникает, когда
- T1 радостно обрабатывает передачи
- T2 обрабатывает передачи невинно
- T1 использует оператор S1, добавляя s1a к пакету B1, содержащему s1a
- T1 использует оператор S2, добавляя s2a в пакет B2, содержащий s2a
- T1 решает, что пора совершать
- T1 фиксирует партию B1, содержащую s1a
- T2 использует S1, добавляя s1b в пакет B1, содержащий s1b
- T2 использует S2, добавляя s2b к партии B2, содержащей s2a, s2b
- T1 фиксирует партию B1, содержащую s2a, s2b
- База данных говорит «нет, нет», поскольку s2b передается перед s1b, что запрещено во внешнем ключе.
Этого можно избежать с помощью ручной синхронизации, а также указать в ответах, но тогда мне все равно придется отдельно отслеживать размер каждого пакета вместо применения локальной логики для каждого потока.