sql >> Database >  >> RDS >> Mysql

Maak een index op een enorme MySQL-productietafel zonder tafelvergrendeling

[2017] Update:MySQL 5.6 heeft ondersteuning voor online indexupdates

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

In MySQL 5.6 en hoger blijft de tabel beschikbaar voor lees- en schrijfbewerkingen terwijl de index wordt gemaakt of verwijderd. De instructie CREATE INDEX of DROP INDEX wordt pas voltooid nadat alle transacties die toegang hebben tot de tabel zijn voltooid, zodat de beginstatus van de index de meest recente inhoud van de tabel weerspiegelt. Voorheen resulteerde het wijzigen van de tabel terwijl een index werd gemaakt of verwijderd, meestal in een impasse die de instructie INSERT, UPDATE of DELETE op de tabel annuleerde.

[2015] Bijwerken van tabelindices blokkeert schrijfacties in MySQL 5.5

Uit het antwoord hierboven:

"Als je een versie gebruikt die hoger is dan 5.1, worden indexen gemaakt terwijl de database online is. Dus maak je geen zorgen, je zult het gebruik van het productiesysteem niet onderbreken."

Dit is ****FALSE**** (tenminste voor MyISAM / InnoDB-tabellen, dat is wat 99,999% van de mensen daar gebruikt. Geclusterde editie is anders.)

Het uitvoeren van UPDATE-bewerkingen op een tafel zal BLOKKEREN terwijl de index wordt gemaakt. MySQL is hier echt heel dom over (en een paar andere dingen).

Testscript:

