Mysql
 sql >> Database >  >> RDS >> Mysql

PHP + MYSQL su Duplicate KEY aumentano ancora la INDEX KEY

ok sì, ora ricordo questo problema. C'era un ragazzo una volta che voleva fare inserti, ma ogni inserto doveva essere in incrementi di 100 se puoi immaginare, a partire da @1000. E abbiamo dovuto avvolgere il tutto in un processo memorizzato per avere un punto di vulnerabilità. Il tuo problema è emerso e ha annullato la sua numerazione di circa 1.

Avvolgendolo, potremmo avere ragione di farlo, con un lucchetto, e mantenere il valore auto_inc con ALTER TABLE

L'altro approccio che gli ho detto era avere una tabella incrementale, bloccare la riga 1, ottenere il valore in quella riga, usarlo, aggiornare quella tabella inc di 100. sbloccare.

Per tutto il tempo abbiamo riso di problemi di DOC. Penso che gli piacessero solo multipli di 10, idk

Modifica:

Schema:

-- 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 memorizzato:

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

Dalla parte Mysql INNODB del Manuale :

Mi vedrai usare questo, probabilmente no. Basta mostrarlo. Sto bene con le lacune e dormendo la notte. Ecco perché ho chiamato la prima tabella come ho fatto :>