PHP + MYSQL на Duplicate KEY все еще увеличивает ключ INDEX

Моя таблица имеет такой стиль:

ID - EMAIL - VERSION - LASTUPDATE 

где id = – auto increment и Primary:

и электронная почта UNIQUE

поэтому каждый раз, когда кто-то использует мое приложение, он получает адрес электронной почты пользователя и пытается вставить, если письмо уже существует, оно ОБНОВЛЯЕТ строку к новым значениям для $ version и $ lastupdate

он почти работает на 100%, его уже обновляет строку отлично, проблема в том, что когда он делает UPDATE, все равно увеличивать идентификатор автоматического увеличения, поэтому следующий INSERT не будет последнимID плюс один, и будет другим примером номера:

 ID - EMAIL - VERSION - LASTUPDATE ----------------------------------- 1 - test1@... - 1.0 - currentTime(); 

если test2 загрузит мое приложение, оно будет добавлено, и база данных будет:

 ID - EMAIL - VERSION - LASTUPDATE ----------------------------------- 1 - test1@.. - 1.0 - currentTime(); 2 - test2@.. - 1.0 - currentTime(); 

так что представьте себе, что test2 имеет новую версию и он обновляется до:

 ID - EMAIL - VERSION - LASTUPDATE ----------------------------------- 1 - test1@.. - 1.1 - currentTime(); 2 - test2@.. - 1.0 - currentTime(); 

отлично, не так ли? поэтому проблема начинается, когда test3 открывает мое приложение, id будет не 3, это будет 4, потому что обновление добавило еще 1 к id (я не знаю, почему)

 ID - EMAIL - VERSION - LASTUPDATE ----------------------------------- 1 - test1@.. - 1.1 - currentTime(); 2 - test2@.. - 1.0 - currentTime(); 4 - test3@.. - 1.1 - currentTime(); 

почему его увеличение плюс к ID при обновлении? я не хочу этого = (

мой синтаксис sql:

 $sql = "INSERT INTO `backups`.`regs` (`email`, `version`, `lastupdate`) VALUES ('$email', '$version', '$lastupdate') ON DUPLICATE KEY UPDATE version='$version', lastupdate='$lastupdate'"; 

хорошо, да, теперь я помню этот вопрос. Был один парень, который хотел сделать вставки, но каждая вставка должна была быть в размере 100 если бы вы могли себе представить, начиная с 1000. И нам пришлось обернуть все это в хранимой процедуре, чтобы иметь одно место уязвимости. Ваш вопрос всплыл, и он сбросил его нумерацию на 1 или около того.

Обертывая его, мы могли бы здраво иметь одну точку делать это с блокировкой и поддерживать значение auto_inc с помощью ALTER TABLE

Другой подход, который я ему сказал, заключался в таблице инкремента, блокировке 1 строки, получении значения в этой строке, использовании ее, обновлении incTable на 100. unlock.

Все время мы смеялись над проблемами ОКР. Я думаю, что он любил всего 10, idk

Редактировать:

Схема:

 -- drop table ocd_nextnums; create table ocd_nextnums ( -- id table for nextnum, for the OCD impaired tableName varchar(100) not null, nextnum int not null -- won't bother with indexes, go for it if you want )engine=INNODB; -- note engine type insert ocd_nextnums(tableName,nextnum) values('thing',1); insert ocd_nextnums(tableName,nextnum) values('some_other_table',1); -- drop table thing; create table thing ( id int primary key, -- NOT an auto_increment, but is a PK email varchar(100) not null, version varchar(20) not null, lastupdate datetime not null, UNIQUE KEY (email) )engine=MyIsam; 

Сохраненный Proc:

 -- drop procedure putInThing; delimiter $$ create procedure putInThing ( email_In varchar(100), version_In varchar(20) ) BEGIN declare toUse int; declare theCount int; select count(*) into theCount from thing where email=email_In; select id into toUse from thing where email=email_In; -- useful for result set @end IF theCount=1 THEN -- was there, do UPDATE update thing set version=version_In,lastupdate=now() where email=email_In; ELSE -- new row, do INSERT (please note the FOR UPDATE clause) select nextnum into toUse from ocd_nextnums where tableName='thing' FOR UPDATE; update ocd_nextnums set nextnum=nextnum+1 where tableName='thing'; insert thing(id,email,version,lastupdate) values (toUse,email_In,version_In,now()); end if; select toUse; -- <------- that was your id END $$ 

Контрольная работа:

 call putInThing('t1@t.com','111'); call putInThing('t2@t.com','121'); call putInThing('t3@t.com','107'); select * from thing; +----+----------+---------+---------------------+ | id | email | version | lastupdate | +----+----------+---------+---------------------+ | 1 | t1@t.com | 111 | 2015-08-14 17:08:10 | | 2 | t2@t.com | 121 | 2015-08-14 17:08:54 | | 3 | t3@t.com | 107 | 2015-08-14 17:08:56 | +----+----------+---------+---------------------+ call putInThing('t3@t.com','101111007'); -- is an update call putInThing('t3@t.com','42'); -- is an update call putInThing('t3@t.com','10007'); -- is an update call putInThing('h@hillaryclinton.com','1'); -- is an insert select * from thing; +----+----------------------+---------+---------------------+ | id | email | version | lastupdate | +----+----------------------+---------+---------------------+ | 1 | t1@t.com | 111 | 2015-08-14 17:08:10 | | 2 | t2@t.com | 121 | 2015-08-14 17:08:54 | | 3 | t3@t.com | 10007 | 2015-08-14 17:22:09 | | 4 | h@hillaryclinton.com | 1 | 2015-08-14 17:22:47 | +----+----------------------+---------+---------------------+ 

Из раздела Mysql INNODB руководства :

Чтобы реализовать чтение и увеличивать счетчик, сначала выполните блокировку чтения счетчика, используя FOR UPDATE, а затем увеличивайте счетчик …..

Вы увидите, что я использую это, возможно, нет. Просто покажите это. Я в порядке с разрывами и спят по ночам. Вот почему я назвал первую таблицу тем, что я сделал:>

Fro, что вы описали, у вас есть неправильное значение в версии $ до того, как вы выполнили вставку. И это заполнено кодом, который вы нам не показали.

Вы должны использовать номер версии, уже сохраненный в базе данных:

 INSERT INTO `backups`.`regs` (`email`, `version`, `lastupdate`) VALUES ('$email', 1, '$lastupdate') ON DUPLICATE KEY UPDATE version=version+1, lastupdate='$lastupdate'" 

Поскольку вы уже передали значения, вы должны использовать version = VALUES(version), lastupdate = VALUES(lastupdate) для ON DUPLICATE , попробуйте следующее:

 $sql = "INSERT INTO `backups`.`regs` (`email`, `version`, `lastupdate`) VALUES ('$email', '$version', '$lastupdate') ON DUPLICATE KEY UPDATE version = VALUES(version), lastupdate = VALUES(lastupdate)";