Ich war ein wenig zu entdecken überrascht , dass DDL - Anweisungen ( alter table
, create index
usw.) implizit die aktuelle Transaktion in MySQL begehen. Ausgehend von MS SQL Server war die Möglichkeit, Datenbankänderungen in einer Transaktion lokal vorzunehmen (die dann zurückgesetzt wurde), ein wichtiger Teil meines Workflows. Für die kontinuierliche Integration wurde das Rollback verwendet, wenn die Migration aus irgendeinem Grund fehlschlug, sodass die Datenbank zumindest nicht in einem halb migrierten Zustand belassen wurde.
Wie lösen die Leute diese beiden Probleme, wenn sie MySQL mit Migrationen und kontinuierlicher Integration verwenden?
mysql
transaction
ddl
rollback
Sennett
quelle
quelle
Antworten:
Für viele Menschen ist die MySQL-Achillesferse ein implizites Commit.
Gemäß Absatz 3 des Buches
Die folgenden Befehle können und werden eine Transaktion abbrechen
ALTER TABLE
BEGIN
CREATE INDEX
DROP DATABASE
DROP INDEX
DROP TABLE
RENAME TABLE
TRUNCATE TABLE
LOCK TABLES
UNLOCK TABLES
SET AUTOCOMMIT = 1
START TRANSACTION
VORSCHLAG
Wenn Sie in MySQL ContinuousIntegration (CI) / SelfService-Jobs erstellen, sollten sich Transaktionsjobs und DDL-Skripten immer gegenseitig ausschließen.
Dies gibt Ihnen die Möglichkeit, Paradigmen zu schaffen, die dies tun würden
START TRANSACTION/COMMIT
Blöcken isoliert sindWARNUNG: Wenn Sie hierfür MyISAM verwenden, können Sie MyISAM (un) freundlich zu der Liste der Dinge hinzufügen, die eine Transaktion unterbrechen können, möglicherweise nicht in Bezug auf das implizite Festschreiben, aber definitiv in Bezug auf die Datenkonsistenz, falls es jemals zu einem Rollback kommen sollte erforderlich.
WARUM NICHT LVM?
LVM-Snapshots eignen sich hervorragend, und die Wiederherstellung ganzer Instanzen von Datenbanken ohne umfangreiche SQL-Verarbeitung ist ideal. Bei MySQL müssen Sie jedoch zwei Speicher-Engines berücksichtigen: InnoDB und MyISAM.
All-InnoDB-Datenbank
Schauen Sie sich die Architektur von InnoDB an (Foto mit freundlicher Genehmigung von Percona CTO Vadim Tkachenko)
InnoDB hat viele bewegliche Teile
Das Erstellen eines LVM-Snapshots einer InnoDB-Datenbank mit nicht festgeschriebenen Änderungen im Pufferpool und im Speichercache würde zu einem Dataset führen, das eine Wiederherstellung nach dem Absturz von InnoDB erfordert, sobald die LUN wiederhergestellt und mysqld gestartet wurde.
VORSCHLAG FÜR ALL-InnoDB
Wenn Sie MySQL herunterfahren können, bevor Sie einen Schnappschuss machen
SET GLOBAL innodb_fast_shutdown = 0;
SET GLOBAL innodb_max_dirty_pages_pct = 0;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
service mysql stop
service mysql stop
Wenn Sie nicht herunterfahren können, sondern einen Schnappschuss mit MySQL Live machen
SET GLOBAL innodb_max_dirty_pages_pct = 0;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
SET GLOBAL innodb_max_dirty_pages_pct = 75;
All-MyISAM-Datenbank oder InnoDB / MyISAM-Mix
Wenn auf MyISAM zugegriffen wird, werden die Anzahl der geöffneten Dateizugriffsnummern beibehalten. Wenn MySQL abstürzt, wird jede MyISAM-Tabelle mit einer Anzahl offener Datei-Handles> 0 als Absturz markiert und muss repariert werden (auch wenn mit den Daten nichts falsch ist).
Wenn Sie einen LVM-Snapshot einer Datenbank erstellen, in der MyISAM-Tabellen verwendet werden, müssen eine oder mehrere MyISAM-Tabellen repariert werden, wenn der Snapshot wiederhergestellt und mysqld gestartet wird.
EMPFEHLUNG FÜR All-MyISAM oder InnoDB / MyISAM Mix
Wenn Sie MySQL herunterfahren können, bevor Sie einen Schnappschuss machen
SET GLOBAL innodb_fast_shutdown = 0;
SET GLOBAL innodb_max_dirty_pages_pct = 0;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
service mysql stop
service mysql stop
Wenn Sie nicht herunterfahren können, sondern einen Schnappschuss mit MySQL Live machen
Sie können ein Leeren bestimmter InnoDB-Tabellen erzwingen
SET GLOBAL innodb_max_dirty_pages_pct = 0;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
FLUSH TABLES innodb_tbl1,... FOR EXPORT;
auf kritische InnoDB - TabellenFLUSH TABLES WITH READ LOCK;
UNLOCK TABLES;
SET GLOBAL innodb_max_dirty_pages_pct = 75;
Könnte MySQL Replication helfen?
Sie können zwar einen LVM-Snapshot auf zwei Servern wiederherstellen und MySQL Master / Slave Replication einrichten, dies wird jedoch zu einer zusätzlichen Quelle für die Hausreinigung beim Wiederherstellen von Snapshots.
Wenn Sie CI-Jobs auf einem Master ausführen und diese Jobs klein sind, kann die Replikation unter bestimmten Umständen zu einer Zeitersparnis führen. Sie könnten einfach
STOP SLAVE;
auf dem Slave laufen , die CI-Jobs auf dem Master starten undSTART SLAVE;
auf dem Slave laufen, wenn die Daten des Masters zertifiziert sind.Wenn die CI-Jobs zu viele Daten melden, können Sie den LVM-Snapshot wiederherstellen und die Replikation von Grund auf einrichten. Wenn Sie dies häufig tun, können Sie möglicherweise MySQL Replication einrichten.
ABSCHLIESSENDE GEDANKEN
quelle
Wenn Sie von kontinuierlicher Integration sprechen, gehe ich davon aus, dass es sich um eine Entwicklungsumgebung handelt. In diesem Fall würde ich sagen, dass die Person, die strukturelle Änderungen vornimmt, diese testen muss, um sicherzustellen, dass die Dinge nicht für andere zerstört werden, ähnlich wie jemand, der eine gemeinsame Bibliothek aktualisiert: Testen Sie in Ihrer eigenen Sandbox, bevor Sie solche Änderungen vornehmen.
In einem Produktionsbereitstellungsprozess durchlaufen Sie normalerweise Entwicklungs-, Qualitätssicherungs- oder sogar Vorproduktionsumgebungen, um Ihre Änderungen zu testen, genau wie bei Codeänderungen.
Beachten Sie, dass dies nicht MySQL-spezifisch ist: Oracle-Datenbanken würden auch implizit COMMIT ausführen, wenn 'alter table' usw. ausgegeben wird.
Wenn Sie sich jetzt schützen möchten, können Sie natürlich vorher ein Backup oder einen LVM- oder Dateisystem-Snapshot erstellen, falls Ihr System dies kann. Möglicherweise haben Sie auch einen Slave, den Sie als Sicherheit vor vertraulichen Vorgängen verzögern / stoppen können.
quelle