ALTER TABLE mit Rails 3 und MySQL

Da nicht immer von Anfang an die Datenbank- bzw. Tabellenstruktur eindeutig ist und geänderte Anforderungen das Datenbankschema beeinflussen, müssen Anpassungen vorgenommen werden. Dies ist in der Regel einfach in den Migration-Scripten konfigurierbar. Mit dem vorgestellten Commit wird es in Zukunft in einer optimierteren Version als Bulk ablaufen.

Der erwähnte Commit ist im GitHub einsehbar (https://github.com/rails/rails/commit/30176f28a41681c7607eed39d03501327869d40c).

 

Das Problem, das bisher bei Änderungen an Tabellen bestand, war die Art wie MySQL diese ausführt. Wenn man von folgendem Beispiel ausgeht:
Es sollen zwei Spalten hinzugefügt werden und der Datentyp einer weiteren soll geändert werden.

[ruby]
change_table(:users) do |t|
t.string :im_handle
t.belongs_to :company
t.change :birthdate, :datetime
end
[/ruby]

 

Diese Migration führte bisher zu drei separat ausgeführten Befehlen:

 

[bash]
ALTER TABLE `users` ADD `im_handle` varchar(255)
ALTER TABLE `users` ADD `company_id` int(11)
ALTER TABLE `users` CHANGE `updated_at` `updated_at` datetime DEFAULT NULL
[/bash]

 

Diese Aktion ist bei kleinen Datenbanken „relativ“ unproblematisch, aber führt zu Problemen bei größeren.Denn wenn man einen Blick in die MySQL Dokumentation wirft, wird man feststellen, dass MySQL einiges im Hintergrund ausführt, um die Änderung durchzuführen. Die grobe Reihenfolge sieht ungefähr so aus:

 
  1. Die Tabelle wird gesperrt (lock). Kein UPDATE und INSERT mehr zugelassen
  2. Eine temporäre Kopie der Tabelle samt Inhalt wird angelegt
  3. Die gewünschten Änderungen werden auf die Kopie angewendet
  4. Die originale Tabelle wird durch die geänderte Kopie ersetzt
 

Wenn nun das oben gezeigte Beispiel ausgeführt wird, würden diese Schritte drei mal ausgeführt werden. Das ist nicht unbedingt performant und nicht immer gewünscht.

In den kommenden Rails-Versionen kann dieser Vorgang als Bulk durchgeführt werden. Dadurch werden alle Änderungen als einziger Befehl durchgeführt:

[ruby]
change_table(:users, :bulk => true) do |t|
t.string :im_handle
t.belongs_to :company
t.change :birthdate, :datetime
end
[/ruby]

Durch den zusätzlichen Parameter „bulk => true“ werden die einzelnen Statements zu einer zusammengefasst:

[bash]
ALTER TABLE `users` ADD COLUMN `im_handle` varchar(255), ADD COLUMN `company_id` int(11), CHANGE `updated_at` `updated_at` datetime DEFAULT NULL
[/bash]

Dadurch werden Datenbankänderungen in Zukunft nicht nur schneller sondern auch atomarer.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.