Sugiro enfileirar todas as ações SQL de vários threads em alguma estrutura de dados intermediária e, em seguida, colocar no banco de dados a partir de um único thread. É possível ter estruturas intermediárias seguras para threads como
ConcurrentHashMap
, ConcurrentLinkedQueue
ou você pode apenas sincronizar ao trabalhar com ele. Dessa forma, você nem precisa iniciar a transação com antecedência. Os dados pendentes podem ser menos seguros, mas presumo que eles não sejam muito mais seguros no banco de dados enquanto a transação ainda não for confirmada.
Claro, isso só pode funcionar se você não tiver
select
instruções que selecionam dados de transação não confirmados da mesma transação. Livrar-se de tais consultas de uma forma ou de outra pode exigir um redesenho. Use
CountDownLatch
para detectar quando todos os dados estão prontos e o encadeamento de gravação do banco de dados deve iniciar sua ação. Se isso nunca acontecer, use o padrão de reator para o encadeamento de gravação do banco de dados.