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

Opret et indeks på en enorm MySQL-produktionstabel uden tabellåsning

[2017] Opdatering:MySQL 5.6 understøtter online indeksopdateringer

https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html#online-ddl-index-syntax-notes

I MySQL 5.6 og nyere forbliver tabellen tilgængelig for læse- og skriveoperationer, mens indekset oprettes eller slettes. CREATE INDEX- eller DROP INDEX-sætningen afsluttes først, efter at alle transaktioner, der har adgang til tabellen, er afsluttet, så indeksets begyndelsestilstand afspejler det seneste indhold i tabellen. Tidligere resulterede ændring af tabellen, mens et indeks oprettes eller slettes, typisk i et dødvande, der annullerede INSERT-, UPDATE- eller DELETE-sætningen på tabellen.

[2015] Opdatering af tabelindeks blokerer skriver i MySQL 5.5

Fra svaret ovenfor:

"Hvis du bruger en version, der er større end 5.1, oprettes indekser, mens databasen er online. Så fortvivl ikke, du vil ikke afbryde brugen af ​​produktionssystemet."

Dette er ****FALSK**** (i det mindste for MyISAM / InnoDB-tabeller, hvilket er hvad 99,999 % af folk derude bruger. Clustered Edition er anderledes.)

Udførelse af OPDATERING på et bord vil BLOKERE mens indekset oprettes. MySQL er virkelig, virkelig dumt med dette (og et par andre ting).

Test script:

( for n i {1..50}; gør #(time mysql -uroot -e 'select * fra website_development.users hvor id =41225\G'>/dev/null) 2>&1 | grep real; (tid mysql -uroot -e 'update website_development.users set bio="" hvor id =41225\G'>/dev/null) 2>&1 | grep real; færdig) | cat -n &PID=$!sleep 0.05echo "Index Update - START"mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'echo "Index Update - FINISH"sleep 0.05kill $PIDtime mysql -uroot website_development -e 'drop index ddopsonfu on users;' 

Min server (InnoDB):

Serverversion:5.5.25a Kildedistribution 

Output (bemærk, hvordan den 6. operation blokerer i de ~400 ms, det tager at afslutte indeksopdateringen):

1 reelle 0m0.009s 2 rigtige 0m0.009s 3 rigtige 0m0.009s 4 rigtige 0m0.012s 5 rigtige 0m0.009sIndex Update - STARTIndex Update - FINISH 6 rigtige 0m0.388s 8.0 rigtige 0m0m .009s 9 real 0m0.009s10 real 0m0.009s11 real 0m0.009s

I modsætning til læseoperationer, der ikke blokerer (byt linjekommentaren i scriptet):

1 ægte 0m0.010s 2 rigtige 0m0.009s 3 rigtige 0m0.009s 4 rigtige 0m0.010s 5 rigtige 0m0.009sIndex Opdatering - START 6 rigtige 0m0.010s 7 rigtige 0m0.010s 080s 1. real 0m0.010s...41 real 0m0.009s42 ​​real 0m0.010s43 real 0m0.009sIndex Update - FINISH44 real 0m0.012s45 real 0m0.009s46 real 0m0.009s47 real 0mcode.9

Opdatering af MySQL's skema uden nedetid

Indtil videre er der kun én metode, jeg kender til, til at opdatere et MySql-skema og ikke lide af en tilgængelighedsafbrydelse. Cirkulære mestre:

  • Master A har din MySQL-database kørende på den
  • Bring Master B i brug, og få den til at kopiere skriverier fra Master A (B er en slave af A)
  • Udfør skemaopdateringen på Master B. Den kommer bagud under opgraderingen
  • Lad mester B indhente det. Invariant:Din skemaændring SKAL være i stand til at behandle kommandoer replikeret fra et nedversionsskema. Indekseringsændringer kvalificerer. Simple kolonnetilføjelser kvalificerer normalt. Vil du fjerne en kolonne? sikkert ikke.
  • Skift ATOMISK alle klienter fra Master A til Master B. Hvis du vil være sikker (tro mig, det gør du), bør du sikre dig, at den sidste skrivning til A replikeres til B FØR B tager sin første skrivning. Hvis du tillader samtidige skrivninger til 2+ mastere, ... forstår du bedre MySQL-replikering på et DYB niveau, eller du er på vej mod en verden af ​​smerte. Ekstrem smerte. Ligesom, har du en kolonne, der er AUTOINCREMENT??? du er skruet sammen (medmindre du bruger lige tal på den ene master og odds på den anden). Stol IKKE på, at MySQL-replikering "gør det rigtige". Det er IKKE smart og vil ikke redde dig. Det er bare lidt mindre sikkert end at kopiere binære transaktionslogfiler fra kommandolinjen og afspille dem i hånden. Alligevel kan det gøres på få sekunder at afbryde alle klienter fra den gamle master og vende dem til den nye master, meget hurtigere end at vente på en flertimers skemaopgradering.
  • Nu er Master B din nye master. Du har det nye skema. Livet er godt. Tag en øl; det værste er overstået.
  • Gentag processen med Master A, og opgrader hans skema, så han bliver din nye sekundære master, klar til at tage over i tilfælde af, at din primære master (master B nu) mister magten eller bare står op og dør på dig.

Det er ikke en nem måde at opdatere skemaet på. Kan arbejde i et seriøst produktionsmiljø; Ja det er. Venligst, venligst, venligst, hvis der er en nemmere måde at tilføje et indeks til en MySQL-tabel uden at blokere skrivninger, så lad mig det vide.

Googling førte mig til denne artikel som beskriver en lignende teknik. Endnu bedre, de råder til at drikke på samme tidspunkt i proceduren (Bemærk, at jeg skrev mit svar, før jeg læste artiklen)!

Perconas pt-online-schema-change

artiklen Jeg linkede ovenstående taler om et værktøj, pt -online-skema-ændring , der fungerer som følger:

  • Opret ny tabel med samme struktur som originalen.
  • Opdater skema på ny tabel.
  • Tilføj en trigger på den originale tabel, så ændringer holdes synkroniseret med kopien
  • Kopiér rækker i batches fra den oprindelige tabel.
  • Flyt den originale tabel af vejen, og udskift den med en ny tabel.
  • Slip gammel tabel.

Jeg har aldrig selv prøvet værktøjet. YMMV

RDS

Jeg bruger i øjeblikket MySQL gennem Amazon's RDS . Det er en virkelig smart service, der afslutter og administrerer MySQL, så du kan tilføje nye læsereplikaer med en enkelt knap og gennemsigtigt opgradere databasen på tværs af hardware-SKU'er. Det er virkelig praktisk. Du får ikke SUPER adgang til databasen, så du kan ikke skrue med replikering direkte (er det en velsignelse eller forbandelse?). Du kan dog bruge Læs Replica Promotion for at lave dine skemaændringer på en skrivebeskyttet slave, og promover den slave til at blive din nye mester. Præcis det samme trick som jeg beskrev ovenfor, bare meget nemmere at udføre. De gør stadig ikke meget for at hjælpe dig med cut-over. Du skal omkonfigurere og genstarte din app.



  1. phpMyAdmin kaster en #2002 kan ikke logge ind på mysql serveren phpmyadmin

  2. Øg værdien i MySQL-opdateringsforespørgsel

  3. Vis alle funktioner i Oracle-databasen

  4. T-SQL:søger efter e-mail-format