পোস্টগ্রিএসকিউএল ডাটাবেস কখন শেষ পরিবর্তন হয়েছিল তা নির্ধারণ করুন


10

আমি কীভাবে ব্যাকআপগুলি হয় তা পরিবর্তনের দিকে লক্ষ্য করছি এবং ভাবছি যে পোস্টগ্রিকেল ক্লাস্টারের কোন ডাটাবেসগুলি সম্প্রতি পরিবর্তন করা হয়নি তা নির্ধারণের কোনও উপায় আছে কিনা?

Pg_dumpall ব্যবহারের পরিবর্তে, আমি pg_dump ব্যবহার করতে চাই এবং কেবলমাত্র সেই ডাটাবেসগুলি শেষ ব্যাকআপের পরে পরিবর্তন করেছি (কিছু ডাটাবেস খুব ঘন ঘন আপডেট হয় না) - ধারণাটি হ'ল যদি কিছু পরিবর্তন না হয় তবে বর্তমান ব্যাকআপটি হওয়া উচিত এখনও ভাল হতে।

নির্দিষ্ট ডাটাবেস শেষবারে আপডেট / পরিবর্তন করা হয়েছিল তা নির্ধারণ করার কোনও উপায় কি কেউ জানেন?

ধন্যবাদ ...

হালনাগাদ:

আমি আশা করছিলাম যে একটি নির্দিষ্ট ক্লাস্টারে ডেটাবেস তৈরির উপর আমার কোনও নিয়ন্ত্রণ না থাকায় (কোনও ডাটাবেসের মধ্যে ডিবি অবজেক্টের একা তৈরি করা যাক) সমস্ত জায়গায় ট্রিগার লিখতে হবে না।

আরও খনন করা অবস্থায়, দেখে মনে হচ্ছে $ পিজিডিটিএ / গ্লোবাল / পিজি_ডাটাবেস ফাইলের (বিশেষত দ্বিতীয় ক্ষেত্রের) বিষয়বস্তু এবং / পিজিডিটিএ / বেসের অধীনে ডিরেক্টরি নামের মধ্যে একটি সম্পর্ক রয়েছে।

একটি অঙ্গে বাইরে গিয়ে, আমি অনুমান করতে পারি যে pg_database ফাইলের দ্বিতীয় ক্ষেত্রটি ডাটাবেস ওড এবং প্রতিটি ডাটাবেসের নিজস্ব সাব-ডাইরেক্টরি $ পিজিডিটিএ / বেসের অধীনে থাকে (সাব-ডাইরেক্টরির নামের জন্য ওডের সাথে)। এটা কি ঠিক? যদি তা হয়, তবে ব্যাকআপের প্রয়োজনের জন্য ট্রিগার হিসাবে $ PGDATA / বেস / * এর অধীন ফাইলগুলি থেকে টাইমস্ট্যাম্পগুলি ব্যবহার করা কি যুক্তিসঙ্গত?

... না এর চেয়ে ভাল উপায় আর কি?

আবার ধন্যবাদ...



কখনও মনে করবেন না যে বর্তমান ব্যাকআপ ভাল good আপনি সর্বদা আপনার নিয়মিত সময়সূচীতে নতুন ব্যাকআপ নিতে চান।
mrdenny

সোনু সিং - আমি ডাটাবেসগুলির সংযোজন নিয়ন্ত্রণ করতে পারি না, এই ক্লাস্টারে টেবিলগুলি একা রাখি যাতে ট্রিগারগুলি কাজ করবে না - প্লাস (আমার জ্ঞানের) ট্রিগারগুলি ডিডিএল পরিবর্তনগুলি ধরবে না। mrdenny ♦ - সঠিক। তবে আমি পর্যায়ক্রমিক পূর্ণ ব্যাকআপগুলির মধ্যে অপ্রয়োজনীয় ইনক্রিমেন্টাল ব্যাকআপগুলি এড়াতে চাই।

উত্তর:


9

select datname, xact_commit from pg_stat_database;@ জ্যাক ডগলাস দ্বারা প্রস্তাবিত হিসাবে ব্যবহার করার সময় বেশিরভাগ কাজ হয় না (দৃশ্যত অটোভ্যাকুমের কারণে), select datname, tup_inserted, tup_updated, tup_deleted from pg_stat_databaseকাজ করে বলে মনে হচ্ছে। ডিএমএল এবং ডিডিএল উভয়ই পরিবর্তন tup_ * কলামের মান পরিবর্তন করবে যখন vacuumনা ( vacuum analyzeঅন্যদিকে ...)।

