@Transactional (изоляция = Isolation.SERIALIZABLE, распространение = распространение.REQUIRES_NEW) не работает должным образом - PullRequest
1 голос
/ 11 марта 2020

У меня есть описанный ниже вариант использования, который я пытаюсь выполнить sh, используя транзакции в SERIALIZABLE или REPEATALBE READ ISOLATION.

Это система книжного магазина. Самый простой, без управления пользователями и ограничения удержания цены. В книжном магазине кол-во копий вместе с ним. Для каждого запроса заказа мне нужно проверить количество доступных копий и вычесть его на 1, если оно> 0.

. Для этого я попытался использовать транзакцию, в которой я 1. прочитал объект книги и получил count 2. если count> 0 обновляет счет (count -1) в дБ.

Оба они должны быть выполнены в одной транзакции для подтверждения атомарности / согласованности.

Я написал этот метод в моем сервисе весенней загрузки:

@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
    @Override
    public Book updateBookQuantity(String isbn) {
        Book book = null;

        Optional<Book> bookRecord = bookRepository.findById(isbn);
        try {
            System.out.println("threadname on hold= " + Thread.currentThread().getId());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("threadname resumed = " + Thread.currentThread().getId());

        if (bookRecord.isPresent()) {
            book = bookRecord.get();
            System.out.println("book count == " + Thread.currentThread().getId() + "  "+ book.getQuantity());

            if (book.getQuantity() > 0) {
                book = bookRecord.get();
                book.setQuantity(bookRecord.get().getQuantity() - 1);
                bookRepository.save(book);
            } else {
                throw new BookOutOfStockException(book.getTitle());
            }
        }
        return book;
    }

Теперь, где я ошибаюсь, как при попытке запустить его с помощью Rest api (нажмите 2 раза одновременно). Оба потока работают параллельно, оба считывают счетчик как 1 и обновляют его до 0. В идеале один должен был пройти, а другой должен был вызвать исключение BookOutOfStockException. Я не настроил ничего, определяющего c для менеджера транзакций, все это обрабатывается только при весенней загрузке.

Где этот код работает неправильно? Является ли конфигурация причиной этого? Примечание: используя spring-data-jpa, база данных: mysql

1 Ответ

0 голосов
/ 16 марта 2020

Использование движка InnoDB решило проблему. Чтобы сменить двигатель, используйте правильный диалект. spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

MyIASM не поддерживает транзакции. Вот почему в вышеуказанной проблеме не создаются транзакции. Innodb также поддерживает транзакции и внешний ключ.

...