هل ترغب في معرفة كيفية إجراء تقسيم قاعدة بيانات Zabbix؟ سنشرح لك في هذا البرنامج التعليمي كيفية تقسيم قاعدة بيانات Zabbix MySQL على جهاز كمبيوتر يعمل بنظام التشغيل Ubuntu Linux.

• إصدار Zabbix: 4.0.5
• Linux: Ubuntu 18.04
• MySQL: Ver 14.14 Distrib 5.7.25

يعتبر برنامجنا التعليمي تثبيت Zabbix جديد تمامًا.

قائمة الأجهزة:

يعرض القسم التالي قائمة المعدات المستخدمة لإنشاء هذا البرنامج التعليمي Zabbix.

يمكن العثور على كل قطعة من الأجهزة المذكورة أعلاه على موقع أمازون.

Zabbix Playlist:

في هذه الصفحة ، نقدم وصولاً سريعًا إلى قائمة مقاطع الفيديو ذات الصلة بتثبيت Zabbix.

لا تنس الاشتراك في قناة يوتيوب الخاصة بنا المسماة FKIT.

البرنامج التعليمي - تقسيم قاعدة البيانات Zabbix

استخدم الأمر التالي لتثبيت البرنامج المطلوب.

# apt-get update
# apt-get install perl libdbi-perl libdatetime-perl libdbd-mysql-perl

نحتاج إلى تقسيم الجداول التالية من قاعدة بيانات Zabbix:

• history
• history_log
• history_str
• history_text
• history_uint
• trends
• trends_uint

ربما يحتوي خادم Zabbix على معلومات من المراقبة داخل قاعدة البيانات الخاصة به.

الوصول إلى وحدة التحكم MySQL والتحقق من أقدم تاريخ إدخال Zabbix للجداول السبعة المذكورة أعلاه:

# mysql -u root -p

use zabbix;
SELECT FROM_UNIXTIME(MIN(clock)) FROM `history`;
SELECT FROM_UNIXTIME(MIN(clock)) FROM `history_log`;
SELECT FROM_UNIXTIME(MIN(clock)) FROM `history_str`;
SELECT FROM_UNIXTIME(MIN(clock)) FROM `history_text`;
SELECT FROM_UNIXTIME(MIN(clock)) FROM `history_uint`;
SELECT FROM_UNIXTIME(MIN(clock)) FROM `trends`;
SELECT FROM_UNIXTIME(MIN(clock)) FROM `trends_uint`;

لكل من أوامر MySQL ، يجب أن يكون الإخراج شيئًا مشابهًا لهذا:

+---------------------------------------+
| FROM_UNIXTIME(MIN(clock)) |
+---------------------------------------+
| 2019-03-22 17:48:07                       |
+---------------------------------------+
1 row in set (0.00 sec)

مهم! يحيط علما بالتاريخ المعروض لكل واحد من الجداول.

الآن ، لنقسم كل جدول من جداول المحفوظات حسب التاريخ:

أولاً ، لنقسم جدول المحفوظات.

# mysql -u root -p
# use zabbix;

ALTER TABLE `history` PARTITION BY RANGE ( clock)
(PARTITION p2019_03_22 VALUES LESS THAN (UNIX_TIMESTAMP("2019-03-23 00:00:00")) ENGINE = InnoDB);

في مثالنا ، سيكون للملف المسمى p2019_03_22 جميع معلومات MySQL قبل 2019-03-23.

إذا كان تاريخك المستهدف هو 2019-03-22 ، فأنت بحاجة إلى إدخال كل شيء قبل 2019-03-23.

ثانياً ، لنقسم جدول history_log.

ALTER TABLE `history_log` PARTITION BY RANGE ( clock)
(PARTITION p2019_03_22 VALUES LESS THAN (UNIX_TIMESTAMP("2019-03-23 00:00:00")) ENGINE = InnoDB);

