From a7e8fc34aa0dd60c6cb62b90a9cc6649ddbdda6c Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 2 Oct 2019 10:55:45 +0200 Subject: [PATCH] add container tablespace --- database/oracle/mode/tablespaceusage.pm | 190 +++++++++++++++++++++++- 1 file changed, 189 insertions(+), 1 deletion(-) diff --git a/database/oracle/mode/tablespaceusage.pm b/database/oracle/mode/tablespaceusage.pm index 7a9607e04..4cf15a473 100644 --- a/database/oracle/mode/tablespaceusage.pm +++ b/database/oracle/mode/tablespaceusage.pm @@ -122,6 +122,7 @@ sub new { 'free' => { name => 'free' }, 'skip' => { name => 'skip' }, 'notemp' => { name => 'notemp' }, + 'container' => { name => 'container' }, }); return $self; @@ -133,6 +134,187 @@ sub prefix_tablespace_output { return "Tablespace '" . $options{instance_value}->{display} . "' "; } +sub manage_container { + my ($self, %options) = @_; + + return if (!defined($self->{option_results}->{container})); + + # request from check_oracle_health. + my $query; + if ($self->{sql}->is_version_minimum(version => '9')) { + my $tbs_sql_undo = q{ + -- freier platz durch expired extents + -- speziell fuer undo tablespaces + -- => bytes_expired + SELECT + tablespace_name, bytes_expired, con_id + FROM + ( + SELECT + tablespace_name, + SUM (bytes) bytes_expired, + status, + con_id + FROM + cdb_undo_extents + GROUP BY + con_id, tablespace_name, status + ) + WHERE + status = 'EXPIRED' + }; + my $tbs_sql_undo_empty = q{ + SELECT NULL AS tablespace_name, NULL AS bytes_expired, NULL AS con_id FROM DUAL + }; + my $tbs_sql_temp = q{ + UNION ALL + SELECT + e.name||'_'||b.tablespace_name "Tablespace", + b.status "Status", + b.contents "Type", + b.extent_management "Extent Mgmt", + sum(a.bytes_free + a.bytes_used) bytes, -- allocated + SUM(DECODE(d.autoextensible, 'YES', d.maxbytes, 'NO', d.bytes)) bytes_max, + SUM(a.bytes_free + a.bytes_used - NVL(c.bytes_used, 0)) bytes_free + FROM + sys.v_$TEMP_SPACE_HEADER a, -- has con_id + sys.cdb_tablespaces b, -- has con_id + sys.v_$Temp_extent_pool c, + cdb_temp_files d, -- has con_id + v$containers e + WHERE + a.file_id = c.file_id(+) + AND a.file_id = d.file_id + AND a.tablespace_name = c.tablespace_name(+) + AND a.tablespace_name = d.tablespace_name + AND a.tablespace_name = b.tablespace_name + AND a.con_id = c.con_id(+) + AND a.con_id = d.con_id + AND a.con_id = b.con_id + AND a.con_id = e.con_id + GROUP BY + e.name, + b.con_id, + b.status, + b.contents, + b.extent_management, + b.tablespace_name + ORDER BY + 1 + }; + + $query = sprintf( + q{ + SELECT /*+ opt_param('optimizer_adaptive_features','false') */ + e.name||'_'||a.tablespace_name "Tablespace", + b.status "Status", + b.contents "Type", + b.extent_management "Extent Mgmt", + a.bytes bytes, + a.maxbytes bytes_max, + c.bytes_free + NVL(d.bytes_expired,0) bytes_free + FROM + ( + -- belegter und maximal verfuegbarer platz pro datafile + -- nach tablespacenamen zusammengefasst + -- => bytes + -- => maxbytes + SELECT + a.con_id, + a.tablespace_name, + SUM(a.bytes) bytes, + SUM(DECODE(a.autoextensible, 'YES', a.maxbytes, 'NO', a.bytes)) maxbytes + FROM + cdb_data_files a + GROUP BY + con_id, tablespace_name + ) a, + sys.cdb_tablespaces b, + ( + -- freier platz pro tablespace + -- => bytes_free + SELECT + a.con_id, + a.tablespace_name, + SUM(a.bytes) bytes_free + FROM + cdb_free_space a + GROUP BY + con_id, tablespace_name + ) c, + ( + %s + ) d, + v$containers e + WHERE + a.tablespace_name = c.tablespace_name (+) + AND a.tablespace_name = b.tablespace_name + AND a.tablespace_name = d.tablespace_name (+) + AND a.con_id = c.con_id(+) + AND a.con_id = b.con_id + AND a.con_id = d.con_id(+) + AND a.con_id = e.con_id + %s + %s + }, + defined($self->{option_results}->{notemp}) ? $tbs_sql_undo_empty : $tbs_sql_undo, + defined($self->{option_results}->{notemp}) ? "AND (b.contents != 'TEMPORARY' AND b.contents != 'UNDO')" : '', + defined($self->{option_results}->{notemp}) ? "" : $tbs_sql_temp + ); + } else { + return ; + } + $self->{sql}->query(query => $query); + my $result = $self->{sql}->fetchall_arrayref(); + + foreach my $row (@$result) { + my ($name, $status, $type, $extentmgmt, $bytes, $bytes_max, $bytes_free) = @$row; + + if (defined($self->{option_results}->{notemp}) && ($type eq 'UNDO' || $type eq 'TEMPORARY')) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': temporary or undo.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_tablespace}) && $self->{option_results}->{filter_tablespace} ne '' && + $name !~ /$self->{option_results}->{filter_tablespace}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); + next; + } + if (!defined($bytes)) { + # seems corrupted, cannot get value + $self->{output}->output_add(long_msg => sprintf("tbs '%s' cannot get data", $name), debug => 1); + next; + } + if (defined($self->{option_results}->{skip}) && $status eq 'OFFLINE') { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': tbs is offline", debug => 1); + next; + } + + my ($percent_used, $percent_free, $used, $free, $size); + if ((!defined($bytes_max)) || ($bytes_max eq '')) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': bytes max not defined.", debug => 1); + next; + } elsif ($bytes_max > $bytes) { + $percent_used = ($bytes - $bytes_free) / $bytes_max * 100; + $size = $bytes_max; + $free = $bytes_free + ($bytes_max - $bytes); + $used = $size - $free; + } else { + $percent_used = ($bytes - $bytes_free) / $bytes * 100; + $size = $bytes; + $free = $bytes_free; + $used = $size - $free; + } + + $self->{tablespace}->{$name} = { + used => $used, + free => $free, + total => $size, + prct_used => $percent_used, + display => lc($name) + }; + } +} + sub manage_selection { my ($self, %options) = @_; @@ -358,7 +540,6 @@ sub manage_selection { } $self->{sql}->query(query => $query); my $result = $self->{sql}->fetchall_arrayref(); - $self->{sql}->disconnect(); $self->{tablespace} = {}; @@ -409,6 +590,9 @@ sub manage_selection { }; } + $self->manage_container(); + $self->{sql}->disconnect(); + if (scalar(keys %{$self->{tablespace}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No tablespaces found."); $self->{output}->option_exit(); @@ -449,6 +633,10 @@ Perfdata show free space skip temporary or undo tablespaces. +=item B<--container> + +Add tablespaces of container databases. + =item B<--skip> Skip offline tablespaces.