Postgres: bash betiğinden yeniden oluşturmadan / yeniden doldurmadan önce tüm veritabanını temizle


139

Ben bir kabuk komut dosyası (bir cronjob olacak) yazıyorum ki:

1: Üretim veritabanımı dökümü

2: dökümü geliştirme veritabanına aktar

Adım 1 ve 2 arasında, geliştirme veritabanı temizlemek gerekir (tüm tabloları bırak?). Bu en iyi nasıl bir kabuk betiğinden elde edilir? Şimdiye kadar, şöyle görünüyor:

#!/bin/bash
time=`date '+%Y'-'%m'-'%d'`
# 1. export(dump) the current production database
pg_dump -U production_db_name > /backup/dir/backup-${time}.sql

# missing step: drop all tables from development database so it can be re-populated

# 2. load the backup into the development database
psql -U development_db_name < backup/dir/backup-${time}.sql

3
acele insanlar için oneliner:dbname='db_name' && dropdb $dbname && createdb $dbname && psql -d $dbname -f dump.sql
ruuter

bu oneliner veritabanı oluşturmak / bırakmak için izinlere sahip olmanızı gerektirir. yazarın denediği yaklaşım özel ayrıcalıklar gerektirmez.
ribamar

Yanıtlar:


188

Ben sadece veritabanını bırakın ve sonra yeniden oluşturun. UNIX veya Linux sisteminde, bunu yapmanız gerekir:

$ dropdb development_db_name
$ createdb developmnent_db_name

Aslında ben böyle yapıyorum.


Ben de öyle yapıyorum. Sonra sadece yeni oluşturulan db geri yükleyin.
Arthur Thomas

3
Evet. bu daha iyidir çünkü geri yüklediğiniz çöplüğün bir parçası olmayan nesneler olabilir. bu durumda kesinlikle öldürülecekler.
pstanton

7
Bana zaman kazandıran bir numara $ sudo -u postgres dropdb DATABASE_NAME
Alvin

36
Ama ... veritabanı izinleri ve sahipliği ne olacak?
Emanuele Paolini

6
@EmanuelePaolini createdb --owner=db_owner [--template=template0 --encoding=UTF8] db_nameTüm veritabanlarına varsayılan olarak son ikisini
ekliyorum

91

Aslında veritabanının yedek bir düz metin .sql komut dosyası biçiminde diske atılmış gerekmiyorsa, bağlanmak olabilir pg_dumpve pg_restorebir boru üzerinde doğrudan bir araya.

Tabloları bırakmak ve yeniden oluşturmak --cleaniçin pg_dump, veritabanı nesnelerini oluşturmadan önce (komutları) veritabanı nesnelerini temizlemek (bırakmak) için SQL komutlarını yaymak üzere komut satırı seçeneğini kullanabilirsiniz. (Bu, tüm veritabanını, sadece her tablo / sekans / dizin / vb. Yeniden oluşturmadan önce bırakmaz.)

Yukarıdaki ikisi şuna benzer:

pg_dump -U username --clean | pg_restore -U username

1
Ben yedek bir kopya istiyorum istiyorum beri ben bu çözümü seviyorum, şimdi yapıyorum: pg_dump -Ft -U üretim_db_name> /backup/dir/backup-${time {.tar pg_restore -U development_db_name -d development_db_name -O - -clean /backup/dir/backup-${time }.tar bir cazibe gibi çalışır, yardımınız için teşekkürler!
Hoff

38
Dikkat: --clean seçeneği yalnızca geri yükleme dosyasında bulunan ilişkileri kaldırır. Eğer test için bir tablo eklerseniz, o zaman (örneğin üretim DB ile senkronize etmek) kaldırmak istediğinizi Bu araçlar, bu olacak değil kaldırılabilir.
ianaré

6
Pg_dump'ın --clean seçeneğinin yalnızca düz metin yedekleriyle çalıştığını unutmayın . Belgeler burada açıkça belirtildiği gibi postgresql.org/docs/9.4/static/app-pgdump.html , arşivlenmiş yedeklemeler için pg_restore'da --clean kullanmanız gerekir.
Kikin-Sama

6
"--Clean" seçeneğine kaskad eklemenin herhangi bir yolu var mı? Bu seçenek olduğu gibi işe yaramaz görünüyor. "HATA: diğer nesneler buna bağlı olduğu için şema genel bırakamıyor" alıyorum zaman% 100 gibi alıyorum.
user4674453

Soru, tüm tabloların kaldırılması hakkında sordu. Bu, yalnızca veritabanında bulunan pg_dump öğesinin attığı tabloları kaldırır.
jbg

13

Aşağıdaki satır bir Windows toplu iş komut dosyasından alınmasına rağmen, komut oldukça benzer olmalıdır:

psql -U username -h localhost -d postgres -c "DROP DATABASE \"$DATABASE\";"

Bu komut, veritabanını gerçekten bırakarak temizlemek için kullanılır. Komuttaki $DATABASE(Windows'da olmalıdır %DATABASE%), veritabanı adı olarak değerlendirilen bir Windows stili ortam değişkenidir. Bunu senin yerine koyman gerekecek development_db_name.


4
o zaman neden zaten mevcut dropdbve createdbkomutları kullanmıyorsunuz ? Psql'yi çalıştırabilirseniz, bunları da çalıştırabilirsiniz.
Mike 'Pomax' Kamermans

10

Boşaltmak için:

pg_dump -Fc mydb > db.dump

Yenilemek:

pg_restore --verbose --clean --no-acl --no-owner -h localhost -U myuser -d my_db db/latest.dump

7

"Example_db" adlı veritabanınızı temizlemek istiyorsanız:

1) Başka bir db'ye giriş yapın (örneğin 'postgres'):

psql postgres

2) Veritabanınızı kaldırın:

DROP DATABASE example_db;

3) Veritabanınızı yeniden oluşturun:

