Open tkrafael opened 1 year ago
@tkrafael sim claro que tem, uma das formas seria por usar transações pra tornar a operação SELECT e INSERT atômica. Uma vez dentro de uma transação, você pode bloquear o registro específico que você deseja atualizar até que aquelaa transação seja confirmada ou revertida por exemplo ficaria assim:
using (var transaction = connection.BeginTransaction()) { try { // Aqui fica o código para SELECT e INSERT/UPDATE transaction.Commit(); } catch { transaction.Rollback(); throw; } }
Outra opção seria com Bloqueio Explícito mas pelo q eu saiba acho que isso só é válido com MySql. Aí você pode usar SELECT ... FOR UPDATE para bloquear explicitamente os registros que você está visualizando para atualização posterior. Isso garantirá que nenhum outro processo possa atualizar o mesmo registro até que você libere o bloqueio (que acontece automaticamente no final da transação) seria uma boa abordagem eu acho.
Outra opção é usar funções de banco de dados que realizam operações condicionais de forma atômica. Por exemplo, ao invés de fazer um SELECT e depois um INSERT ou UPDATE baseado nisso, você pode usar uma única query que faz ambas as operações condicionalmente.
https://github.com/fredfmiranda/TesteS3SQS/blob/f1af930c33819d4b2b3ead9f20294976f4872caa/MySqlDatabaseManager.cs#L21
Nesse método, ocorre um select e depois um insert com gerenciamento de duplicate key. Ocorre que caso haja um tratamento do mesmo registro ao mesmo tempo, haverá uma corrida crítica onde o select pra obter informação vem vazio, mas no momento do insert, o registro pode já existir. Há alguma forma de resolver esse problema?