Mysql
 sql >> Base de données >  >> RDS >> Mysql

PHP + MYSQL sur Duplicate KEY augmente toujours la CLÉ D'INDEX

ok oui, maintenant je me souviens de ce problème. Il y avait un gars une fois qui voulait faire des insertions, mais chaque insertion devait être par incréments de 100 si vous pouviez imaginer, à partir de @1000. Et nous avons dû envelopper le tout dans un proc stocké pour avoir un point de vulnérabilité. Votre problème a fait surface et a modifié sa numérotation d'environ 1 unité.

En l'enveloppant, nous pourrions raisonnablement avoir un point de le faire, avec un verrou, et maintenir la valeur auto_inc avec ALTER TABLE

L'autre approche que je lui ai proposée était d'avoir une table d'incrémentation, de verrouiller la ligne 1, d'obtenir la valeur de cette ligne, de l'utiliser, de mettre à jour cette incTable de 100. déverrouiller.

Pendant tout ce temps, nous avons ri des problèmes de TOC. Je pense qu'il n'aimait que les multiples de 10, idk

Modifier :

Schéma :

-- 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édure stockée :

-- 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
$$

Test :

call putInThing('[email protected]','111');
call putInThing('[email protected]','121');
call putInThing('[email protected]','107');
select * from thing;
+----+----------+---------+---------------------+
| id | email    | version | lastupdate          |
+----+----------+---------+---------------------+
|  1 | [email protected] | 111     | 2015-08-14 17:08:10 |
|  2 | [email protected] | 121     | 2015-08-14 17:08:54 |
|  3 | [email protected] | 107     | 2015-08-14 17:08:56 |
+----+----------+---------+---------------------+

call putInThing('[email protected]','101111007'); -- is an update
call putInThing('[email protected]','42'); -- is an update
call putInThing('[email protected]','10007'); -- is an update
call putInThing('[email protected]','1'); -- is an insert

select * from thing;
+----+----------------------+---------+---------------------+
| id | email                | version | lastupdate          |
+----+----------------------+---------+---------------------+
|  1 | [email protected]             | 111     | 2015-08-14 17:08:10 |
|  2 | [email protected]             | 121     | 2015-08-14 17:08:54 |
|  3 | [email protected]             | 10007   | 2015-08-14 17:22:09 |
|  4 | [email protected] | 1       | 2015-08-14 17:22:47 |
+----+----------------------+---------+---------------------+

De la partie Mysql INNODB du Manuel :

Me verrez-vous l'utiliser, probablement pas. Juste le montrer. Je vais bien avec des lacunes et dormir la nuit. C'est pourquoi j'ai nommé la première table ce que j'ai fait :>