CREATE DATABASE example_db;


4

Not: Cevabım tabloları ve diğer veritabanı nesnelerini gerçekten silmekle ilgili; için tüm verileri silerek içinde tablolar, yani tüm tabloları kesiliyor , Endre Hem bir ay sonra aynı boyutlardaki iyi yürütülen (doğrudan yürütme) deyimi sağlamıştır.

Sadece olamaz durumlar için DROP SCHEMA public CASCADE;, DROP OWNED BY current_user;burada işlemin güvenli (eğer arasına koyabilirsiniz yani yazdığım tek başına bir SQL komut veya bir şey BEGIN;ve ya ROLLBACK;sadece test dışarı veya COMMIT;aslında tapusunu yapmak) “tüm” veritabanı nesnelerini temizler… iyi, uygulamamızın kullandığı veritabanında kullanılanlar veya mantıklı bir şekilde ekleyebilirim:

  • tabloları tetikler
  • tablolardaki kısıtlamalar (FK, PK CHECK,, UNIQUE)
  • Endeksler
  • VIEWs (normal veya somutlaştırılmış)
  • tablolar
  • dizileri
  • rutinler (toplu fonksiyonlar, fonksiyonlar, prosedürler)
  • tüm nōn-default (yani değil publicveya DB-internal) şemaları “biz” sahibiz: komut dosyası “veritabanı süper kullanıcısı” olarak çalıştırıldığında kullanışlıdır; bir süper kullanıcı tüm şemaları düşürebilir (gerçekten önemli olanlar hala açıkça hariç tutulur)
  • uzantıları (kullanıcı katkısı, ancak normalde onları kasıtlı olarak bırakıyorum)