এটি অন্যদের জন্য কার্যকর হতে পারে এমন অফারটিতে, আমি স্থাপন করেছি এমন ব্যাকআপ স্ক্রিপ্টটি আমি অন্তর্ভুক্ত করছি। এটি Pg 8.4.x এর জন্য কাজ করে তবে 8.2.x- এর জন্য নয় - ব্যবহৃত পিজির সংস্করণের উপর নির্ভর করে ওয়াইএমএমভি।

#!/usr/bin/env perl
=head1 Synopsis

pg_backup -- selectively backup a postgresql database cluster

=head1 Description

Perform backups (pg_dump*) of postgresql databases in a cluster on an
as needed basis.

For some database clusters, there may be databases that are:

 a. rarely updated/changed and therefore shouldn't require dumping as 
    often as those databases that are frequently changed/updated.

 b. are large enough that dumping them without need is undesirable.

The global data is always dumped without regard to whether any 
individual databses need backing up or not.

=head1 Usage

pg_backup [OPTION]...

General options:

  -F, --format=c|t|p    output file format for data dumps 
                          (custom, tar, plain text) (default is custom)
  -a, --all             backup (pg_dump) all databases in the cluster 
                          (default is to only pg_dump databases that have
                          changed since the last backup)
  --backup-dir          directory to place backup files in 
                          (default is ./backups)
  -v, --verbose         verbose mode
  --help                show this help, then exit

Connection options:

  -h, --host=HOSTNAME   database server host or socket directory
  -p, --port=PORT       database server port number
  -U, --username=NAME   connect as specified database user
  -d, --database=NAME   connect to database name for global data

=head1 Notes

This utility has been developed against PostgreSQL version 8.4.x. Older 
versions of PostgreSQL may not work.

`vacuum` does not appear to trigger a backup unless there is actually 
something to vacuum whereas `vacuum analyze` appears to always trigger a 
backup.

=head1 Copyright and License

Copyright (C) 2011 by Gregory Siems

This library is free software; you can redistribute it and/or modify it 
under the same terms as PostgreSQL itself, either PostgreSQL version 
8.4 or, at your option, any later version of PostgreSQL you may have 
available.

=cut

use strict;
use warnings;
use Getopt::Long;
use Data::Dumper;
use POSIX qw(strftime);

my %opts = get_options();

my $connect_options = '';
$connect_options .= "--$_=$opts{$_} " for (qw(username host port));

my $shared_dump_args = ($opts{verbose})
    ? $connect_options . ' --verbose '
    : $connect_options;

my $backup_prefix = (exists $opts{host} && $opts{host} ne 'localhost')
    ? $opts{backup_dir} . '/' . $opts{host} . '-'
    : $opts{backup_dir} . '/';

do_main();


########################################################################
sub do_main {
    backup_globals();

    my $last_stats_file = $backup_prefix . 'last_stats';

    # get the previous pg_stat_database data
    my %last_stats;
    if ( -f $last_stats_file) {
        %last_stats = parse_stats (split "\n", slurp_file ($last_stats_file));
    }

    # get the current pg_stat_database data
    my $cmd = 'psql ' . $connect_options;
    $cmd .= " $opts{database} " if (exists $opts{database});
    $cmd .= "-Atc \"
        select date_trunc('minute', now()), datid, datname, 
            xact_commit, tup_inserted, tup_updated, tup_deleted 
        from pg_stat_database 
        where datname not in ('template0','template1','postgres'); \"";
    $cmd =~ s/\ns+/ /g;
    my @stats = `$cmd`;
    my %curr_stats = parse_stats (@stats);

    # do a backup if needed
    foreach my $datname (sort keys %curr_stats) {
        my $needs_backup = 0;
        if ($opts{all}) {
            $needs_backup = 1;
        }
        elsif ( ! exists $last_stats{$datname} ) {
            $needs_backup = 1;
            warn "no last stats for $datname\n" if ($opts{debug});
        }
        else {
            for (qw (tup_inserted tup_updated tup_deleted)) {
                if ($last_stats{$datname}{$_} != $curr_stats{$datname}{$_}) {
                    $needs_backup = 1;
                    warn "$_ stats do not match for $datname\n" if ($opts{debug});
                }
            }
        }
        if ($needs_backup) {
            backup_db ($datname);
        }
        else {
            chitchat ("Database \"$datname\" does not currently require backing up.");
        }
    }

    # update the pg_stat_database data
    open my $fh, '>', $last_stats_file || die "Could not open $last_stats_file for output. !$\n";
    print $fh @stats;
    close $fh;
}