ثالثًا ، لنقسم الجدول history_str.

ALTER TABLE `history_str` PARTITION BY RANGE ( clock)
(PARTITION p2019_03_22 VALUES LESS THAN (UNIX_TIMESTAMP("2019-03-23 00:00:00")) ENGINE = InnoDB);

رابعًا ، لنقسم جدول history_text.

ALTER TABLE `history_text` PARTITION BY RANGE ( clock)
(PARTITION p2019_03_22 VALUES LESS THAN (UNIX_TIMESTAMP("2019-03-23 00:00:00")) ENGINE = InnoDB);

خامسًا ، لنقسم جدول history_uint

ALTER TABLE `history_uint` PARTITION BY RANGE ( clock)
(PARTITION p2019_03_22 VALUES LESS THAN (UNIX_TIMESTAMP("2019-03-23 00:00:00")) ENGINE = InnoDB);

الآن ، لنقسم كل جدول من جدول الاتجاهات حسب الشهر:

أولاً ، لنقسم جدول الاتجاهات.

ALTER TABLE `trends` PARTITION BY RANGE ( clock)
(PARTITION p2019_03 VALUES LESS THAN (UNIX_TIMESTAMP("2019-04-01 00:00:00")) ENGINE = InnoDB);

في مثالنا ، سيكون للملف المسمى p2019_03 جميع معلومات MySQL قبل 2019-04-01.

إذا كان تاريخك المستهدف هو 2019-03 ، فأنت بحاجة إلى إدخال كل شيء قبل 2019-04-01.

ثانياً ، لنقسم جدول الاتجاهات.

ALTER TABLE `trends_uint` PARTITION BY RANGE ( clock)
(PARTITION p2019_03 VALUES LESS THAN (UNIX_TIMESTAMP("2019-04-01 00:00:00")) ENGINE = InnoDB);

تم إنشاء أقسام قاعدة بيانات Zabbix بنجاح.

البرنامج التعليمي - Zabbix قاعدة بيانات التقسيم النصي

سنستخدم برل بيرل للقيام بالمهام التالية:

قم بإنشاء 10 أيام من قسم قاعدة بيانات MySQL في وقت مبكر لمنع توقف الخدمة.

حذف أقسام MySQL القديمة التي لم تعد مطلوبة.

# mkdir /downloads/zabbix_script
# cd /downloads/zabbix_script
# vi zabbix_partition_creator.pl

فيما يلي محتوى البرنامج النصي zabbix_partition_creator.pl:

use strict;
use Data::Dumper;
use DBI;
use Sys::Syslog qw(:standard :macros);
use DateTime;
use POSIX qw(strftime);
openlog("mysql_zbx_part", "ndelay,pid", LOG_LOCAL0);
my $db_schema = 'zabbix';
my $dsn = 'DBI:mysql:'.$db_schema.':mysql_socket=/var/run/mysqld/mysqld.sock';
my $db_user_name = 'zabbix';
my $db_password = 'kamisama123';
my $tables = { 'history' => { 'period' => 'day', 'keep_history' => '30'},
'history_log' => { 'period' => 'day', 'keep_history' => '30'},
'history_str' => { 'period' => 'day', 'keep_history' => '30'},
'history_text' => { 'period' => 'day', 'keep_history' => '30'},
'history_uint' => { 'period' => 'day', 'keep_history' => '30'},
'trends' => { 'period' => 'month', 'keep_history' => '2'},
'trends_uint' => { 'period' => 'month', 'keep_history' => '2'},
};
my $amount_partitions = 10;
my $curr_tz = 'America/Sao_Paulo';
my $part_tables;
my $dbh = DBI->connect($dsn, $db_user_name, $db_password, {'ShowErrorStatement' => 1});
my $sth = $dbh->prepare(qq{SELECT table_name, partition_name, lower(partition_method) as partition_method,
rtrim(ltrim(partition_expression)) as partition_expression,
partition_description, table_rows
FROM information_schema.partitions
WHERE partition_name IS NOT NULL AND table_schema = ?});
$sth->execute($db_schema);
while (my $row = $sth->fetchrow_hashref()) {
$part_tables->{$row->{'table_name'}}->{$row->{'partition_name'}} = $row;
}
$sth->finish();
foreach my $key (sort keys %{$tables}) {
unless (defined($part_tables->{$key})) {
syslog(LOG_ERR, 'Partitioning for "'.$key.'" is not found! The table might be not partitioned.');
next;
}
create_next_partition($key, $part_tables->{$key}, $tables->{$key}->{'period'});
remove_old_partitions($key, $part_tables->{$key}, $tables->{$key}->{'period'}, $tables->{$key}->{'keep_history'})
}
delete_old_data();
$dbh->disconnect();
sub create_next_partition {
my $table_name = shift;
my $table_part = shift;
my $period = shift;
for (my $curr_part = 0; $curr_part < $amount_partitions; $curr_part++) {
my $next_name = name_next_part($tables->{$table_name}->{'period'}, $curr_part);
my $found = 0;
foreach my $partition (sort keys %{$table_part}) {
if ($next_name eq $partition) {
syslog(LOG_INFO, "Next partition for $table_name table has already been created. It is $next_name");
$found = 1;
}
}
if ( $found == 0 ) {
syslog(LOG_INFO, "Creating a partition for $table_name table ($next_name)");
my $query = 'ALTER TABLE '."$db_schema.$table_name".' ADD PARTITION (PARTITION '.$next_name.
' VALUES less than (UNIX_TIMESTAMP("'.date_next_part($tables->{$table_name}->{'period'}, $curr_part).'") div 1))';
syslog(LOG_DEBUG, $query);
$dbh->do($query);
}
}
}
sub remove_old_partitions {
my $table_name = shift;
my $table_part = shift;
my $period = shift;
my $keep_history = shift;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
$curr_date->add(days => -$keep_history);
$curr_date->add(hours => -$curr_date->strftime('%H'));
$curr_date->add(minutes => -$curr_date->strftime('%M'));
$curr_date->add(seconds => -$curr_date->strftime('%S'));
}
elsif ( $period eq 'week' ) {
}
elsif ( $period eq 'month' ) {
$curr_date->add(months => -$keep_history);
$curr_date->add(days => -$curr_date->strftime('%d')+1);
$curr_date->add(hours => -$curr_date->strftime('%H'));
$curr_date->add(minutes => -$curr_date->strftime('%M'));
$curr_date->add(seconds => -$curr_date->strftime('%S'));
}
foreach my $partition (sort keys %{$table_part}) {
if ($table_part->{$partition}->{'partition_description'} <= $curr_date->epoch) {
syslog(LOG_INFO, "Removing old $partition partition from $table_name table");
my $query = "ALTER TABLE $db_schema.$table_name DROP PARTITION $partition";
syslog(LOG_DEBUG, $query);
$dbh->do($query);
}
}
}
sub name_next_part {
my $period = shift;
my $curr_part = shift;
my $name_template;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
my $curr_date = $curr_date->truncate( to => 'day' );
$curr_date->add(days => 1 + $curr_part);
$name_template = $curr_date->strftime('p%Y_%m_%d');
}
elsif ($period eq 'week') {
my $curr_date = $curr_date->truncate( to => 'week' );
$curr_date->add(days => 7 * $curr_part);
$name_template = $curr_date->strftime('p%Y_%m_w%W');
}
elsif ($period eq 'month') {
my $curr_date = $curr_date->truncate( to => 'month' );
$curr_date->add(months => 1 + $curr_part);
$name_template = $curr_date->strftime('p%Y_%m');
}
return $name_template;
}
sub date_next_part {
my $period = shift;
my $curr_part = shift;
my $period_date;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
my $curr_date = $curr_date->truncate( to => 'day' );
$curr_date->add(days => 2 + $curr_part);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
elsif ($period eq 'week') {
my $curr_date = $curr_date->truncate( to => 'week' );
$curr_date->add(days => 7 * $curr_part + 1);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
elsif ($period eq 'month') {
my $curr_date = $curr_date->truncate( to => 'month' );
$curr_date->add(months => 2 + $curr_part);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
return $period_date;
}
sub delete_old_data {
$dbh->do("DELETE FROM sessions WHERE lastaccess < UNIX_TIMESTAMP(NOW() - INTERVAL 1 MONTH)");
$dbh->do("TRUNCATE housekeeper");
$dbh->do("DELETE FROM auditlog_details WHERE NOT EXISTS (SELECT NULL FROM auditlog WHERE auditlog.auditid = auditlog_details.auditid)");
}

تحتاج إلى تغيير الأجزاء التالية من البرنامج النصي لتعكس بيئة MySQL الخاصة بك.

my $db_schema = 'zabbix';
my $dsn = 'DBI:mysql:'.$db_schema.':mysql_socket=/var/run/mysqld/mysqld.sock';
my $db_user_name = 'zabbix';
my $db_password = 'kamisama123';
my $tables = { 'history' => { 'period' => 'day', 'keep_history' => '30'},
'history_log' => { 'period' => 'day', 'keep_history' => '30'},
'history_str' => { 'period' => 'day', 'keep_history' => '30'},
'history_text' => { 'period' => 'day', 'keep_history' => '30'},
'history_uint' => { 'period' => 'day', 'keep_history' => '30'},
'trends' => { 'period' => 'month', 'keep_history' => '2'},
'trends_uint' => { 'period' => 'month', 'keep_history' => '2'},
};
my $amount_partitions = 10;
my $curr_tz = 'America/Sao_Paulo';

في مثالنا ، نستخدم اسم مستخدم zabbix MySQL وكلمة المرور kamisama123 MySQL.

في مثالنا ، نحتفظ بـ 30 يومًا من محتوى جداول السجل.

في مثالنا ، نحتفظ بمحتوى جداول اتجاهات شهرين.

في مثالنا ، قمنا بتعيين منطقة زمنية America / Sao_Paulo.

الآن ، تحتاج إلى تشغيل البرنامج النصي يدويًا دون أخطاء.

# cd /downloads/zabbix_script
# chmod 700 zabbix_partition_creator.pl
# ./zabbix_partition_creator.pl

قم بالوصول إلى وحدة MySQL وتحقق من أن النظام أنشأ 10 أيام من قسم السجل في وقت مبكر

# mysql -u root -p

use zabbix;
show create table history;

/*!50100 PARTITION BY RANGE ( clock)
(PARTITION p2019_03_22 VALUES LESS THAN (1553310000) ENGINE = InnoDB,
PARTITION p2019_03_23 VALUES LESS THAN (1553396400) ENGINE = InnoDB,
PARTITION p2019_03_24 VALUES LESS THAN (1553482800) ENGINE = InnoDB,
PARTITION p2019_03_25 VALUES LESS THAN (1553569200) ENGINE = InnoDB,
PARTITION p2019_03_26 VALUES LESS THAN (1553655600) ENGINE = InnoDB,
PARTITION p2019_03_27 VALUES LESS THAN (1553742000) ENGINE = InnoDB,
PARTITION p2019_03_28 VALUES LESS THAN (1553828400) ENGINE = InnoDB,
PARTITION p2019_03_29 VALUES LESS THAN (1553914800) ENGINE = InnoDB,
PARTITION p2019_03_30 VALUES LESS THAN (1554001200) ENGINE = InnoDB,
PARTITION p2019_03_31 VALUES LESS THAN (1554087600) ENGINE = InnoDB,
PARTITION p2019_04_01 VALUES LESS THAN (1554174000) ENGINE = InnoDB) */