Mittwoch, 23. Januar 2013

Schulungen für PostgreSQL Administratoren

  • PostgreSQL richtig administrieren, pflegen und warten
  • Welche Hardware ist sinnvoll für meine Datenbank
  • Was ist an Linuxtuning erforderlich, damit meine Datenbank schneller läuft?
  • An welchen internen PostgreSQL-Stellschrauben kann gedreht werden, um aus meinem Datenbank-Traktor einen Rennwagen zu machen.
  • Welche Backup-Strategien gibt es, was sind die Vor- und Nachteile
  • Welche Hochverfügbarkeitsstrategien gibt es, was sind die Vor- und Nachteile
  • Welche Replikationsstrategien gibe es, was sind die Vor- und Nachteile
  • Was ist Vacuum? Was macht Analyze?
  • Wie wende ich EXPLAIN an? Wie lese ich es? Wie werte ich es aus?
  • Was ist für das SQL Tuning zu beachten?
  • Wie arbeitet der Optimizer?
  • Wie speichert PostgreSQL die Daten auf der Festplatte ab?
  • ...
Diese und andere Fragen werden in unserem 3-Tages Training für PostgreSQL-Administratoren beantwortet.

Unsere neuen Schulungstermine stehen fest.

http://2ndquadrant.de/postgresql-training/

Buchen Sie eine unserer PostgreSQL Schulung wahlweise in Berlin, Bielefeld oder Köln.

Dienstag, 22. Mai 2012

Call for Paper für die FrOSCon