sub parse_stats {
    my @in = @_;
    my %stats;
    chomp @in;
    foreach my $line (@in) {
        my @ary = split /\|/, $line;
        my $datname = $ary[2];
        next unless ($datname);
        foreach my $key (qw(tmsp datid datname xact_commit tup_inserted tup_updated tup_deleted)) {
            my $val = shift @ary;
            $stats{$datname}{$key} = $val;
        }
    }
    return %stats;
}

sub backup_globals {
    chitchat ("Backing up the global data.");

    my $backup_file = $backup_prefix . 'globals-only.backup.gz';
    my $cmd = 'pg_dumpall --globals-only ' . $shared_dump_args;
    $cmd .= " --database=$opts{database} " if (exists $opts{database});

    do_dump ($backup_file, "$cmd | gzip");
}

sub backup_db {
    my $database = shift;
    chitchat ("Backing up database \"$database\".");

    my $backup_file = $backup_prefix . $database . '-schema-only.backup.gz';
    do_dump ($backup_file, "pg_dump --schema-only --create --format=plain $shared_dump_args $database | gzip");

    $backup_file = $backup_prefix . $database . '.backup';
    do_dump ($backup_file, "pg_dump --format=". $opts{format} . " $shared_dump_args $database");
}

sub do_dump {
    my ($backup_file, $cmd) = @_;

    my $temp_file = $backup_file . '.new';
    warn "Command is: $cmd > $temp_file" if ($opts{debug});

    chitchat (`$cmd > $temp_file`);
    if ( -f $temp_file ) {
        chitchat (`mv $temp_file $backup_file`);
    }
}

sub chitchat {
    my @ary = @_;
    return unless (@ary);
    chomp @ary;
    my $first   = shift @ary;
    my $now     = strftime "%Y%m%d-%H:%M:%S", localtime;
    print +(join "\n                  ", "$now $first", @ary), "\n";
}

sub get_options {
    Getopt::Long::Configure('bundling');

    my %opts = ();
    GetOptions(
        "a"             => \$opts{all},
        "all"           => \$opts{all},
        "p=s"           => \$opts{port},
        "port=s"        => \$opts{port},
        "U=s"           => \$opts{username},
        "username=s"    => \$opts{username},
        "h=s"           => \$opts{host},
        "host=s"        => \$opts{host},
        "F=s"           => \$opts{format},
        "format=s"      => \$opts{format},
        "d=s"           => \$opts{database},
        "database=s"    => \$opts{database},
        "backup-dir=s"  => \$opts{backup_dir},
        "help"          => \$opts{help},
        "v"             => \$opts{verbose},
        "verbose"       => \$opts{verbose},
        "debug"         => \$opts{debug},
        );

    # Does the user need help?
    if ($opts{help}) {
        show_help();
    }

    $opts{host}         ||= $ENV{PGHOSTADDR} || $ENV{PGHOST}     || 'localhost';
    $opts{port}         ||= $ENV{PGPORT}     || '5432';
    $opts{host}         ||= $ENV{PGHOST}     || 'localhost';
    $opts{username}     ||= $ENV{PGUSER}     || $ENV{USER}       || 'postgres';
    $opts{database}     ||= $ENV{PGDATABASE} || $opts{username};
    $opts{backup_dir}   ||= './backups';

    my %formats = (
        c       => 'custom',
        custom  => 'custom',
        t       => 'tar',
        tar     => 'tar',
        p       => 'plain',
        plain   => 'plain',
    );
    $opts{format} = (defined $opts{format})
        ? $formats{$opts{format}} || 'custom'
        : 'custom';

    warn Dumper \%opts if ($opts{debug});
    return %opts;
}

sub show_help {
    print `perldoc -F $0`;
    exit;
}

sub slurp_file { local (*ARGV, $/); @ARGV = shift; <> }

__END__

আপডেট: স্ক্রিপ্টটি এখানে গিথুবে রাখা হয়েছে


বেশ সুন্দর কোড, ভাগ করে নেওয়ার জন্য ধন্যবাদ। বিটিডাব্লু, এটি গিথুবড হতে পারে, আপনি কি তাই মনে করেন না? :-)
পোয়েজ

2

দেখে মনে হচ্ছে আপনি pg_stat_databaseলেনদেনের গণনা পেতে ব্যবহার করতে পারেন এবং এটি একটি ব্যাকআপ থেকে অন্যটিতে চলে কিনা তা পরীক্ষা করে দেখুন:

select datname, xact_commit from pg_stat_database;

  datname  | xact_commit 
-----------+-------------
 template1 |           0
 template0 |           0
 postgres  |      136785

