Getting “Deadlock found when trying to get lock; try restarting transaction”

后端 未结 5 1754
一个人的身影
一个人的身影 2020-12-07 21:11

My Application(java spring-core) has several threads running concurrently and accessing db, I am getting exception in some peaktime

07:43:33,400 WARN  [org.         


        
5条回答
  •  佛祖请我去吃肉
    2020-12-07 21:39

    Here is an example with plain Spring and no extra frameworks.

        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); // autowired
        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); // this increases deadlocks, but prevents multiple simultaneous similar requests from inserting multiple rows
        Object o = transactionTemplate.execute(txStatus -> {
                for (int i=0; i<3; i++) {
                    try {
                        return findExistingOrCreate(...);
                    } catch (DeadlockLoserDataAccessException e) {
                        Logger.info(TAG, "create()", "Deadlock exception when trying to find or create. Retrying "+(2-i)+" more times...");
                        try { Thread.sleep(2^i*1000); } catch (InterruptedException e2) {}
                    }
                }
                return null;
        });
        if (o == null) throw new ApiException(HttpStatus.SERVICE_UNAVAILABLE, "Possible deadlock or busy database, please try again later.");
    

    Using serializable transaction isolation level is specific to my situation because it converts SELECT to SELECT ... IN SHARE MODE / SELECT ... FOR UPDATE and locks those rows. The findExistingOrCreate() is doing a lot of complicated searching for existing rows and auto-generating names and checking for bad words, etc. When many of the same request came in at the same time, it would create multiple rows. With the serializable transaction isolation level, it is now indempotent; it now locks the rows, creates a single row, and all subsequent requests return the new existing row.

提交回复
热议问题