FAQ |
Kalender |
2013-06-02, 20:28 | #1 | ||
|
|||
Medlem
|
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). |
||
Svara med citat |
2013-06-02, 21:13 | #2 | ||
|
|||
Klarade millennium-buggen
|
En temptabell skapas ju på nytt varje gång så jag skull använda arkiv-tabellens autoincrement som primary copy.
|
||
Svara med citat |
2013-06-03, 15:39 | #3 | ||
|
|||
Medlem
|
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... |
||
Svara med citat |
2013-06-03, 17:57 | #4 | |||
|
||||
Supermoderator
|
Citat:
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. |
|||
Svara med citat |
2013-06-03, 18:07 | #5 | ||
|
|||
Medlem
|
Citat:
Foreign key var bara ett exempel. |
||
Svara med citat |
2013-06-03, 21:06 | #6 | |||
|
||||
Supermoderator
|
Citat:
Är du bunden till InnoDBs funktioner eller skulle MyISAM kunna fungera? |
|||
Svara med citat |
2013-06-03, 21:53 | #7 | ||
|
|||
Klarade millennium-buggen
|
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; Senast redigerad av Conny Westh den 2013-06-03 klockan 21:57 |
||
Svara med citat |
2013-06-03, 22:52 | #8 | ||
|
|||
Medlem
|
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 |
||
Svara med citat |
2013-06-04, 00:10 | #9 | ||
|
|||
Klarade millennium-buggen
|
Citat:
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. |
||
Svara med citat |
2013-06-04, 02:12 | #10 | ||
|
|||
Klarade millennium-buggen
|
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 |
||
Svara med citat |
Svara |
|
|