Bırakılmayan (bazıları kasıtlı; bazıları sadece DB'mizde hiç örnek olmadığım için):

  • publicşema (onları uzantısı tarafından sağlanan şeyler için örneğin)
  • harmanlamalar ve diğer yerel ayarlar
  • olay tetikleyicileri
  • metin arama öğeleri,… ( kaçırmış olabileceğim diğer şeyler için buraya bakın )
  • roller veya diğer güvenlik ayarları
  • kompozit türleri
  • tost masaları
  • FDW ve yabancı tablolar

Bu, geri yüklemek istediğiniz dökümün, geri yüklemek istediğiniz veritabanından farklı bir veritabanı şeması sürümüne (örneğin Debian , Flyway veya Liquibase / DB-Manul ile) sahip olduğu durumlarda gerçekten yararlıdır dbconfig-common.

Ayrıca biri ilgilenirse "iki tablo dışında her şeyi ve onlara ait olan" silen bir sürümü var (bir dizi, elle test, üzgünüm, biliyorum, sıkıcı); fark küçüktür. Benimle iletişime geçin veya ilgileniyorsanız bu repoyu kontrol edin .

SQL

-- Copyright © 2019, 2020
--      mirabilos <t.glaser@tarent.de>
--
-- Provided that these terms and disclaimer and all copyright notices
-- are retained or reproduced in an accompanying document, permission
-- is granted to deal in this work without restriction, including un‐
-- limited rights to use, publicly perform, distribute, sell, modify,
-- merge, give away, or sublicence.
--
-- This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
-- the utmost extent permitted by applicable law, neither express nor
-- implied; without malicious intent or gross negligence. In no event
-- may a licensor, author or contributor be held liable for indirect,
-- direct, other damage, loss, or other issues arising in any way out
-- of dealing in the work, even if advised of the possibility of such
-- damage or existence of a defect, except proven that it results out
-- of said person’s immediate fault when using the work as intended.
-- -
-- Drop everything from the PostgreSQL database.

DO $$
DECLARE
        q TEXT;
        r RECORD;
BEGIN
        -- triggers
        FOR r IN (SELECT pns.nspname, pc.relname, pt.tgname
                FROM pg_catalog.pg_trigger pt, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pt.tgrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pt.tgisinternal=false
            ) LOOP
                EXECUTE format('DROP TRIGGER %I ON %I.%I;',
                    r.tgname, r.nspname, r.relname);
        END LOOP;
        -- constraints #1: foreign key
        FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
                FROM pg_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pcon.contype='f'
            ) LOOP
                EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
                    r.nspname, r.relname, r.conname);
        END LOOP;
        -- constraints #2: the rest
        FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
                FROM pg_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pcon.contype<>'f'
            ) LOOP
                EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
                    r.nspname, r.relname, r.conname);
        END LOOP;
        -- indicēs
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='i'
            ) LOOP
                EXECUTE format('DROP INDEX %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- normal and materialised views
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind IN ('v', 'm')
            ) LOOP
                EXECUTE format('DROP VIEW %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- tables
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='r'
            ) LOOP
                EXECUTE format('DROP TABLE %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- sequences
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='S'
            ) LOOP
                EXECUTE format('DROP SEQUENCE %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- extensions (only if necessary; keep them normally)
        FOR r IN (SELECT pns.nspname, pe.extname
                FROM pg_catalog.pg_extension pe, pg_catalog.pg_namespace pns
                WHERE pns.oid=pe.extnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
            ) LOOP
                EXECUTE format('DROP EXTENSION %I;', r.extname);
        END LOOP;
        -- aggregate functions first (because they depend on other functions)
        FOR r IN (SELECT pns.nspname, pp.proname, pp.oid
                FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns, pg_catalog.pg_aggregate pagg
                WHERE pns.oid=pp.pronamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pagg.aggfnoid=pp.oid
            ) LOOP
                EXECUTE format('DROP AGGREGATE %I.%I(%s);',
                    r.nspname, r.proname,
                    pg_get_function_identity_arguments(r.oid));
        END LOOP;
        -- routines (functions, aggregate functions, procedures, window functions)
        IF EXISTS (SELECT * FROM pg_catalog.pg_attribute
                WHERE attrelid='pg_catalog.pg_proc'::regclass
                    AND attname='prokind' -- PostgreSQL 11+
            ) THEN
                q := 'CASE pp.prokind
                        WHEN ''p'' THEN ''PROCEDURE''
                        WHEN ''a'' THEN ''AGGREGATE''
                        ELSE ''FUNCTION''
                    END';
        ELSIF EXISTS (SELECT * FROM pg_catalog.pg_attribute
                WHERE attrelid='pg_catalog.pg_proc'::regclass
                    AND attname='proisagg' -- PostgreSQL ≤10
            ) THEN
                q := 'CASE pp.proisagg
                        WHEN true THEN ''AGGREGATE''
                        ELSE ''FUNCTION''
                    END';
        ELSE
                q := '''FUNCTION''';
        END IF;
        FOR r IN EXECUTE 'SELECT pns.nspname, pp.proname, pp.oid, ' || q || ' AS pt
                FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns
                WHERE pns.oid=pp.pronamespace
                    AND pns.nspname NOT IN (''information_schema'', ''pg_catalog'', ''pg_toast'')
            ' LOOP
                EXECUTE format('DROP %s %I.%I(%s);', r.pt,
                    r.nspname, r.proname,
                    pg_get_function_identity_arguments(r.oid));
        END LOOP;
        -- nōn-default schemata we own; assume to be run by a not-superuser
        FOR r IN (SELECT pns.nspname
                FROM pg_catalog.pg_namespace pns, pg_catalog.pg_roles pr
                WHERE pr.oid=pns.nspowner
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'public')
                    AND pr.rolname=current_user
            ) LOOP
                EXECUTE format('DROP SCHEMA %I;', r.nspname);
        END LOOP;
        -- voilà
        RAISE NOTICE 'Database cleared!';
END; $$;

PostgreSQL 9.6 ( ) üzerinde daha sonraki ilaveler ( Clément Prévost'unextensions katkılarıyla) dışında test edilmiştir . Agrega çıkarma işlemi 9.6 ve 12.2'de, prosedür kaldırma işlemi de 12.2'de test edilmiştir. Hata düzeltmeleri ve diğer iyileştirmeler hoş geldiniz!jessie-backports

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.