Es ist wieder soweit. Am 25./26. August findet an der Hochschule Bonn-Rhein-Sieg die FrOSCon (Free and Open Source Software Conference) statt (http://froscon.org).

Ein Event, dass man sich auf keinen Fall entgehen lassen sollte.

Dieses Jahr habe ich die Ehre, den Vortragsraum für Rechtsthemen zu betreuen.

Wünschenswert wären hier Vorträge rund um das Thema Lizenzen. Aber auch Vorträge zum Thema, was sollte bei der Mitwirkung an einem Open Source
Projekt beachtet werden oder wie veröffentliche ich ein Open Source Projekt? Was sollte beachtet werden? Wie sieht das mit Spenden für Open Source Projekte aus? Wann und wie darf ein Open Source Projekt eingesetzt werden? und so weiter ...
Rechtliche Themen die für Anwender und Mitwirkende von Interesse sind.

Es wäre schön, wenn sich hier ein paar Vortragende finden ließen. Bitte reicht Eure Vorträge bis zum 27. Juni bei der FrOSCon ein (http://cfp.froscon.org).

Daneben gibt es dieses Jahr einen Vortragsraum über beide Tage zu dem Thema Open Source Software Datenbanken. Hier finden Vorträge zu allen Open Source Software Datenbank-Systemen statt, wie beispielsweise PostgreSQL oder MySQL bzw. MariaDB. Auch hier nutzen wir das Vorschlagsportal der FrOSCon.

Bitte reicht auch hierfür eure Vorträge rund um OSS Datenbanken bis zum 27. Juni bei der FrOSCon ein (http://cfp.froscon.org).

Mittwoch, 16. November 2011

PostgreSQL und die Luftblasen in Indexen

B-Tree Indexe sind, wie der Name schon sagt, Indexe, die nach dem B-Baum Prinzip abgespeichert werden.

Details zum Thema B-Baum lassen sich bei Wikipedia nachlesen:
http://de.wikipedia.org/wiki/B-Baum

Passieren viele Veränderungen auf den Index - viele Updates auf den indizierten Spalten bzw. viele Deletes - so kann sich der Index bei PostgreSQL aufblähen.
Durch dieses Operationen kann es passieren, dass der Baum nicht mehr richtig ausbalanziert ist. Natürlich dauert es länger, einen nicht-ausbalancierten Baum zu durchsuchen, als einen ausbalancierten Baum.

Wie aber kommt es dazu?
Wie lässt es sich Monitoren?
Wie lässt es sich beheben?


Bei PostgreSQL sind die Index-Pages (Blätter) 8 kB groß.

Ist die Page voll und es kommt ein neuer Wert dazu, der in diese Page einsortiert werden müsste, so wird die Page geteilt. Wenn beim Anlegen eines Indexes alle Pages zu 100% gefüllt werden, kann es passieren, dass gleich beim ersten Wert, der neu dazukommt, es zu einer Page-Teilung kommt. Um dieses zu verhindern, lässt sich bei der Indexerstellung angeben, wie voll die Pages beim Anlegen gepackt werden dürfen. Default ist 90. Das bedeutet, die Pages werden, wenn sie angelegt werden, maximal zu 90% gefüllt. Je kleiner der Fillfactor, um so mehr Speicherplatz wird benötigt. Hier ein Beispiel mit einer einfachen Tabelle und einem Index mit 50% Füllung, einem mit den 90% aus dem Default und einem mit 100%.

CREATE TABLE t(i INTEGER, j INTEGER);
INSERT INTO t VALUES (generate_series(1,10000), random()*100+1);
CREATE INDEX i_fillfactor_default ON t(j);
CREATE INDEX i_fillfactor50 ON t(j) WITH (fillfactor=50);
CREATE INDEX i_fillfactor100 ON t(j) WITH (fillfactor=100);

SELECT
relname,
pg_size_pretty(relpages * 8 * 1024) AS size,
relpages,
reltuples
FROM pg_class
WHERE oid > 17000 ORDER BY relpages desc;

relname size relpages reltuples
t 360 kB 45 10000
i_fillfactor50 336 kB 42 10000
i_fillfactor_default 192 kB 24 10000
i_fillfactor100 176 kB 22 10000

Wie erwartet ist der Index mit nur halb gefüllten Pages ungefähr doppelt so groß wie der vollgefüllte.

Jetzt erzeugen wir mal etwas Traffic:

DELETE FROM t WHERE j > 50;
INSERT INTO t values (generate_series(10001,20000), random()*100+1);
UPDATE t SET j=103 WHERE j=47;
UPDATE t SET j=104 WHERE j=42;
DELETE FROM t WHERE j BETWEEN 23 AND 25;
INSERT INTO t values (generate_series(20001,25000), random()*100+1);

SELECT
relname,
pg_size_pretty(relpages * 8 * 1024) AS size,
relpages,
reltuples
FROM pg_class
WHERE oid > 17000 ORDER BY relpages desc;

relname size relpages reltuples
t 720 kB 90 19324
i_fillfactor100 584 kB 73 19324
i_fillfactor_default 568 kB 71 19324
i_fillfactor50 568 kB 71 19324

Zu sehen ist hier, dass die Tabelle ca. um das doppelte gewachsen ist. Von 360 kB auf 720 kB. Von vorher 10000 Zeilen auf 19324 Zeilen. Der 100% Index ist jedoch um mehr als das dreifache gewachsen und der Default-Index ebenfalls fast um das dreifache. Obwohl die Tabelle doppelt so groß geworden ist, ist der 50% Index nur um 60% gewachsen.

Um die Indexe zu bereinigen, können zwei Wege eingeschlagen werden. Zum einen kann ein REINDEX durchgeführt werden. Der Nachteil dabei ist, es wird gelockt. Während REINDEX läuft, müssen Schreibzugriffe warten. Auch Lesezugriffe, die den Index verwenden möchten, müssen warten.

PostgreSQL kennt jedoch CREATE INDEX CONCURRENTLY, bei dem weder Schreib- noch Lesezugriffe geblockt werden. Es kann hiervon jedoch nur ein Index pro Tabelle zur selben Zeit angelegt werden. Ein normaler CREATE INDEX würde jedoch auch wieder Schreibzugriffe blockieren.

Die komfortableste Lösung ist daher den Index mit CONCURRENTLY neu anzulegen, danach den alten Index zu droppen und ggf. danach noch mit Hilfe von RENAME den Namen von dem neuen Index auf den Namen von den alten Index zu setzen. Im Beispiel habe ich den 100er Index mit REINDEX bearbeitet und für die beiden anderen zwei neue Indexe erstellt:

REINDEX INDEX i_fillfactor100;
CREATE INDEX CONCURRENTLY i_fillfactor_default2 ON t(j);
CREATE INDEX CONCURRENTLY i_fillfactor_50_2 ON t(j) WITH (fillfactor=50);

Hier das Zwischenergebnis:

SELECT
relname,
pg_size_pretty(relpages * 8 * 1024) AS size,
relpages,
reltuples
FROM pg_class
WHERE oid > 17000 ORDER BY relpages desc;

relname size relpages reltuples
t 720 kB 90 19324
i_fillfactor_50_2 632 kB 79 19324
i_fillfactor_default 568 kB 71 19324
i_fillfactor50 568 kB 71 19324
i_fillfactor_default2 360 kB 45 19324
i_fillfactor100 328 kB 41 19324


Jetzt noch die alten Indexe löschen und die neuen umbenennen:

DROP INDEX i_fillfactor_default;
ALTER INDEX i_fillfactor_default2 RENAME TO i_fillfactor_default;
DROP INDEX i_fillfactor50;
ALTER INDEX i_fillfactor_50_2 RENAME TO i_fillfactor50;

SELECT
relname,
pg_size_pretty(relpages * 8 * 1024) AS size,
relpages,
reltuples
FROM pg_class
WHERE oid > 17000 ORDER BY relpages desc;

relname size relpages reltuples
t 720 kB 90 19324
i_fillfactor50 632 kB 79 19324
i_fillfactor_default 360 kB 45 19324
i_fillfactor100 328 kB 41 19324

Schön zu sehen ist, dass der 50% Index gewachsen, statt geschrumpft ist. Die beiden anderen sind jedoch extrem geschrumpft.

Fazit

Bei viel Bewegung auf der Tabelle ist es besser einen Index mit einem kleineren Fillfactor zu verwenden. Die Indexgröße und die Tabellengröße sollten beobachtet werden. Ist das Wachstum des Index erheblich größer als das Wachstum der regelmäßig und korrekt gevacuumten Tabelle, so hat sich der Index aufgebläht und eine Bereinigung ist notwendig.

Dieses und andere Themen behandeln wir in unseren Schulungen: http://www.2ndquadrant.de

Donnerstag, 20. Oktober 2011

Technische Unterschiede PostgreSQL, MySQL, MariaDB - Teil 9

Die vorangegangenen Teile dieser Artikelserie sind hier:


  1. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql.html 
  2. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql_30.html
  3. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql_31.html
  4. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql.html
  5. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_02.html
  6. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_06.html
  7. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_16.html
  8. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_28.html 
Datentypen

PostgreSQL hat eine ganze Reihe von eigenen Datentypen, die nicht im SQL Standard erfasst sind. Auch MySQL kennt ein paar mehr als der Standard. Daneben besteht in PostgreSQL noch die Möglichkeit eigene Datentypen zu kreieren.

Ich gehe hier nur auf die wichtigsten Datentypen ein:

PostgreSQL hat Boolean implementiert - bei MySQL ist Boolean nur ein
Alias auf Tinyint (1 Byte). Ein NOT NULL Boolean lässt sich bei MySQL auch
durch einen CHAR(0) simmulieren. CHAR(0) lässt genau zwei Werte zu: NULL und Empty String. Es bleibt dabei dem Anwender überlassen was er als TRUE und was als FALSE definiert.

Tinyint (1 Byte), Mediumint (3 Byte) sind MySQL eigene. Daneben kann in
MySQL noch zwischen signed und unsigned unterschieden werden.

Smallint (2 Byte), Integer (4 Byte) und Bigint (8 Byte) sind in beiden
Systemen vorhanden.

Verwirrend ist hier nur, dass MySQL von INT(m) spricht. Das m steht nicht
etwa für die Bittigkeit. NEIN!! Auch ein INT(27) ist ein normaler 4-Byte
Integer und kein Bigint. Die Zahl sagt nur aus, mit wievielen Leerzeichen
die Ausgabe ausgefüllt werden soll, damit die Zahlen rechtsbündig
untereinander stehen.

Decimal und Numeric sind SQL Standard. Beide sind bei beiden implementiert. Bei PostgreSQL ist Decimal ein Alias auf Numeric, bei MySQL ist es genau anders herum.


Float, Real und Double Precision sind SQL Standard Typen.
PostgreSQL hat Real (4 Byte) und Double Precision (8 Byte) implementiert. Float ist bei PostgreSQL ein Alias für Double Precision.

MySQL kennt Float (4 Byte) und Double (8 Byte). Real ist ein Alias auf Float
und Double Precision ein Alias auf Double. Gerechnet wird bei MySQL jedoch immer mit Double Precision, was bei der Verwendung von Float zu erheblichen
Rundungsfehlern führen kann.

Char und Varchar kennen beide.
Darüber hinaus kennen beide den nicht im Standard stehenden Datentyp Text.

Bei MySQL zählt Text jedoch zu den Blob-Typen. Bei PostgreSQL zu Varchar.
Von diesen Dreien ist bei MySQL Char der schnellste und Text der
langsamste Datentyp. Bei PostgreSQL sind alle drei gleich schnell.
MySQLs Varchar kann maximal eine Länge von 2¹⁶-1 haben. Char ist bei MySQL auf 255 Zeichen beschränkt.

MySQL kennt verschieden Blob-Datentypen. PostgreSQL nutzt hier Bitea.

Date kennen beide. PostgreSQL kann hier noch mit vorchristlichen Daten
umgehen, MySQL nicht.

Der SQL Standard sagt Time und Timestamp sind ohne Angabe einer Zeitzone.
Time bzw. Timestamp with timezone sind mit Angabe der Zeitzone.
PostgreSQL hat dieses auch brav genau so implementiert. Auch der im Standard stehen Datentyp Interval ist bei PostgreSQL vorhanden.

MySQL kennt die Datentypen WITH TIMEZONE nicht. Es kenn auch den Datentyp Interval nicht. Es kennt Time, Timestamp und Datetime. Den wesentlichen Unterschied von Datetime und Timestamp habe ich schon erklärt. Die Zeitzone wird hier nicht festgehalten. Der Unix-Timestamp wird hier anhand der im Server eingestellten Zeitzone berechnet. Bei MySQL ist es daher wichtig, dass alle Zeiten mit selber Zeitzone in die Datenbank gelangen.

Die Funktionen und Berechnungsformeln für Datums- und Zeitdatentypen
sind erheblich unterschiedlich.

Nicht Standard aber nützlich sind in MySQL noch der Datentyp Enum, der in
PostgreSQL erst selbst erstellt werden muß, bevor er verwendet werden kann.
Und in PostgreSQL der Datentyp Array, der in MySQL nicht existiert.

Fortsetzung folgt ...

Mittwoch, 28. September 2011

Technische Unterschiede PostgreSQL, MySQL, MariaDB - Teil 8

Die vorangegangenen Teile dieser Artikelserie sind hier:

  1. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql.html 
  2. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql_30.html
  3. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql_31.html
  4. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql.html
  5. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_02.html
  6. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_06.html
  7. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_16.html
SQL-Standard

Sowohl PostgreSQL als auch MySQL versuchen so nah wie möglich am SQL-Standard zu bleiben und soviel wie möglich standardkonform zu implementieren. Beide sind daneben so ehrlich, dass sie in der Dokumentation herausstellen, wann sie vom Standard abweichen.

Die größte Abweichung vom Standard haben beide in der Implementierung von Identifier (Bezeichnern). Der Standard schreibt hier etwas von Identifier sollen per Default nur aus Großbuchstaben bestehen. PostgreSQL fand das schon im letzten Jahrhundert unzeitgemäß und implementierte genau das Gegenteil:

Bei PostgreSQL bestehen Identifier per Default nur aus Kleinbuchstaben. Somit ist PostgreSQL bei Identifiern case-insensitive.

MySQL kämpft hier mit weitaus größeren Problemen. Spalten- und Indexname sowie Namen für Funktionen und Prozeduren werden auch bei MySQL zu Kleinbuchstaben und sind case-insensitive. Trigger hingegen sind case-sensitive. Daneben hat MySQL ein weitaus größeres Problem mit Datenbank / Schema und Tabellennamen. Diese werden direkt auf dem Dateisystem abgelegt und es hängt vom Dateisystem ab, ob sie case-sensitive oder case-insensitive sind. Windows-Dateisysteme sind eigentlich immer case-insensitive und Unix-Dateisystem case-sensitive. Wird unter MacOS UFS genutzt, so sind Tabellen und Datenbanknamen case-sensitive. Wird das MacOS-Dateisystem HFS+ genutzt, sind sie case-insensitive. Durch setzen von lower_case_table_names kann das Verhalten geändert werden.

Als Sprachen, die zur Programmierung von Funktionen und Prozeduren verwendet werden, hat sich MySQL als einziges, der gängigen Systeme an den SQL Standard gehalten und SQL implementiert. Die SQL-Implementierung in PostgreSQL ist eher spärlich und beschränkt sich auf die ganz rudimentären Dinge.

PostgreSQL hat jedoch die eigene Sprache Pl/PgSQL implementiert, mit der sich auch komplexe Funktionen und Prozeduren schreiben lassen.

Mir persönlich ist noch keine produktive Datenbank mit Funktionen und Prozeduren begegnet, in der ich die Funktionen / Prozeduren nicht hätte sowohl in SQL als auch in Pl/PgSQL zusammenstricken können.

Mir sind sowohl in MySQL schon Funktionen / Prozeduren begegnet, bei denen ich mir dachte, dass wäre mit Pl/PgSQL einfacher gewesen als auch Funktionen in PostgreSQL bei denen die Umsetzung in SQL einfacher gewesen wäre. Daher denke ich, SQL versus Pl/PgSQL ist lediglich eine Frage der Gewohnheit.

Anzumerken ist hier - der Hauptunterschied, den der SQL Standard zwischen Funktionen und Prozeduren festlegt ist, dass Prozeduren keinen Rückgabewert haben. PostgreSQL hat das so interpretiert und implementiert, dass Prozeduren einfach Funktionen sind, die VOID zurückgeben. Prozeduren werden daher bei PostgreSQL auch nicht mit CALL aufgerufen, sondern genauso behandelt, wie andere Funktionen auch. Als Beispiel:

SELECT prozedur() statt CALL prozedur()

Neben Pl/PgSQL bietet PostgreSQL noch eine Reihe von anderen Sprachen an, in denen Funktionen geschrieben werden können. Die Palette ist lang und enthält alle gängigen Programmiersprachen wie PHP, Perl, C, Java, Ruby, ....

MySQL bietet die Möglichkeit User Defined Functions in C zu schreiben. Das würde ich persönlich aber eher als Qual als als Wahl bezeichnen.

Beim Thema Funktionen und Prozeduren stellt sich auch schnell die Frage, wo die Logik sinnvoller aufgehoben ist. In der Anwendung selbst oder in der Datenbank:

Ich sah einst eine fürchterlich aufwendige Pl/SQL-Funktion (Oracle) die alle eingebenen Umlauten in HTML-Code (z.b. ä für ä) wandelte. Die Programmiersprache, in der die Anwendung geschrieben war, verfügte bereits schon über eine solche Funktion. Heisst, in der Anwendung selbst war es ein Einzeiler. Warum hier also die Datenbank bemühen, wenn die Anwendung das viel besser kann?

Datenbanklogik gehört in die Datenbank, Anwendungslogik in die Anwendung. Die Grenze hier ist manchmal grau.

Genauso häufig wie man bei vielen MySQL-Anwendungen schreien könnte, weil Datenbanklogik in die Anwendung gepackt wurde, könnte man bei PostgreSQL-Anwendungen schreien, weil Anwendungslogik in die Datenbank gepackt wurde.

Wer wirklich nur Datenbanklogik in die Datenbank packt, kommt mit SQL genauso weit, wie mit Pl/PgSQL.

Constraints sind Bedingungen. Der Standard sieht sechs Constraints vor:
  • Not NULL
  • Unique
  • Default
  • Primary Key
  • Foreign Key
  • Check
PostgreSQL hat alle implementiert, InnoDB alle bis auf Check Constraints.

Beide lösen die Implementierung von Primary Key als NOT NULL Constraint plus Unique Index. Beide lösen die Implementierung von Unique als Unique Index.

Wie wichtig oder unwichtig CHECK Constraints sind, ist anwendungsabhängig.

Check Constraints können häufig mehr Schaden als Nutzen.

Check Constraints helfen nur bei Eingaben - also bei INSERT und UPDATE.

In den meisten Fällen, werden die Eingaben schon in der Anwendung geprüft, bevor sie zur Datenbank geschickt werden. Ein häufiger Grund hierfür ist, SQL-Injections zu vermeiden.

Warum dann also ein Check-Constraint als Bremse einbauen, dass die Eingabe nochmals prüft?

Daneben sind Verbindungen bei PostgreSQL teuer. Warum also eine teure Verbindung aufmachen, um eine Eingaben prüfen zu lassen? Bei Fehlschlag
bräuchte ist dann, nach Eingabekorrektur, nochmals eine Verbindung nötig. Ist es da nicht sinnvoller, die Daten werden in der Anwendung geprüft und gleich richtig übergeben?

Ich persönlich habe bei PostgreSQL, abgesehen von Partitionierung, noch keinen Anwendungsfall für Check-Constraints gesehen, wo die Eingabeprüfung nicht besser in der Anwendung aufgehoben war.
  • NULL bedeutet unbestimmt / unbekannt
  • NULL ist weder 0 noch Leerstring noch 00-00-0000 00:00:00.
  • NULL ist weder gleich noch nicht gleich NULL, sondern NULL.
PostgreSQL ist hier standardkonform. Wird für eine Zelle nichts angegeben und ist die Spalte nicht NOT NULL, so ist die Zelle NULL.

Das ist für die meisten Datentypen bei MySQL auch so. Allerdings kann MySQL mit NULL im Datentyp timestamp nicht umgehen. Hier ist per Default im ersten Timestamp der Default current_timestamp und in folgenden 00-00-0000 00:00:00. Der Datentyp datetime kann mit NULL umgehen und sollte verwendet werden, wenn das Verhalten von Timestamp missfällt.

Indexe sind nicht SQL Standard. Beide, sowohl PostgreSQL als auch MySQL behelfen sich mit Indexen wenn es um UNIQUE Constraints geht. Der Primary Key ist ein Zusammenschluß aus NOT NULL und UNIQUE Constraint. Daher wird hier sowohl für UNIQUE als auch für PRIMARY KEY ein Unique Index angelegt.

Zusätzlich legt InnoDB für jeden Foreign Key automatisch einen Index an.

Fortsetzung folgt ....

Samstag, 17. September 2011

Die Lichtgeschwindigkeit und Synchrone Replikation

Welche Strecke legt das Licht in einem Takt zurück?

Wir erinnern uns:

Die Lichtgeschwindigkeit sind rund 300 Tausend km/s.
Das macht 3 * 10⁸ m/s.

Rechner haben eine Frequenz von 3 GHz.
Das sind rund 3 * 10⁹ Takte.

Wieviel Meter legt jetzt das Licht in einem Takt zurück?

3 * 10⁸  m/s : 3 * 10⁹ Hz = 0,1 m = 10 cm

Da das rund gerechnet ist kann man auch sagen 10 cm sind 4 Zoll.

Two Phase Commit

Beim Two Phase Commit wird ...

       1.1. ein Prepare gesendet
       1.2. ein Ready zurückgesendet
       2.1. ein Commit gesendet
       2.2. ein ACK zurückgesendet

Das sind vier Wege - die zurückgelegt werden.

10 cm : 4 Wege = 2,5 cm/Weg oder auch rund 1 Zoll.

Eine CPU hat üblicher Weise 1" x 1" im Quadrat. 

Quelle: Kristian Köhntopp auf der PHP Unconference in Hamburg 2011
Eine verdammt kurze Strecke oder?

Synchrone Replikation

Hier gibt es zwei Theorien:
  1. ACK wird erst dann zurückgesendet, wenn die Daten garantiert permanent auf der anderen Seite gespeichert sind
  2. ACK wird schon dann zurückgesendet, wenn die Daten auf der anderen Seite angekommen sind.
Ein Datentransfer kann nicht schneller sein, als die Lichtgeschwindigkeit (noch nicht). In der ersten Theorie kommt daneben noch die mechanische Trägheit der Festplatte als Bremse hinzu.

Wie oben gezeigt, legt das Licht während eines Taktes nur 10 cm zurück.

Hier müssten mindestens zwei Wege zurückgelegt werden:
  1. Die Daten senden
  2. ACK zurücksenden
10 cm : 2 = 5 cm

Wenn der Replikationsserver 15000 km entfernt steht - müssten 30000 km zurückgelegt werden.

Lichtgeschwindigkeit: 3 * 10⁵ km/s

3 * 10⁵ km/s : 3 * 10⁴ km = 10 Transaktionen pro Sekunde

Bei 150 km Entfernung kommt man so auf 1000 Transaktionen pro Sekunde.

Aber alles nur in der Theorie - weil in der Praxis noch andere Faktoren das ganze ausbremsen.

Die Frage die sich daraus ergibt:

Will man wirklich synchrone Replikation oder ist asynchrone Replikation ausreichend?

Freitag, 16. September 2011

Technische Unterschiede PostgreSQL, MySQL, MariaDB - Teil 7

Die vorangegangenen Teile dieser Artikelserie sind hier:
  1. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql.html 
  2. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql_30.html
  3. http://miraspostgresqlwelt.blogspot.com/2011/08/technische-unterschiede-postgresql_31.html
  4. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql.html
  5. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_02.html
  6. http://miraspostgresqlwelt.blogspot.com/2011/09/technische-unterschiede-postgresql_06.html 
Wie ist das jetzt genau mit den Transaktionen und dem Redo?

Aufgrund vieler Nachfragen zu genau diesem Thema, werde ich es vorziehen und schon heute darauf tiefer eingehen.

Wie bereits erwähnt loggen sowohl PostgreSQL als auch InnoDB abgeschlossene Transaktionen. Ebenfalls bereits erwähnt hatte ich, dass bei PostgreSQL die Blöcke in der Regel 8 kB groß sind und bei InnoDB 16 kB.

Checkpoints sorgen bei beiden dafür, dass die Änderungen permanent gespeichert werden.

Geänderte Blöcke zwischen zwei Checkpoints werden dirty pages genannt.

InnoDB überträgt nur die geänderten Bereiche eines geänderten Blocks in das Log.

Wird bei PostgreSQL nach einem Checkpoint zum ersten Mal ein Block geändert, dann schreibt PostgreSQL den gesamten Block ins Redo-Log.

Wird ein Block dann nochmal geändert, bevor der nächste Checkpoint passiert, dann wird bei PostgreSQL, genau wie InnoDB nur die Änderung festgehalten.

Bei einem Checkpoint schreiben beide die dirty pages auf die Platte.

InnoDB schreibt dabei die dirty pages zweimal auf die Platte. Zuerst einmal in den Double Write Buffer und danach an die eigentliche Position. Auf diese Weise hat InnoDB eine Kopie der Page, die es zur Rekonstruktion verwenden kann, falls der Server während des Schreibens an die eigentliche Position crashed (z.B. bei einem Stormausfall).

PostgreSQL hat keinen Double Write Buffer. Es schreibt die dirty pages direkt an die eigentliche Position. Da PostgreSQL bei der ersten Änderung nach einem Checkpoint die Page komplett ins Redo-Log geschrieben hat, hat es hier eine Kopie der Page, auf die es zurückgreifen kann, wenn beim Schreiben der Strom ausgefallen ist. Zur Rekonstruktion angelt sich PostgreSQL die Page aus dem Redo und patched die weiteren Änderungen, die weiter hinten im Redo-Log stehen, einfach in die Page hinein.

Das speichern der gesamten Page im Redo ersetzt bei PostgreSQL den Double Write Buffer von InnoDB.

Je weniger Checkpoints umso mehr einzelne geänderte Zeilen stehen im Redo und umso länger dauert somit die Rekonstruktion. Bei PostgreSQL lassen sich die Checkpoints konfigurieren. InnoDB nutzt andere Algorithmen hier und die Konfiguration der Checkpoints ist nicht so ohne weiteres möglich.

Fortsetzung folgt ....