как избежать проблемы параллелизма (взаимоблокировки) после хука вставки? - PullRequest
0 голосов
/ 05 июля 2019

Когда метод afterinsert вызывается двумя запросами одновременно, генерируется эта ошибка

ERROR 2019-07-03 11:59:18,152 [ajp-bio-8109-exec-34040] util.JDBCExceptionReporter: Deadlock found when trying to get lock; try restarting transaction
ERROR 2019-07-03 11:59:18,152 [ajp-bio-8109-exec-34037] util.JDBCExceptionReporter: Cannot add or update a child row: a foreign key constraint fails (`rcroadweb`.`inventory_entry_order`, CONSTRAINT `FKDD86A2DE546E2B52` FOREIGN KEY (`order_id`) REFERENCES `inventory_order` (`id`))
ERROR 2019-07-03 11:59:18,173 [ajp-bio-8109-exec-34037] events.PatchedDefaultFlushEventListener: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at invoice.InventoryEntry$_afterInsert_closure1.doCall(InventoryEntry.groovy:105)
    at invoice.InventoryEntry.afterInsert(InventoryEntry.groovy:101)
    at org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener.onApplicationEvent(AbstractPersistenceEventListener.java:46)
    at registration.RegistrationService$_createInvoices_closure11.doCall(RegistrationService.groovy:414)
    at registration.RegistrationService.createInvoices(RegistrationService.groovy:316)
    at registration.RegistrationService$_completeSale_closure14.doCall(RegistrationService.groovy:653)
    at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:686)

Класс домена InventoryEntry после ловушки вставки выглядит следующим образом. Ошибка в этом месте.

void afterInsert(){
        if (this.metaClass.hasMetaProperty('unsavedOrders')){
            withNewSession{ session ->
                this.unsavedOrders.each{ order ->
                    InventoryEntryOrder.create(this, order)
                }
                session.flush()
            }
            this.unsavedOrders.clear()
        }
    }

У меня нет большого опыта работы с проблемой параллелизма, поэтому я ценю любую помощь экспертов. Моя догадка - использовать блокировку, чтобы за один раз в этот метод вошел только 1 поток. Спасибо за идеи!

...