Решение задачи сохранения единого для нескольких таблиц автоинкрементального счетчика. Иными словами, как реализовать в MySQL аналог SEQUENCE в PostgreSQL, работающих примерно так:
CREATE SEQUENCE next_contraсt start 1 increment 1 maxvalue 2147483647 minvalue 1 cache 1;
CREATE TABLE contract (
"id" integer NOT NULL DEFAULT nextval('next_contraсt') PRIMARY KEY,
...
);
++ Метод 1.
Создаем таблицу:
CREATE TABLE option1 (id int not null primary key auto_increment) engine=innodb;
При необходимости получения очередного номера счетчика выполняем (фиктивная вставка данных, необходимая для срабатывания auto_increment):
INSERT INTO option1 VALUES (NULL);
Получаем текущее значение идентификатора через API-вызов $connection->insert_id(), например, в PHP:
$last_id = mysql_insert_id();
++ Метод 2:
Создаем таблицу из одного столбца:
CREATE TABLE option2 (id int not null primary key) engine=innodb;
Инициализируем первое значение:
INSERT INTO option2 VALUES (1); # начинаем последовательность с 1
Для получения очередного значения счетчика выполняем:
UPDATE option2 SET id=@id:=id+1;
SELECT @id;
По производительности первый метод заметно быстрее второго:
Метод 1 с использованием транзакций: 19 сек на выполнение 10000 итераций
Метод 1 без использования транзакций: 13 сек на выполнение 10000 итераций
Метод 2 с использованием транзакций: 27 сек на выполнение 10000 итераций
Метод 2 без использования транзакций: 22 сек на выполнение 10000 итераций
++ Метод 3.
Использовать функцию LAST_INSERT_ID(), которая возвращает последний сгенерированный через AUTO_INCREMENT на сервере идентификатор.
UPDATE option3 SET id = LAST_INSERT_ID(id+1);
++ Метод 4.
Использование хранимых процедур и триггеров.
Создаем таблицу sequences для хранения счетчика и функцию nextval('seqname') для возвращения следующего номера:
CREATE TABLE IF NOT EXISTS sequences
(name CHAR(20) PRIMARY KEY,
val INT UNSIGNED);
DROP FUNCTION IF EXISTS nextval;
DELIMITER //
CREATE FUNCTION nextval (seqname CHAR(20))
RETURNS INT UNSIGNED
BEGIN
INSERT INTO sequences VALUES (seqname,LAST_INSERT_ID(1))
ON DUPLICATE KEY UPDATE val=LAST_INSERT_ID(val+1);
RETURN LAST_INSERT_ID();
END
//
DELIMITER ;
Создаем тестовую таблицу data для последующего подключения генератора последовательности:
CREATE TABLE IF NOT EXISTS data
(id int UNSIGNED NOT NULL PRIMARY KEY DEFAULT 0,
info VARCHAR(50));
Создаем триггер для автоматизации инкрементирования счетчика в таблице data:
DROP TRIGGER nextval;
CREATE TRIGGER nextval BEFORE INSERT ON data
FOR EACH ROW SET new.id=IF(new.id=0,nextval('data'),new.id);
TRUNCATE TABLE data;
Экспериментируем:
INSERT INTO data (info) VALUES ('bla');
INSERT INTO data (info) VALUES ('foo'),('bar');
SELECT * FROM data;
+----+------+
| id | info |
+----+------+
| 1 | bla |
| 2 | foo |
| 3 | bar |
+----+------+
URL: http://www.mysqlperformanceblog.com/2010/10/04/sharing-an-au.../ http://openquery.com/blog/implementing-sequences-using-a-sto...
Обсуждается: http://www.opennet.me/tips/info/2460.shtml