У меня есть таблица mysql некоторых записей, например:
CREATE TABLE test ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value varchar NOT NULL )
теперь мне нужно создать уникальную последовательность из 1, 2, …, N в php-скрипте и сохранить в другой таблице … Как достичь этого, чтобы быть потокобезопасным и не создавать дублирование или что-то пропускать?
Мне было интересно, может ли какая-то дополнительная таблица mysql быть полезной, но я не знаю, как создать что-то вроде «отдельных автоинкрементов для каждого значения столбца» или чего-нибудь еще …
test: 1 ... apples 2 ... oranges 3 ... lemons
некоторый php-скрипт (доступный одновременно несколькими пользователями в то время):
save_next_fruit($_GET['fruit']);
создаст некоторую запись в других таблицах со значениями, такими как:
saved_fruit: ID | FRUIT(FK) | FRUIT_NO 1 1 1 2 1 2 3 2 1 4 3 1 5 3 2 6 1 3 7 3 3 8 2 2 9 1 4 10 2 3 11 1 5 12 2 4 13 1 6 14 3 4 15 3 5
другими словами, мне нужно это сделать (например, для фруктов 3 (лимоны)):
insert into saved_fruit (fruit, fruit_no) values (3, select MAX(fruit_no)+1 from saved_fruit where fruit = 3);
но в потоковом безопасном режиме (я понимаю, что команда выше не является потоковой безопасностью в базе данных MySQL MyISAM)
Вы можете помочь?
благодаря
MyISAM поддерживает это поведение. Создайте первичный ключ с двумя столбцами и сделайте второй шаг автоматического увеличения. Он начнется для каждого отдельного значения в первом столбце.
CREATE TABLE t (i INT, j INT AUTO_INCREMENT, PRIMARY KEY (i,j)) ENGINE=MyISAM; INSERT INTO t (i) VALUES (1), (1), (2), (2), (1), (3); SELECT * FROM t; +---+---+ | i | j | +---+---+ | 1 | 1 | | 1 | 2 | | 1 | 3 | | 2 | 1 | | 2 | 2 | | 3 | 1 | +---+---+
Но если вы думаете об этом, это только поточно-безопасное средство хранения, которое блокирует блокировку на уровне таблицы для инструкций INSERT. Поскольку INSERT должен искать другие строки в таблице, чтобы найти максимальное значение j
одного и того же значения i
. Если другие люди делают INSERT одновременно, это создает условие гонки.
Таким образом, зависимость от MyISAM, которая делает блокировку на уровне таблицы в INSERT.
См. Эту ссылку в руководстве: http://dev.mysql.com/doc/refman/5.6/en/example-auto-increment.html в разделе « Заметки MyISAM» .
Существует множество веских причин не использовать MyISAM. Решающим фактором для меня является тенденция MyISAM к искажению данных.
Ваш комментарий:
InnoDB не поддерживает поведение приращений для каждой группы, описанное выше. Вы можете сделать первичный ключ с несколькими столбцами, но полученная вами ошибка связана с тем, что InnoDB требует, чтобы столбец с автоматическим приращением был первым столбцом в ключе таблицы (он не обязательно должен быть первичным ключом)
Независимо от положения столбца auto-increment в многоколоночном ключе, он увеличивается только тогда, когда вы используете его с InnoDB; он не числивает записи на отдельное значение в другом столбце.
Чтобы сделать это с помощью таблицы InnoDB, вам нужно будет заблокировать таблицу явно на время INSERT, чтобы избежать условий гонки. Вы сделаете свой собственный запрос SELECT для максимального значения в группе, в которую вы вставляете. Затем вставьте это значение + 1.
В принципе, вам нужно обойти функцию автоматического увеличения и указать значения вместо их автоматического создания.
Когда вы используете MyISAM, вы можете заблокировать всю таблицу .
LOCK TABLES `saved_fruit`; -- Insert query with select. UNLOCK TABLES;