2015-03-30 6 views
7

Der Anwendungsfall, um dies mit ansible zu automatisieren. Ich möchte Datenbank-Dump nur importieren, wenn die Datenbank vollständig leer ist (keine Tabellen im Inneren). Natürlich gibt es immer eine Möglichkeit, SQL-Anweisungen auszuführen, aber dies ist der letzte Ausweg, ich glaube, dass es elegantere Lösungen dafür geben sollte.PgSQL - Wie Datenbank-Dump nur zu importieren, wenn die Datenbank vollständig leer ist?

pg_restore Handbuch bietet diese Option nicht, soweit ich sehe.

Hier ist, wie ich plane, diese mit ansible zu tun:

- name: db_restore | Receive latest DB backup 
    shell: s3cmd --skip-existing get `s3cmd ls s3://{{ aws_bucket }}/ | grep sentry | tail -1 | awk '{print $4}'` sql.latest.tgz 
    args: 
     chdir: /root/ 
     creates: sql.latest.tgz 

    - name: db_restore | Check if file exists 
    stat: path=/root/sql.latest.tgz 
    register: sql_latest 

    - name: db_restore | Restore latest DB backup if backup file found 
    shell: PGPASSWORD={{ dbpassword }} tar -xzOf /root/sentry*.tgz db.sql | psql -U{{ dbuser }} -h{{ pgsql_server }} --set ON_ERROR_STOP=on {{ dbname }} 
    when: sql_latest.stat.exists 
    ignore_errors: True 

Im Idealfall sollte dies überprüfen, ob DB leer. Zu diesem Zweck existiert kein geeignetes Modul. Google ist auch in der Stille .. Aktuelle Lösung funktioniert auch, dies wird Fehler geben, wenn der Import fehlschlägt, und ich kann einfach ignorieren Fehler, aber es ist ein bisschen schmerzhaft, einen Fehlalarm zu sehen.

+0

"leer" ist ein vager Begriff. Sogar eine "leere" Datenbank kann eine Menge gespeicherter Objekte definiert haben. Wie würde 'pg_restore' feststellen, dass es" leer genug "ist? – zerkms

+0

eine Frage behoben :) leer = Datenbank ohne Tabellen.Frisch erstellt – holms

+0

Ich würde nicht erwarten, dass ein solcher Schlüssel "ohne Tabellen" eine extra-enge Anforderung ist. Die andere Person würde eine leere Datenbank als die ohne Sequenzen behandeln. – zerkms

Antwort

3

Um die Datenbank als leer zu betrachten, müssen wir wissen, dass vom Zeitpunkt der Erstellung nichts hinzugefügt wurde. Da postgres dies nicht verfolgt (wie schon von @Craig Ringer erwähnt) empfehle ich einen anderen Ansatz in Bezug auf ansible.

So verwendet nur einen Handler-Mechanismus wie:

- name: Create zabbbix postgres DB 
    postgresql_db: name="{{zabbix_db_name}}" 
    notify: 
    - Init zabbix database 
+1

das einzige Problem, dass Notify kommt am Ende des Playbook .. weil app nicht einmal ohne bereitgestellten db. Eine Möglichkeit, Benachrichtigungen mit Nachdruck auszuführen? – holms

+0

Leider halte ich es jetzt für unmöglich. Aber vorgeschlagen für neue Version als unmittelbare Handler: https://github.com/ansible/ansible/issues/10829 – Hubbitus

+0

In der Zwischenzeit möchten Sie vielleicht "- meta: flush_handlers", um Handler erzwingen ausführen (https://groups.google.com/forum/#! topic/ansible-project/0lMtduWbxwU) – Hubbitus

5

Es gibt nicht wirklich so etwas wie "leer"; Es hat in der Regel die integrierten Typen, die Standardsprache PL/PgSQL usw., selbst wenn Sie von template0 erstellen. Wenn Sie aus einer anderen Vorlage erstellen, könnte es viel mehr drin geben.

PostgreSQL speichert keine Aufzeichnungen über das erste Nicht-Template-Schreiben in einen DB, daher kann man auch nicht sagen, "geändert seit erstellt".

Deshalb gibt es keine --if-empty Option zu pg_restore. Es macht keinen Sinn.

Mit Abstand die beste Option ist psqlinformation_schema abzufragen und festzustellen, ob es Tabellen im public Schema gibt. Oder, noch besser, fragen Sie nach dem Vorhandensein bestimmter Tabellen und Typen, von denen Sie wissen, dass sie vom Dump erstellt werden.

z.B.

psql -qAt mydbname -c "select 1 from information_schema.tables where table_schema = 'public' and table_name = 'testtable';" 

Sie können dann auf null/nicht-null-Zeilen testen, die auf stdout zurückgegeben werden. Oder wickle es in SELECT EXISTS(...), um einen booleschen Wert von psql zu erhalten. Oder verwenden Sie einen DO Block, der ist, wenn die Tabelle vorhanden ist, wenn Sie einen Null-/Nicht-Null-Exit-Status von psql benötigen.

2

Da es schwer zu sagen ist, wenn eine Datenbank „leer“ ist, wie von anderen erklärt, es ist viel einfacher zu überprüfen, ob die Datenbank existiert, dann erstellen und wiederherstellen in einem Schritt. Ich mache es so:

- name: Check my_database database already exists 
    become: yes 
    become_user: postgres 
    shell: psql -l | grep my_database 
    ignore_errors: true 
    register: my_database_db_existence 
- debug: var=my_database_db_existence 

- name: Copy backup of the my-database database 
    shell: your-s3-command here 
    when: my_database_db_existence | failed 

- name: Restore my_database database on first run 
    become_user: postgres 
    shell: createdb -O my_user my_database && psql -d my_database -f /path/to/my_dump.sql 
    when: my_database_db_existence | failed 

P.S. Außerdem wurde eine detailed blog post geschrieben, die jede mögliche Aufgabe in der Implementierung erklärt.

Verwandte Themen