Datenbank/Tabellen Sperren für Update?

Hi, und zwar habe ich folgende Struktur:
5 Rechner im Büro
1 Rechner im Netz (online).

Die 5 Rechner aktuallisieren alle 3 minuten eine Datenbank mit 5 Tabellen, mit teilweise über 100.000 Einträgen.

Diese Daten will ich im 3 Minuten-Takt online stellen. So… die Frage nu wie mach ich das am Besten.

Aktuell hab ich mir das so vorgestellt:

  1. Dump von Datenbank erstellen + packen (tar/rar)
  2. hochladen
  3. entpacken + dump in einem Temporäre Datenbank importieren
  4. Alle Tabellen Locken (da ich ja keine Datenbank locken kann)
  5. Alle Tabellen leeren
  6. Alle Tabllen mit neuen Werten füllen.

PS:
Cooler wäre natürlich, wenn man ein gesamten Datenbank-Lock auslösen könnte und einfach die Datenbanken umbenennt. Hab in der Doku gesucht, funktioniert leider nicht, oder jemand eine Idee?


Alternativ könnte man auch ein Synchronisations-programm dafür schreiben. Ich denke jedoch dass ich hier sehr viel länger für das Update brauche als sonst.

Am Besten soll sowas “dieser Switch neu <> alt” natürlich möglichst schnell funktionieren, damit externe das nicht merken.

Würd mich über ein paar Ideen freuen.

Was exakt spricht dagegen, die Updates in einer TX zu machen? In der Zeit, wo die TX läuft, sieht ein SELECT den alten Stand. Aber das wäre ja in Deinem Beispiel auch der Fall.

Andreas

Sry, eine TX? sprichst du damit von einer Transaktion über alle Tabellen? Wäre das nicht eine Nummer zu heftig für postgreSQL? Aber generell ist das wirklich ne super Idee. Von der Performance her, wird man nicht viel merken.

Sehe ich das richtig?

Jein. Angenommen, Du willst in table foo den Datensatz mit der id 4711 ändern:

begin;
select * from foo where id=4711 for update;
update foo set bla='bla' where id=4711;
commit;

Du brauchst also nicht nur lediglich die Tabellen zu sperren, sondern kannst das auch noch auf die Records eingrenzen, um die es geht.

Wäre das nicht eine Nummer zu heftig für postgreSQL?

Bitte was?

Aber generell ist das wirklich ne super Idee. Von der Performance her, wird man nicht viel merken.

Sehe ich das richtig?

Ja.

Andreas

Unschön ist hier, dass wieder mit einem anderen programm die sychronisation regeln muss. Update’s wird es eh nicht geben, primär delete (wenn niccht mehr vorhanden) oder insert wenn neu vorhanden.

Kann ich das nicht so lösen mit

begin;
delete from foo;
insert ....
end;

? :slight_smile:

Was ist daran umschön? Du machst einfach Dein DELETE bzw. INSERT. Was exakt mußt Du mittels externem Programm synchronisieren? Ist Dir der Begriff MVCC schon mal vor die Augen gekommen?

Multiversion Concurrency Control – Wikipedia

Vielleicht überrascht Dich das jetzt, aber: nix anderes macht PG.

Andreas

Okay, dann werd ich mal anfangen zu tippen. Mal schauen was bei raus kommt. Ich werd dann das Resultat hier posten. Erstmal danke akretschmer für deine Hilfe!

Omg.
denk denk denk … hab drei Tabellen. Die sind durchschnittlich:

         foo       foo1      foo2
---------------------------------------
size:   2.700   20.000   79.000

Das wäre doch zu heftig jede Minute über 100.000 Inserts Befehle auf die Datenbank loszulassen? :astonished:

naja mal abwarten was der Test zeigt.

Masseninserts macht man ja auch besser via COPY. Und wenn doch via INSERT: dann in einer TX.
Aber wenn Du das wirklich so brauchst, dann hast Du da sicher auch nicht nur eine schnelle Spindel, sondern das TX-Log z.B. auf einer eigenen, oder?

Andreas

Okay … öhm ja :slight_smile: Wat ist Spindel?

Rund, sich drehend.

Andreas

Also zu der Copy-Gesichte. D.h. Ich leg einfach ne Copy für jede Tabelle an, und kann diese dann wieder Online aufspielen. Hört sich ja ebenfalls vernünftig an.

Nein.

Hört sich ja ebenfalls vernünftig an.

PostgreSQL: Documentation: Manuals: PostgreSQL 8.3: COPY

Da da ja.

Andreas

Okay dann nicht :smiley:


Was spricht denn dagegen? Ich leg einfach jeweils Copy’s der Tabellen an. Pack den misst. Lad es hoch und spiel es einfach drauf:

BEGIN;
Delete from foo;
copy foo FROM file;
END;



BEGIN;
Delete from foo1;
copy foo1 FROM file;
END;

Okay, der erste Test scheint wohl gut zu laufen:

35.000 Datensätze

BEGIN;
TRUNCATE foo_stats;
COPY foo_stats FROM '/home/postgres/copy/foo_stats.copy';
END;
...

ca. 1.5 sec dauer. Parallel läuft die Plattform ohne probleme weiter. Bitte Einwände bringen, wenn etwas bedenklich ist? :frowning:

Spindel der Festplatte(n), auf denen deine Datenbank liegt.
Je mehr einzelne Spindeln du vorweisen kannst, desto bessere Schreibperformance wirst du bekommen. Wenn alle Daten auf eine einzelne Platte geschrieben werden müssen, dauert dies natürlich länger als wenn sich das Schreiben parallel auf 5 Platten verteilt.

Mach da mal lieber ein COMMIT; statt END; Ähm, TRUNCATE braucht einen exklusiven Lock, in der Zeit geht dann kein Select mehr bzw. TRUNCATE wartet, bis es einen bekommt. Dafür geht es schnell. Es arbeitet faktisch auf Dateiebene.

Andreas

Nachtrag:
Wenn PG eine Änderung in einer Tabelle macht, so zieht das Schreiboperationen in der der Tabelle zugörigen Datei, den Indexdateien und dem Transaction Log nach sich. Wenn man Performance will, teilt man diese Dinge (also table, index,tx-log) so auf, daß das dann auf physisch unterschiedlichen Platten liegt.

Andreas

Okay, das hört sich gut für Performance verbesserungen an. Thx.

Mal eine Frage, um zum ursprünglichen Problem zurückzukehren: wieviele Updates hast du in diesen Daten effektiv in welchem Zeitraum?