Механизм MyISAM MySQL может это сделать. См. Их руководство в разделе Использование AUTO_INCREMENT :
Для таблиц MyISAM вы можете указать AUTO_INCREMENT на вторичном столбце в индексе с несколькими столбцами. В этом случае генерируемое значение для столбца AUTO_INCREMENT вычисляется как MAX (auto_increment_column) + 1 WHERE prefix = given-prefix. Это полезно, когда вы хотите поместить данные в упорядоченные группы.
blockquote>Документы продолжаются после этого параграфа, демонстрируя пример.
Механизм InnoDB в MySQL не поддерживайте эту функцию, что является неудачным, потому что лучше использовать InnoDB практически во всех случаях.
Вы не можете эмулировать это поведение с помощью триггеров (или любых операторов SQL, ограниченных областью транзакций) без блокировки таблиц в INSERT. Рассмотрим эту последовательность действий:
- Mario начинает транзакцию и вставляет новую строку для пользователя 4.
- Билл начинает транзакцию и вставляет новую строку для пользователя 4.
- Сеанс Марио запускает триггер для вычисления MAX (id) +1 для пользователя 4. Вы получаете 3.
- В сеансе Билла срабатывает триггер для вычисления MAX (id). Я получаю 3.
- Заседание Билла заканчивает его INSERT и совершает.
- Сеанс Марио пытается завершить свой INSERT, но теперь строка с (userid = 4, id = 3) существует, поэтому Марио получает конфликт с первичным ключом.
В общем, вы не можете контролировать порядок выполнения этих шагов без какой-либо синхронизации.
Решения для это либо:
- Получите эксклюзивную блокировку таблицы. Перед тем, как попробовать INSERT, заблокируйте таблицу. Это необходимо, чтобы предотвратить одновременные ВСТАВКИ от создания условия гонки , как в приведенном выше примере. Необходимо заблокировать всю таблицу, так как вы пытаетесь ограничить INSERT, нет конкретной строки для блокировки (если вы пытаетесь управлять доступом к данной строке с помощью UPDATE, вы можете заблокировать только определенную строку). Но блокировка таблицы приводит к тому, что доступ к таблице становится последовательным, что ограничивает вашу пропускную способность.
- Сделайте это за пределами транзакции. Создайте идентификационный номер таким образом, чтобы он не скрывался от двух параллельных транзакций. Кстати, это то, что делает AUTO_INCREMENT. Два параллельных сеанса будут получать уникальное значение id независимо от порядка выполнения или порядка фиксации. Но отслеживание последнего сгенерированного идентификатора для каждого пользователя требует доступа к базе данных или дублированного хранилища данных. Например, ключ memcached для каждого пользователя, который может быть инкрементирован атомарно .
Относительно легко убедиться, что вставки получают значения unique , Но трудно гарантировать, что они получат последовательные порядковые значения. Также рассмотрите:
- Что произойдет, если вы вСТАВИТЕСЬ в транзакции, а затем откат? Вы указали значение 3 в этой транзакции, а затем я выделил значение 4, поэтому, если вы откат и я зафиксирую, теперь есть пробел.
- Что произойдет, если INSERT завершится с ошибкой из-за других ограничений на таблица (например, другой столбец NOT NULL)? Вы также можете получить пробелы.
- Если вы когда-либо удаляете строку, вам нужно перенумеровать все следующие строки для одного и того же идентификатора пользователя? Что это делает для ваших записей memcached, если вы используете это решение?
Если вы отметите Документы MDN :
метод HTTP-метод, который браузер использует для отправки формы. Возможные значения:
post : Соответствует методу HTTP POST; Данные формы включаются в тело формы и отправляются на сервер.
get : соответствует методу HTTP GET; данные формы добавляются к URI атрибута действия с символом «?» в качестве разделителя, и в результате.
blockquote>Если вы хотите отправить удаление, прослушайте событие
submit
в форме, позвонитеevent.preventDefault()
, чтобы остановить действие по умолчанию, и сделайте свой собственный запрос к бэкэнду, что более типично. «современный» способ сделать это в любом случае, так как это не приводит к обновлению страницы.Также ваш маршрут не будет поврежден без чего-либо в части
:id
.Один из способов сделать это заключается в следующем:
Дайте вашей форме класс или найдите способ ссылаться на него
<form action="/api" method="post" id="test-form"> <input type="number" name="id" placeholder="delete" /><br/> </form>
В вашем JavaScript, найти способ ссылки на форму и запретить ее отправку:
const form = document.getElementById('test-form'); form.addEventListener('submit', async event => { event.preventDefault(); // This prevents the form from submitting using POST const idInput = form.querySelector('input[name="id"]'); const id = idInput.value; const res = await fetch(`https://apiurl.com/api/${id}`, { method: 'DELETE', }); const json = await res.json(); console.log(json); });
Поскольку форма не поддерживает метод удаления, вы можете запретить отправку формы автоматически и отправить запрос вручную, используя либо API выборки, либо jquery xhr:
<form action="/api" method="" id="deleteApi">
<input type="number" name="id" placeholder="delete" /><br/>
<input type="submit" value="Submit">
</form>
js код:
[ 111]