WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   Få MySQL att sluta resetta auto_increment? (https://www.wn.se/forum/showthread.php?t=1058131)

JesperA 2013-06-02 20:28

Få MySQL att sluta resetta auto_increment?
 
Tja!

Stötte på ett problem med MySQL (innodb), detta problemet tog jag för givet att det inte existerade.

Jag har 2st tabeller med liknande struktur och jag använder samma $_POST för att lägga in data i båda tabellerna. Jag använder transaktioner för att säkerhetsställa att datan verkligen läggs in i båda tabellerna, detta fungerar utmärkt.

I tabell 1 har jag ett PostID som är PRIMARY KEY och auto_increment

I tabell 2 har jag också ett PostID som använder "$PostID = $db->lastInsertID();" (i PHP) från ovanstående insert, detta gör ju att PostID bör bli samma i båda tabellerna, vilket det blir.


Problemet är att tabell 1 bara är en temporär tabell vars rader bara existerar i några timmar eller max ett par dagar innan raden tas bort, ibland riskerar den att bli tom, och råkar man då starta om servern just när tabell 1 är tom så defaultar auto_increment ner till 1 igen, detta pajar ju hela consistency grejen mellan dom 2 tabellerna.




Tabell 2 är en arkiverande tabell, jag skulle kunna sätta auto_increment på tabell 2 istället och låta tabell 1 få sitt PostID från tabells 2 "$PostID = $db->lastInsertID();", alltså sätter in i tabell 2 först, och sen i tabell 1.

Men finns ju samma risk där att om jag migrerar tabell 2 vid ett senare tillfälle så kan jag inte garantera någon consistency.


Går det inte få auto_increment att låsa sitt värde oavsett om tabellen blir tömd (alltså inte bara vid truncate utan även när varje rad tas bort 1 och 1 tills tabellen blir tom).

Conny Westh 2013-06-02 21:13

En temptabell skapas ju på nytt varje gång så jag skull använda arkiv-tabellens autoincrement som primary copy.

JesperA 2013-06-03 15:39

Jag tror du tänker på en temptabell som skapas tex när man kör subqueries osv, det är inte en sådan tabell jag syftar på, utan jag har en permanent tabell som jag dumpar tillfällig data i.

Iaf, jag kommer ju bli tvungen att köra med tabell 2 som "huvudtabell" nu istället.

Helt sjukt att jag missat detta problemet, har tagit för givet i över 10 år att auto_increment är ett sätt att garantera 100% unikt ID, men det är det ju inte, det går ju bara att garantera på en enskild tabell, inte om man tar ID från en tabell och vill använda som foreign key eller whatever på andra tabeller, ID över flera tabeller kan ju då enbart garanteras om tabellen aldrig blir tom...

FredrikMH 2013-06-03 17:57

Citat:

Ursprungligen postat av JesperA (Inlägg 20471227)
Helt sjukt att jag missat detta problemet, har tagit för givet i över 10 år att auto_increment är ett sätt att garantera 100% unikt ID, men det är det ju inte, det går ju bara att garantera på en enskild tabell, inte om man tar ID från en tabell och vill använda som foreign key eller whatever på andra tabeller, ID över flera tabeller kan ju då enbart garanteras om tabellen aldrig blir tom...

Nej tabellen kan bli tom utan att auto_increment nollställs, men det beror på hur du tömmer tabellen. TRUNCATE kommer återställa auto_increment, men jag tror inte en vanlig DELETE FROM gör det.

Vitsen är ju att om du tar bort data som används som nyckel i andra tabeller så bör du nog även ta bort data där eller fundera på ett annat databasupplägg.

JesperA 2013-06-03 18:07

Citat:

Ursprungligen postat av FredrikMH (Inlägg 20471253)
Nej tabellen kan bli tom utan att auto_increment nollställs, men det beror på hur du tömmer tabellen. TRUNCATE kommer återställa auto_increment, men jag tror inte en vanlig DELETE FROM gör det.

Som sagt, auto_increment nollställs om du har tömt raderna en och en, är då tabellen tom när man startar om servern eller mysql service så resettas auto_increment.

Citat:

Ursprungligen postat av FredrikMH (Inlägg 20471253)
Vitsen är ju att om du tar bort data som används som nyckel i andra tabeller så bör du nog även ta bort data där eller fundera på ett annat databasupplägg.

Foreign key var bara ett exempel.

FredrikMH 2013-06-03 21:06

Citat:

Ursprungligen postat av JesperA (Inlägg 20471254)
Som sagt, auto_increment nollställs om du har tömt raderna en och en, är då tabellen tom när man startar om servern eller mysql service så resettas auto_increment.

Det stämmer det du säger med InnoDB. För MyISAM stämmer det dock inte, då är auto_increment sparat trots att MySQL service startar om och tabellen är tom.

Är du bunden till InnoDBs funktioner eller skulle MyISAM kunna fungera?

Conny Westh 2013-06-03 21:53

Stopp och belägg!!!


Skapa först en databas, sen kör du Create enligt nedan med InnoDB....
Kod:

use wn;

delimiter $$

CREATE TABLE `test` (
  `idTest` int(11) NOT NULL AUTO_INCREMENT,
  `Testcol` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`idTest`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$


Sen kör du denna kod dvs först rensar hela tabellen Test från alla poster med en vanlig SQL Delete...

Sen lägger du till nya poster med INSERT och sen raderar igen och skapar nya med INSERT så kommer INTE autoincrement att nollställas, tvärtom förtsätter den att öka.

Nedanstående kod kan du köra flera gånger och då kommer hela tiden primärnyckeln att öka från gång till gång, trots att alla poster raderas varje gång....
Kod:

delete from test;
insert into test(testcol) values('a');
insert into test(testcol) values('b');
insert into test(testcol) values('c');
insert into test(testcol) values('d');
insert into test(testcol) values('e');
select * from test;
delete from test;
insert into test(testcol) values('f');
insert into test(testcol) values('g');
insert into test(testcol) values('h');
insert into test(testcol) values('i');
insert into test(testcol) values('j');
insert into test(testcol) values('k');
select * from test;


lubic 2013-06-03 22:52

Conny: Tror du missade punkten om att servern startas om efter att man har tagit bort raderna. Sen tycker jag iofs det låter märkligt/dumt att autoincrement nollställs vid en omstart? Men så är det kanske tänkt att fungera av någon anledning?

http://dev.mysql.com/doc/refman/5.0/...-handling.html

Conny Westh 2013-06-04 00:10

Citat:

Ursprungligen postat av lubic (Inlägg 20471277)
Conny: Tror du missade punkten om att servern startas om efter att man har tagit bort raderna. Sen tycker jag iofs det låter märkligt/dumt att autoincrement nollställs vid en omstart? Men så är det kanske tänkt att fungera av någon anledning?

http://dev.mysql.com/doc/refman/5.0/...-handling.html

OK, det missade jag.

Då kan man ju faktiskt aldrig använda auto_increment i MySQL.

Man får skapa en egen tabell som håller koll på nästa ID och anropa en SP som ger nästa lediga ID för just den tabellen.

Conny Westh 2013-06-04 02:12

Hittade följande länk (otestat): http://dev.mysql.com/doc/refman/5.0/...increment.html

Kod:

-- Posted by Thomas Mayer on January 20 2012 3:17pm
--
-- As InnoDb forgets its highest auto_increment after server restart, you can set it again,
-- if you have stored it anywhere. This happens often if you archive your data in an archive
-- table and then delete it and then restart mysql. When archiving again this will result in
-- duplicate key entries.
--
-- To work around this you can create a trigger which makes sure your auto_increment is
-- higher than the auto_increment of your archive table:

delimiter //
drop trigger if exists trigger_autoinc_tbl;
CREATE TRIGGER trigger_autoinc_tbl BEFORE INSERT ON tbl
FOR EACH ROW
BEGIN
declare auto_incr1 BIGINT;
declare auto_incr2 BIGINT;
 SELECT AUTO_INCREMENT INTO auto_incr1 FROM information_schema.TABLES WHERE table_schema=DATABASE() AND table_name='tbl';
 SELECT AUTO_INCREMENT INTO auto_incr2 FROM information_schema.TABLES WHERE table_schema=DATABASE() AND table_name='tbl_archiv';
 IF (auto_incr2 > auto_incr1 and NEW.id<auto_incr2) THEN
 SET NEW.id = auto_incr2;
 END IF;
END;//
delimiter ;

-- Further reading: http://www.slicewise.net/index.php?id=82



Alla tider är GMT +2. Klockan är nu 05:41.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson