Тупик при вставке / обновлении в той же транзакции на серверах с балансировкой нагрузки - PullRequest
0 голосов
/ 24 апреля 2020

У нас часто возникают проблемы взаимоблокировки при реализации следующей функции.

1. Это реализуется как часть очереди шины nservice на 4 серверах с балансировкой нагрузки. 2. Мы делаем вставку / обновление одной и той же таблицы в одной транзакции. 3. Основным виновником является таблица учетных записей пользователей, а не хранилище аудита. 4. У нас примерно 264056 строк в таблице учетных записей пользователей. 5. Наши администраторы баз данных перестраивают индекс один раз в неделю. 6. В среднем мы запускаем эту функцию каждый день для включения / выключения для X пользователей. 7. Мы используем уровень изоляции для фиксации чтения, но мы видели измененный уровень изоляции, то есть в некоторые дни это будет сериализуемая изоляция, а в другие дни она не будет сериализуемой.

    Things we have tried so far:
    •   Moved old/expired records from userAccount Audit table to a back up table.
    •   Dropping some indexes which did not make much difference.
    •   Thought about moving the insert out of this transaction but that will violate the integrity of the table as we do need both of them to finish this action.


    Has someone ever faced a similar situation where there were deadlock in transaction that was running creation/update of records and what helped you?


   function is as below..
 public UsernamePasswordDetailModel CreateUserAccount(AccountDetailsMessage message)
            {
                UserAccount userAccount;
                string password;
                using (_conversation.BeginConversation())
                {
                    userAccount = MapUserAccount(message);
                    password = Helper.GenerateRandomPassword(8);

                    userAccount.Username = "TEST- " + Helper.GenerateRandomPassword(8);
                    userAccount = _userAccountRepository.SaveOrUpdate(userAccount); // save it to get the ID back
                    userAccount.Username = userAccount.Id.ToString(CultureInfo.InvariantCulture) + Helper.CalculateCheckDigit(userAccount.Id.ToString(CultureInfo.InvariantCulture));

                    if (string.IsNullOrEmpty(userAccount.PlatformUniqueIdentifier))
                    {
                        userAccount.PlatformUniqueIdentifier = String.Format("{0}:{1}", userAccount.PlatformCode, userAccount.Username);
                    }

                    userAccount.Password = PasswordGenerator.ComputePassword(userAccount.Username, password);
                    userAccount = _userAccountRepository.SaveOrUpdate(userAccount);

                    var audit = new Audit
                    {
                        AuditType = AuditType.Creation,
                        Message = string.Format("Account created: username:{0}  id:{1} ", userAccount.Username, userAccount.Id),
                        UserAccount = userAccount
                    };
                    _auditRepository.SaveOrUpdate(audit);
                }

                var result = new UsernamePasswordDetailModel { Username = userAccount.Username, Password = password };
                return result;
            }
...