(   
  for n in {1..50}; do
    #(time mysql -uroot -e 'select  * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
    (time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
  done
) | cat -n &
PID=$!
sleep 0.05
echo "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.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'

Mijn server (InnoDB):

Server version: 5.5.25a Source distribution

Uitvoer (let op hoe de 6e bewerking de ~400ms blokkeert die nodig zijn om de indexupdate te voltooien):

 1  real    0m0.009s
 2  real    0m0.009s
 3  real    0m0.009s
 4  real    0m0.012s
 5  real    0m0.009s
Index Update - START
Index Update - FINISH
 6  real    0m0.388s
 7  real    0m0.009s
 8  real    0m0.009s
 9  real    0m0.009s
10  real    0m0.009s
11  real    0m0.009s

Vs leesbewerkingen die niet blokkeren (verwissel de regelcommentaar in het script):

 1  real    0m0.010s
 2  real    0m0.009s
 3  real    0m0.009s
 4  real    0m0.010s
 5  real    0m0.009s
Index Update - START
 6  real    0m0.010s
 7  real    0m0.010s
 8  real    0m0.011s
 9  real    0m0.010s
...
41  real    0m0.009s
42  real    0m0.010s
43  real    0m0.009s
Index Update - FINISH
44  real    0m0.012s
45  real    0m0.009s
46  real    0m0.009s
47  real    0m0.010s
48  real    0m0.009s

Het MySQL-schema bijwerken zonder downtime

Tot nu toe is er maar één methode die ik ken om een ​​MySql-schema bij te werken en geen beschikbaarheidsstoring te ondervinden. Circulaire meesters:

  • Master A heeft uw MySQL-database erop draaien
  • Breng Master B in gebruik en laat het schrijven van Master A repliceren (B is een slaaf van A)
  • Voer de schema-update uit op Master B. Deze loopt achter tijdens de upgrade
  • Laat meester B bijpraten. Invariant:uw schemawijziging MOET opdrachten kunnen verwerken die zijn gerepliceerd vanuit een downversieschema. Indexeringswijzigingen komen in aanmerking. Eenvoudige kolomtoevoegingen komen meestal in aanmerking. Een kolom verwijderen? waarschijnlijk niet.
  • ATOMISCH alle clients van Master A naar Master B verwisselen. Als u veilig wilt zijn (geloof me, dat doet u), moet u ervoor zorgen dat de laatste schrijfactie naar A wordt gerepliceerd naar B VOORDAT B neemt zijn eerste schrijven. Als u gelijktijdige schrijfbewerkingen naar meer dan 2 masters toestaat, ... begrijpt u MySQL-replicatie op een DEEP-niveau beter of gaat u een wereld van pijn tegemoet. Extreme pijn. Zoals, heb je een kolom die AUTOINCREMENT is??? je bent genaaid (tenzij je even getallen gebruikt op de ene master en odds op de andere). Vertrouw NIET op MySQL-replicatie om "het juiste te doen". Het is NIET slim en zal je niet redden. Het is gewoon iets minder veilig dan het kopiëren van binaire transactielogboeken vanaf de opdrachtregel en ze met de hand opnieuw af te spelen. Toch kan het binnen enkele seconden worden gedaan om alle clients los te koppelen van de oude master en ze om te zetten naar de nieuwe master, veel sneller dan wachten op een schema-upgrade van meerdere uren.
  • Nu is meester B je nieuwe meester. Je hebt het nieuwe schema. Het leven is goed. Drink een biertje; het ergste is voorbij.
  • Herhaal het proces met Master A, upgrade zijn schema zodat hij je nieuwe secundaire master wordt, klaar om het over te nemen in het geval dat je primaire master (master B nu) de macht verliest of gewoon omhoog gaat en op je sterft.
  • li>

Een gemakkelijke manier om het schema bij te werken, is dit niet. Werkbaar in een serieuze productieomgeving; jawel. Alsjeblieft, alsjeblieft, alsjeblieft, als er een gemakkelijkere manier is om een ​​index toe te voegen aan een MySQL-tabel zonder schrijfbewerkingen te blokkeren, laat het me dan weten.

Googlen leidde me naar dit artikel die een vergelijkbare techniek beschrijft. Sterker nog, ze adviseren om op hetzelfde punt in de procedure te drinken (merk op dat ik mijn antwoord schreef voordat ik het artikel las)!

Percona's pt-online-schema-change

Het artikel Ik heb hierboven gesproken over een tool, pt -online-schema-verandering , dat werkt als volgt:

  • Maak een nieuwe tabel met dezelfde structuur als het origineel.
  • Schema op nieuwe tafel bijwerken.
  • Voeg een trigger toe aan de originele tabel zodat wijzigingen synchroon blijven met de kopie
  • Kopieer rijen in batches van de originele tabel.
  • Verplaats de originele tafel uit de weg en vervang deze door een nieuwe tafel.
  • Laat oude tafel vallen.

Ik heb de tool zelf nog nooit geprobeerd. YMMV

RDS

Ik gebruik momenteel MySQL via Amazon's RDS . Het is een heel handige service die MySQL afrondt en beheert, zodat u met één enkele knop nieuwe leesreplica's kunt toevoegen en de database transparant kunt upgraden voor alle hardware-SKU's. Het is echt handig. Je krijgt geen SUPER toegang tot de database, dus je kunt niet direct met replicatie rotzooien (is dit een zegen of een vloek?). U kunt echter Replica-promotie lezen om uw schemawijzigingen aan te brengen op een alleen-lezen slaaf en promoveer die slaaf vervolgens tot uw nieuwe meester. Precies dezelfde truc als ik hierboven heb beschreven, alleen veel gemakkelijker uit te voeren. Ze doen nog steeds niet veel om je te helpen met de overgang. U moet uw app opnieuw configureren en opnieuw opstarten.



  1. Hoe dubbele records te vinden met behulp van Group by and Having-clausule in SQL Server - SQL Server / TSQL-zelfstudie, deel 132

  2. Hoe wachtwoord versleutelen in Oracle?

  3. De functie Oracle REPLACE() verwerkt geen regelterugloop en regelinvoer

  4. Nummerreeks generator uitdaging oplossingen - Deel 3