Вопрос

У члена команды возникла проблема со старой внутренней системой, когда пользователь, дважды щелкнув ссылку на веб-странице, может вызвать отправку двух запросов из браузера, в результате чего две базы данных будут вставлены в одну и ту же запись. в состоянии гонки; последний из них не работает с нарушением первичного ключа. Несколько решений и взломов были предложены и обсуждены:

<Ол>
  • Используйте Javascript на веб-странице, чтобы уменьшить второй щелчок, отключив ссылку для первого щелчка. Это быстрый и простой способ уменьшить возникновение проблемы, но не полностью устранить ее.

  • Оберните выполнение запроса на стороне сервера в транзакции. Эта операция считалась слишком дорогой из-за нагрузки на сервер и уровней блокировки в рассматриваемой таблице.

  • Перехватите исключение первичного ключа, вызванное неудачной вставкой, определите его как таковое и сожмите. Это имеет недостатки: (а) блокировка поставщика, необходимость знать нюансы исключений, характерных для базы данных, и (б) возможность не регистрировать / обрабатывать допустимые сбои базы данных.

  • Расширение # 3 путем попытки обновления записи в случае сбоя вставки и проверки результата обновления, чтобы убедиться, что он возвращает 1 затронутую запись.

  • Есть другие варианты, которые не были рассмотрены? Есть ли плюсы и минусы представленных вариантов, которые были упущены? Что является меньшим из всех зол?

    Это было полезно?

    Решение

    Вам необходимо реализовать шаблон токена синхронизатора.

    Как это работает: значение (токен) генерируется на сервере для каждого запроса. Этот же токен должен быть включен в вашу форму. После получения запроса токен сервера и токен клиента сравниваются, и если они совпадают, вы можете продолжить добавление своей записи. Затем токен на стороне сервера регенерируется, поэтому последующие запросы, содержащие старый токен, не будут выполнены.

    Существует более подробное объяснение о том, как на полпути вниз эту страницу .

    Я не уверен, какую технологию вы используете, но Struts обеспечивает поддержку на уровне структуры для этого шаблона. См. Пример здесь

    Другие советы

    Поместите уникальный идентификатор на страницу в скрытом поле. Принимайте только один ответ с заданным уникальным идентификатором.

    Похоже, вы неправильно используете запрос GET для изменения состояния сервера (хотя это не всегда так). Хотя это может не подходить для вашей ситуации, следует указать, что вам следует рассмотреть возможность преобразования ссылки в форму POST.

    Кажется, вы уже ответили на свой вопрос; Кажется, # 1 - единственный жизнеспособный вариант.

    В противном случае вы действительно должны выполнить все три шага - целостность данных должна обрабатываться на уровне базы данных, но дополнительные проверки (такие как явная транзакция) в коде во избежание обращения к базе данных могут быть полезны для производительности.

    REF Необходимо реализовать шаблон токена синхронизатора.

    Это для Javascript / HTML, а не JAVA

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top