Wie kann ich MySQL Innodb so konfigurieren, dass 1000 Einfügungen pro Stunde verarbeitet werden?

10

Ich habe eine sehr stark frequentierte Website, auf der möglicherweise jede Stunde Tausende neuer Datensätze eingefügt werden.

Dieser eine Fehler lähmt die Site:

PDOException: SQLSTATE[40001]: Serialization failure: 1213 
Deadlock found when trying to get lock; 
try restarting transaction: INSERT INTO {location_instance} 
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0, 
:db_insert_placeholder_1, :db_insert_placeholder_2, 
:db_insert_placeholder_3, :db_insert_placeholder_4); 
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] => 
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] => 
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )

Ich wäre sehr überrascht, wenn MySQL diese Art von Last nicht bewältigen könnte. Meine Fragen sind also: Ist dies ein Datenbankproblem und wie kann ich MySQL so konfigurieren, dass es so viel Verkehr verarbeiten kann?

Ich habe eine Kopie meiner Website auf einem Entwicklungsserver mit Skripten eingerichtet, die das Laden von Inhalten simulieren, die der Website hinzugefügt werden. Ich verwende Ubuntu, LAMP-Stack, mit 16 GB RAM.

Zugegeben, ich kenne mich mit Datenbanken nicht sehr gut aus. Tatsächlich beginne ich mit der Standardeinstellung my.cnf, die nach Abschluss der 'apt-get-Installation' mitgeliefert wird. Tische sind alle Innodb. Welche Startkonfigurationseinstellungen und -ansätze würden Sie empfehlen, um dieses Problem zu lösen?

Lassen Sie mich wissen, welche weiteren Informationen Sie möglicherweise benötigen.

Vielen Dank

user658182
quelle
Sie beginnen mit der Standardeinstellung my.cnf für die Produktion? Mann, du musst es mehr optimieren. Ich werde Sie in meiner Antwort näher erläutern. :-)

Antworten:

11

Sie haben es mit einem Deadlock zu tun, nicht mit einem Leistungsengpass.

Wenn Sie tausend neue Datensätze pro Stunde haben, sind Sie weit davon entfernt, die MySQL-Grenzen zu erreichen. MySQL kann mindestens das 50-fache Ihrer Last verarbeiten.

Deadlocks werden durch den Anwendungscode verursacht und sind nicht die Schuld des Datenbankservers. Deadlocks können auf der MySQL-Serverseite nur in bestimmten Situationen behoben werden.

InnoDBkann Ihnen detaillierte Deadlock-Informationen anzeigen, indem Sie SHOW ENGINE INNODB STATUSan der MySQL-Eingabeaufforderung oder mit ausführen mysql -uroot -p... -e "SHOW ENGINE INNODB STATUS".

Dies zeigt jedoch nur den letzten aufgetretenen Deadlock an, es gibt kein Deadlock-Protokoll.

Zum Glück gibt es ein Tool pt-deadlock-logger, das sich um dieses Problem kümmert, sich um den Abfragestatus kümmert InnoDBund alle detaillierten Deadlock-Informationen speichert, bevor es mit einem neuen Deadlock aktualisiert wird.

Tapferkeit
quelle
Gut zu wissen! Ich sehe im Befehl show status die Informationen über die Sperre und die zugehörige Abfrage und Tabelle. Wie kann ich diese Informationen aus dem Statusbefehl verwenden, um mit dem Debuggen des Problems zu beginnen, da dies in meinem Code enthalten ist? Die PHP-PDO-Abfrage ist ziemlich einfach - verbinden, vorbereiten, ausführen, wiederholen. Ich würde gerne einen Code oder die Statusmeldung posten, wenn das helfen würde.
user658182
@ user658182 Überprüfen Sie diesen Beitrag auf Stackoverflow, wie man mit Deadlocks umgeht: Wie vermeide
Valor
1
@ max-vernon danke für die syntax edit, klar englisch es ist nicht meine muttersprache :-).
Tapferkeit
1
-e "SHOW ENGINE INNODB STATUS"
Glyphe
8

Dies kann so einfach sein wie ein Teil Ihres Codes, der eine Transaktion ausführt:

insert into t1...
insert into t2...
commit;

Während ein anderer Teil Ihres Codes dieselben Tabellen in einer anderen Reihenfolge ändert:

delete from t2 where...
delete from t1 where...
commit;

Wenn beide Transaktionen gleichzeitig ausgeführt werden, kann eine Race-Bedingung auftreten: Die erste Transaktion kann nicht geändert werden, t2da sie von der zweiten Transaktion gesperrt wird. während die zweite Transaktion ähnlich blockiert ist, weil t1sie von der ersten Transaktion gesperrt wird. MySQL wählt eine Transaktion als "Opfer" aus, bei dem INSERT / UPDATE / DELETE fehlschlägt. Die Anwendung muss diesen Fehler abfangen und die Anweisung erneut versuchen - möglicherweise nach einer Pause, damit die andere Transaktion Zeit zum Abschluss hat. Nichts mit Kapazitätsbeschränkungen zu tun, nur unglückliches Timing, das durch die Anordnung des Codes noch verschärft werden kann. Schalten Sie die DELETEs in Transaktion 2 oder die INSERTs in Transaktion 1 um, und dann liegt kein Konflikt vor. Jede Transaktion wartet auf den Zugriff auf die benötigten Tabellen.

In MySQL 5.6 können Sie mit aktivierter Option innodb_print_all_deadlocks ausführen , um Informationen zu allen Deadlocks (nicht nur zu den neuesten) im MySQL-Fehlerprotokoll zu sammeln.

[Obligatorischer Haftungsausschluss: Ich bin ein Oracle-Mitarbeiter. Das Obige ist meiner persönlichen Ansicht nach keine offizielle Aussage.]

Max Webster
quelle