যদি কেউ ডেকে থাকেন pg_stat_resetতবে কোনও ডিবি পরিবর্তিত হয়েছে কিনা তা আপনি নিশ্চিত হতে পারবেন না তবে আপনি এটি শেষের ক্ষেত্রে যথেষ্ট হবে বলে মনে করতে পারেন, তারপরে আপনার শেষ পাঠের সাথে মিলিয়ে দেওয়ার জন্য সঠিক সংখ্যক লেনদেন হবে।

--EDIT

কেন এটি কাজ করবে না তার জন্য এই এই প্রশ্নটি দেখুন । কেন এটি হতে পারে তা নিশ্চিত নয় তবে লগিং সক্ষম করার ফলে কিছুটা আলোকপাত হতে পারে ....


যদি কেউ ফোন করে pg_stat_resetতবে xact_commit মানটির আগেরটির সাথে মিলের সম্ভাবনাটি খুব কম হবে, না? যাতে অবশ্যই ডিএমএল পরিবর্তনের অস্তিত্ব ধরা যায়। এখন আমার কেবল ডিডিএল পরিবর্তন হয়েছে কিনা তা ধরতে হবে catch
জিএসএম

ডিডিএল পোস্টগ্রাজে লেনদেন হয় - আমি আশা করি প্রতিশ্রুতি গণনা সে ক্ষেত্রেও বাড়বে। যদিও যাচাই করা হয়নি ...
জ্যাক বলছেন topanswers.xyz

আপনি স্যার, ঠিক আছে। আমি পিজি ডিডিএল লেনদেনের সম্পর্কে ভুলে গিয়েছিলাম এবং একটি দ্রুত create table ...পরীক্ষা এক্সক্রিট_কমিট ইনক্রিমেন্টে উপস্থিত হয়।
gsiems

1
আরও পরীক্ষা করে দেখা যাচ্ছে যে কোনও ব্যবহারকারীর ক্রিয়াকলাপ চলছে না- এমনকি অটোভ্যাকুয়াম বোধহয় এক্স্যাক্ট_কমিট বাড়ছে?
gsiems

এটি অবশ্যই ব্যাকআপ উদ্দেশ্যে কাজ করে না। xact_commit খুব ঘন ঘন বৃদ্ধি পায়, এমনকি যখন কেউ ডাটাবেসে সংযুক্ত থাকে না।
mivk

1

পোস্টগ্রিস ডক্স এবং নিউজ গ্রুপগুলির চারপাশে খনন করা থেকে:

txid_current()আপনাকে একটি নতুন উপহার দেবে xid- আপনি যদি পরবর্তী তারিখে আবার ফাংশনটি কল করেন, আপনি যদি একটি xidউচ্চতর হন, আপনি জানেন যে দুটি কলের মধ্যে কোনও লেনদেন হয়নি। আপনি যদিও মিথ্যা ইতিবাচক পেতে পারেন - যেমন যদি অন্য কেউ কল করেtxid_current()


আপনার পরামর্শের জন্য ধন্যবাদ। আমি বিশ্বাস করি না এটি কাজ করবে তবে txid_current () ক্লাস্টার স্তরে ডাটাবেস স্তরের পরিবর্তে অপারেটিং হিসাবে প্রদর্শিত হবে।
gsiems

আমি এটিতে কিছু ডক খুঁজছিলাম এবং খুঁজে পেলাম না - আপনার কোনও লিঙ্ক আছে?
জ্যাক বলছেন topanswers.xyz

1
কোন সংযোগ নেই. আমি ডাটাবেসগুলির মধ্যে স্যুইচ করে এবং "বর্তমানের_ড্যাটাবেস নির্বাচন করুন (), টেক্সিড_ক্রেন্ট () নির্বাচন করে পরীক্ষা করেছি;" এবং ফলাফল তুলনা।
জিএসএম

0

আপনার ফাইলগুলিতে ডিবি-ডেটা রয়েছে এমন টাইম স্ট্যাম্পটি দেখুন এবং সেগুলি পরিবর্তন হয়েছে কিনা তা দেখুন। তারা যদি সেখানে লেখেন।

ওয়াল-ইঙ্গিতের পরে সম্পাদনা করুন: অসামান্য লেখকদের ফ্লাশ করার পরে আপনার এটি করা উচিত।


2
এটি নির্ভরযোগ্য নির্ভরযোগ্য নয়। এমন কিছু পরিবর্তন হতে পারে যা এখনও ডেটাফাইলে লেখা হয়নি (ফ্লাশ করা হয়েছে), যেমন সেগুলি কেবল ওয়াল-এ লেখা হয়েছিল।
a_horse_with_no_name

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.