├── LICENSE ├── README.md ├── awr-generator.sql ├── awr-io.sh ├── awr-parser.sh ├── setup-kaminario-mpath.sh ├── setup-violin-mpath.sh ├── show_physical_io.sql └── slob_harness.sh /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | scripts 2 | ======= 3 | 4 | Scripts and tools from flashdba 5 | -------------------------------------------------------------------------------- /awr-generator.sql: -------------------------------------------------------------------------------- 1 | -- AWR-Generator.sql: Script for creating multiple consecutive Oracle AWR Reports 2 | -- Creates an output SQL script which, when run, will generate 3 | -- all AWR Reports between the specificed start and end snapshot 4 | -- IDs, for all instances 5 | -- 6 | -- See GitHub repository at https://github.com/flashdba/scripts 7 | -- 8 | -- ########################################################################### 9 | -- # # 10 | -- # Copyright (C) {2014,2015} Author: flashdba (http://flashdba.com) # 11 | -- # # 12 | -- # This program is free software; you can redistribute it and/or modify # 13 | -- # it under the terms of the GNU General Public License as published by # 14 | -- # the Free Software Foundation; either version 2 of the License, or # 15 | -- # (at your option) any later version. # 16 | -- # # 17 | -- # This program is distributed in the hope that it will be useful, # 18 | -- # but WITHOUT ANY WARRANTY; without even the implied warranty of # 19 | -- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 20 | -- # GNU General Public License for more details. # 21 | -- # # 22 | -- # You should have received a copy of the GNU General Public License along # 23 | -- # with this program; if not, write to the Free Software Foundation, Inc., # 24 | -- # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 25 | -- # # 26 | -- ########################################################################### 27 | 28 | set feedback off 29 | set echo off 30 | set verify off 31 | set timing off 32 | 33 | -- Set AWR_FORMAT to "text" or "html" 34 | define AWR_FORMAT = 'text' 35 | define DEFAULT_OUTPUT_FILENAME = 'awr-generate.sql' 36 | define NO_ADDM = 0 37 | -- start and end snap gap. For example to generate report for 1 hour interval with 15 mins snap set it to 4 38 | define snap_interval = 1 39 | 40 | -- Get values for dbid and inst_num before calling awrinput.sql 41 | 42 | set echo off heading on 43 | column inst_num heading "Inst Num" new_value inst_num format 99999; 44 | column inst_name heading "Instance" new_value inst_name format a12; 45 | column db_name heading "DB Name" new_value db_name format a12; 46 | column dbid heading "DB Id" new_value dbid format 9999999999 just c; 47 | 48 | prompt 49 | prompt Current Instance 50 | prompt ~~~~~~~~~~~~~~~~ 51 | 52 | select d.dbid dbid 53 | , d.name db_name 54 | , i.instance_number inst_num 55 | , i.instance_name inst_name 56 | from v$database d, 57 | v$instance i; 58 | 59 | 60 | -- Call the Oracle common input script to setup start and end snap ids 61 | @@?/rdbms/admin/awrinput.sql 62 | 63 | -- Ask the user for the name of the output script 64 | prompt 65 | prompt Specify output script name 66 | prompt ~~~~~~~~~~~~~~~~~~~~~~~~~~ 67 | prompt This script produces output in the form of another SQL script 68 | prompt The output script contains the commands to generate the AWR Reports 69 | prompt 70 | prompt The default output file name is &DEFAULT_OUTPUT_FILENAME 71 | prompt To accept this name, press to continue, otherwise enter an alternative 72 | prompt 73 | 74 | set heading off 75 | column outfile_name new_value outfile_name noprint; 76 | select 'Using the output file name ' || nvl('&&outfile_name','&DEFAULT_OUTPUT_FILENAME') 77 | , nvl('&&outfile_name','&DEFAULT_OUTPUT_FILENAME') outfile_name 78 | from sys.dual; 79 | 80 | set linesize 800 81 | set serverout on 82 | set termout off 83 | 84 | -- spool to outputfile 85 | spool &outfile_name 86 | 87 | -- write script header comments 88 | prompt REM Temporary script created by awr-generator.sql 89 | prompt REM Used to create multiple AWR reports between two snapshots 90 | select 'REM Created by user '||user||' on '||sys_context('userenv', 'host')||' at '||to_char(sysdate, 'DD-MON-YYYY HH24:MI') from dual; 91 | 92 | set heading on 93 | 94 | DECLARE 95 | 96 | -- Begin iterating through snapshots and generating reports 97 | c_dbid CONSTANT NUMBER := :dbid; 98 | c_inst_num CONSTANT NUMBER := :inst_num; 99 | c_start_snap_id CONSTANT NUMBER := :bid; 100 | c_end_snap_id CONSTANT NUMBER := :eid; 101 | c_awr_options CONSTANT NUMBER := &&NO_ADDM; 102 | c_report_type CONSTANT CHAR(4):= '&&AWR_FORMAT'; 103 | v_awr_reportname VARCHAR2(100); 104 | v_report_suffix CHAR(5); 105 | c_snap_internaval CONSTANT NUMBER := &&snap_interval; 106 | 107 | CURSOR c_snapshots IS 108 | select inst_num, start_snap_id, end_snap_id, seqnum 109 | from ( 110 | select s.instance_number as inst_num, 111 | s.snap_id as start_snap_id, 112 | lead(s.snap_id,c_snap_internaval,null) over (partition by s.instance_number order by s.snap_id) as end_snap_id, 113 | row_number() over (partition by s.instance_number order by s.snap_id) as seqnum 114 | from dba_hist_snapshot s 115 | where s.dbid = c_dbid 116 | and s.snap_id >= c_start_snap_id 117 | and s.snap_id <= c_end_snap_id 118 | ) 119 | where end_snap_id is not null 120 | and mod(seqnum, c_snap_internaval) = 0 121 | order by inst_num, start_snap_id; 122 | 123 | BEGIN 124 | 125 | dbms_output.put_line(''); 126 | dbms_output.put_line('prompt Beginning AWR Generation...'); 127 | 128 | dbms_output.put_line('set heading off feedback off lines 800 pages 5000 trimspool on trimout on'); 129 | 130 | -- Determine report type (html or text) 131 | IF c_report_type = 'html' THEN 132 | v_report_suffix := '.html'; 133 | ELSE 134 | v_report_suffix := '.txt'; 135 | END IF; 136 | 137 | -- Iterate through snapshots 138 | FOR cr_snapshot in c_snapshots 139 | LOOP 140 | -- Construct filename for AWR report 141 | v_awr_reportname := 'awrrpt_'||cr_snapshot.inst_num||'_'||cr_snapshot.start_snap_id||'_'||cr_snapshot.end_snap_id||v_report_suffix; 142 | 143 | dbms_output.put_line('prompt Creating AWR Report '||v_awr_reportname 144 | ||' for instance number '||cr_snapshot.inst_num||' snapshots '||cr_snapshot.start_snap_id||' to '||cr_snapshot.end_snap_id); 145 | dbms_output.put_line('prompt'); 146 | 147 | -- Disable terminal output to stop AWR text appearing on screen 148 | dbms_output.put_line('set termout off'); 149 | 150 | -- Set spool to create AWR report file 151 | dbms_output.put_line('spool '||v_awr_reportname); 152 | 153 | -- call the table function to generate the report 154 | IF c_report_type = 'html' THEN 155 | dbms_output.put_line('select output from table(dbms_workload_repository.awr_report_html(' 156 | ||c_dbid||','||cr_snapshot.inst_num||','||cr_snapshot.start_snap_id||','||cr_snapshot.end_snap_id||','||c_awr_options||'));'); 157 | ELSE 158 | dbms_output.put_line('select output from table(dbms_workload_repository.awr_report_text(' 159 | ||c_dbid||','||cr_snapshot.inst_num||','||cr_snapshot.start_snap_id||','||cr_snapshot.end_snap_id||','||c_awr_options||'));'); 160 | END IF; 161 | 162 | dbms_output.put_line('spool off'); 163 | 164 | -- Enable terminal output having finished generating AWR report 165 | dbms_output.put_line('set termout on'); 166 | 167 | END LOOP; 168 | 169 | dbms_output.put_line('set heading on feedback 6 lines 100 pages 45'); 170 | 171 | dbms_output.put_line('prompt AWR Generation Complete'); 172 | 173 | -- EXCEPTION HANDLER? 174 | 175 | END; 176 | / 177 | 178 | spool off 179 | 180 | set termout on 181 | 182 | prompt 183 | prompt Script written to &outfile_name - check and run in order to generate AWR reports... 184 | prompt 185 | 186 | --clear columns sql 187 | undefine outfile_name 188 | undefine AWR_FORMAT 189 | undefine DEFAULT_OUTPUT_FILENAME 190 | undefine NO_ADDM 191 | undefine OUTFILE_NAME 192 | 193 | set feedback 6 verify on lines 100 pages 45 194 | -------------------------------------------------------------------------------- /awr-io.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # awr-io.sh - Simple script to extract IO information from an Oracle AWR report 4 | # 5 | # Author: flashdba (http://flashdba.com) 6 | # 7 | # For educational purposes only - no warranty is provided 8 | # Test thoroughly - use at your own risk 9 | 10 | total_iops() { 11 | TOTAL_IOPS=`grep "Total Requests:" $file | awk '{ print $4 }'` 12 | return 0 13 | } 14 | 15 | total_throughput() { 16 | TOTAL_THROUGHPUT=`grep "Total (MB):" $file | grep -v Optimized | awk '{ print $4 }'` 17 | return 0 18 | } 19 | 20 | latency() { 21 | READ_LATENCY=`grep -A 10 "Top 10 Foreground" $file | grep "db file sequential read" | awk '{ print $7 }'` 22 | return 0 23 | } 24 | 25 | if [ "$#" -lt 1 ]; then 26 | echo "Usage: $0 " 27 | exit 1 28 | fi 29 | 30 | for file in $*; do 31 | total_iops 32 | total_throughput 33 | latency 34 | echo "$file: IOPS = $TOTAL_IOPS THROUGHPUT: $TOTAL_THROUGHPUT READ LATENCY = $READ_LATENCY" 35 | done 36 | exit 0 37 | -------------------------------------------------------------------------------- /awr-parser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # AWR Parser script : tool for extracting data from Oracle AWR reports 4 | # 5 | # See GitHub repository at https://github.com/flashdba/scripts 6 | # 7 | # ########################################################################### 8 | # # # 9 | # # Copyright (C) {2014,2015,2016} Author: flashdba (http://flashdba.com) # 10 | # # # 11 | # # This program is free software; you can redistribute it and/or modify # 12 | # # it under the terms of the GNU General Public License as published by # 13 | # # the Free Software Foundation; either version 2 of the License, or # 14 | # # (at your option) any later version. # 15 | # # # 16 | # # This program is distributed in the hope that it will be useful, # 17 | # # but WITHOUT ANY WARRANTY; without even the implied warranty of # 18 | # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 19 | # # GNU General Public License for more details. # 20 | # # # 21 | # # You should have received a copy of the GNU General Public License along # 22 | # # with this program; if not, write to the Free Software Foundation, Inc., # 23 | # # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 24 | # # # 25 | # ########################################################################### 26 | # 27 | AWRSCRIPT_VERSION="1.02" 28 | AWRSCRIPT_LASTUPDATE="04/12/2016" 29 | # 30 | # Used to parse multiple AWR reports and extract useful information 31 | # The input is an AWR workload repository report **in TEXT format** 32 | # - HTML format reports will be ignored, as will STATSPACK reports 33 | # The output is a CSV file which can be used in Microsoft Excel etc 34 | # 35 | # Usage: ./awr-parser.sh [ -n | -H ] [ -s | -p | -v ] (wildcards are accepted) 36 | # 37 | # Script for parsing multiple AWR reports and extracting useful information 38 | # Redirect stdout to a CSV file to import into Excel 39 | # Errors and info are printed to stderr 40 | # 41 | # Options: 42 | # -h Help (print help and version information) 43 | # -H Header (print the header row only and then exit) 44 | # -n NoHeader (do not print the header row in the CSV file) 45 | # -p Print (print AWR report values to screen) 46 | # -s Silent (do not print AWR processing information) 47 | # -v Verbose (show extra AWR processing details) 48 | # -X DEBUG *** HIDDEN OPTION FOR DEBUGGING *** 49 | # 50 | # Return Values: 51 | # 0 Complete Success (all files processed) 52 | # 1 Partial Success (some files processed) 53 | # 2 Failure (no files processed) 54 | # 55 | # Example: 56 | # ./awr-parser.sh -v awrrpt*.txt > output.csv 57 | # 58 | # Version History 59 | # 60 | # 1.00 01/12/2014 flashdba Initial release (open sourced from AWR-Analyze.sh) 61 | # 1.01 05/01/2015 flashdba Added ability to read Wait Event Histogram sections 62 | # 1.02 04/12/2016 flashdba Bugfix: Exadata statistics cause incorrect read of physical read/write throughput 63 | 64 | # I have recently learnt that the way I calculate Redo write IOPS/Throughput is incorrect. The Oracle statistic "redo size" does 65 | # not take into account multiplexing of online redo logs, nor does it include the value of "redo wastage". For this reason the 66 | # parsed values for Redo Write IOPS/Throughput and Data Write IOPTS/Throughput are likely to be incorrect. The fix (TODO) will 67 | # be to read the values for Redo from the IOStat section of later AWR reports, or the IO Profile section of >= 11.2.0.4 68 | 69 | # A note about the use of bc - the Basic Calculator 70 | # This script uses bc in numerous places so if running via Cygwin ensure bc is installed (it is not part of the default install) 71 | # When reducing the scale of numbers in bc, the default behaviour is simply to drop the extra decimal places insetad of rounding 72 | # To make bc round we have to use a hack where we add half a decimal point and then divide by one 73 | # For example, when reducing to one decimal place we add 0.05 then divide by 1 causing bc to implement the scale reduction 74 | # Alternatively, when reducing to three decimal places we add 0.0005 then divide by 1...it's not pretty, but it works just fine 75 | 76 | # Define counters and flags 77 | ERRORCNT=0 # Count number of files where processing errors occurred 78 | FILECNT=0 # Count number of files where processing was attempted 79 | HEADERROW=1 # 0 = No, 1 = Yes, 2 = Only 80 | SILENT=0 # 0 = No, 1 = Yes 81 | PRINT_REPORT_INFO=0 # 0 = No, 1 = Yes 82 | VERBOSE=0 # 0 = No, 1 = Yes 83 | DEBUG=0 # 0 = No, 1 = Yes 84 | # Define constants 85 | EXIT_SUCCESS=0 86 | EXIT_PARTIAL_SUCCESS=1 87 | EXIT_FAILURE=2 88 | AWR_NOTFOUND=0 89 | AWR_PENDING=1 90 | AWR_FOUND=2 91 | # Define section terminators in AWR reports (a string of 61 hyphens) 92 | # Two variables are needed deending on whether we are searching by line or word (see comments on the IFS variable) 93 | OLD_AWR_SECTION_TERMINATOR_BY_WORD="-------------------------------------------------------------" 94 | OLD_AWR_SECTION_TERMINATOR_BY_LINE=" -------------------------------------------------------------" 95 | # In 12c format reports the section terminators are different - there are only 54 hyphens 96 | NEW_AWR_SECTION_TERMINATOR_BY_WORD="------------------------------------------------------" 97 | NEW_AWR_SECTION_TERMINATOR_BY_LINE=" ---------------------------------------------" 98 | # Define field terminator for use with debugging the contents of variables 99 | ENDCHAR="" 100 | 101 | # Define functions for printing messages - echodbg includes call to translate the # character into horizontal tab then expand back to spaces (makes debug easier to read) 102 | echoerr() { echo "Error: $@" 1>&2; let ERRORCNT++; } 103 | echoinf() { [[ "$SILENT" = 1 ]] || echo "Info : ${@}${ENDCHAR}" 1>&2; } 104 | echoprt() { echo "Info : ${@}${ENDCHAR}" 1>&2; } 105 | echovrb() { [[ "$VERBOSE" = 1 ]] && echo "Info : ${@}${ENDCHAR}" 1>&2; } 106 | echodbg() { [[ "$DEBUG" = 1 ]] && echo "Debug: ${@}" | tr '#' '\t' | expand -t 15 1>&2; } 107 | echocsv() { echo "$@"; } 108 | 109 | # Function for printing usage information 110 | usage() { 111 | if [ "$#" -gt 0 ]; then 112 | echo "Error: $@" 1>&2 113 | fi 114 | echo "Usage: $0 [ -n | -H ] [ -s | -p | -v ] (wildcards are accepted)" 1>&2 115 | echo "" 1>&2 116 | echo " Version v${AWRSCRIPT_VERSION} (published on $AWRSCRIPT_LASTUPDATE)" 117 | echo "" 1>&2 118 | echo " Script for parsing multiple AWR reports and extracting useful information" 119 | echo " Redirect stdout to a CSV file to import into Excel" 1>&2 120 | echo " Errors and info are printed to stderr" 1>&2 121 | echo "" 1>&2 122 | echo " Options:" 1>&2 123 | echo " -h Help (print help and version information)" 1>&2 124 | echo " -H Header (print the header row only and then exit)" 1>&2 125 | echo " -n NoHeader (do not print the header row in the CSV file)" 1>&2 126 | echo " -p Print (print AWR report values to screen)" 1>&2 127 | echo " -s Silent (do not print AWR processing information)" 1>&2 128 | echo " -v Verbose (show extra AWR processing details)" 1>&2 129 | echo "" 1>&2 130 | echo " Example usage:" 1>&2 131 | echo " $0 awr*.txt > awr.csv" 1>&2 132 | echo "" 1>&2 133 | exit $EXIT_FAILURE 134 | } 135 | 136 | # Function for setting the Internal Field Seperator so that lines read from the AWR file are word-delimited 137 | # This means that spaces, tabs and newlines are all used as field seperators 138 | set_ifs_to_word_delimited() { 139 | IFS_DELIMITER="WORD" 140 | IFS=$' \t\n' && echodbg " Setting IFS to SPACE, TAB and NEWLINE" 141 | } 142 | 143 | # Function for setting the Internal Field Seperator so that lines read from the AWR file are line-delimited 144 | # This means that only newlines are used as field seperators, while spaces and tabs are not 145 | set_ifs_to_line_delimited() { 146 | IFS_DELIMITER="LINE" 147 | IFS=$'\n' && echodbg " Setting IFS to NEWLINE" 148 | } 149 | 150 | # Function for determining the width and location of columns within each AWR section 151 | # It is passed the header row (a set of hyphens) as input and updates a set of variables accordingly 152 | process_header_row() { 153 | echodbg "Entering process_header_row() with argument $1" 154 | # Clear the column variables down 155 | unset AWRCOL1 AWRCOL2 AWRCOL3 AWRCOL4 AWRCOL5 AWRCOL6 AWRCOL7 AWRCOL8 AWRCOL9 AWRCOL10 156 | if [ -z "$1" ]; then 157 | echodbg "process_header_row() called with zero arguments - doing nothing" 158 | PROCESS_HEADER_ROW="NO_DATA" 159 | return $EXIT_FAILURE 160 | else 161 | # Set IFS to be word delimited 162 | [[ "$IFS_DELIMITER" = "LINE" ]] && IFS=$' \t\n' 163 | HEADERROW_ARRAY=($1) 164 | HEADERROW_COLUMNS="${#HEADERROW_ARRAY[@]}" 165 | 166 | # If necessary change the IFS back to line delimited 167 | [[ "$IFS_DELIMITER" = "LINE" ]] && IFS=$'\n' 168 | 169 | # If there are less than six words in this header then abandon attempt to process this section 170 | if [ "$HEADERROW_COLUMNS" -lt "6" ]; then 171 | echovrb "Failed during process_header_row() because header did not have enough arguments ($HEADERROW_COLUMNS)" 172 | PROCESS_HEADER_ROW="FAILED" 173 | return $EXIT_FAILURE 174 | elif [ "$HEADERROW_COLUMNS" -gt "10" ]; then 175 | echovrb "Failed during process_header_row() because header had too many arguments ($HEADERROW_COLUMNS)" 176 | PROCESS_HEADER_ROW="FAILED" 177 | return $EXIT_FAILURE 178 | else 179 | echodbg "Analyzing header row with $HEADERROW_COLUMNS columns" 180 | fi 181 | 182 | # Variable for use in while loop iterating through columns in header row 183 | AWRCOLNUM=1 184 | # Use a counter to keep track of the column locations 185 | COL_COUNTER=1 186 | 187 | # Begin calculating column locations 188 | while [ "$AWRCOLNUM" -le "$HEADERROW_COLUMNS" ]; do 189 | eval AWRCOL${AWRCOLNUM}="${COL_COUNTER}-$(($COL_COUNTER + ${#HEADERROW_ARRAY[${AWRCOLNUM} - 1]} - 1))" 190 | COL_COUNTER=$(($COL_COUNTER + ${#HEADERROW_ARRAY[${AWRCOLNUM}-1]} + 1)) 191 | let AWRCOLNUM++ 192 | done 193 | echodbg "Computed column widths: AWRCOL1=$AWRCOL1, AWRCOL2=$AWRCOL2, AWRCOL3=$AWRCOL3, AWRCOL4=$AWRCOL4, AWRCOL5=$AWRCOL5, AWRCOL6=$AWRCOL6, AWRCOL7=$AWRCOL7, AWRCOL3=$AWRCOL8, AWRCOL4=$AWRCOL9, AWRCOL5=$AWRCOL10" 194 | PROCESS_HEADER_ROW="SUCCESS" 195 | return $EXIT_SUCCESS 196 | fi 197 | } 198 | 199 | # Function for processing AWR header section and extracting information about the system 200 | process_awr_report() { 201 | # Read the AWR report looking for key sections containing required information 202 | # Note that different versions of Oracle have different formats for the AWR header 203 | # For the first two sections we have to look for a header and then set a flag (to $AWR_FOUND) 204 | # This flag then triggers specific behaviour over the next defined number of lines 205 | # For example, the phrase "DB Name" indicates the start of the DB Details section 206 | # We therefore know that two lines later will contain the DB name, instance num, version etc 207 | # After this the report is divided up into sections, each of which has its own handler below 208 | # There are two methods of parsing the data depending on the way it is formatted in the report 209 | # For one method (e.g. the Profile section) we read each word on the line into its own array element 210 | # We then pick the data out based on its position relative to the number of words in the line 211 | # The other method is to pick data out based on start and end character positions (e.g. the Top 5 section) 212 | # For this method we read the entire line into one array element and parse it using the cut tool 213 | # Switching between these two methods is a case of changing the Internal Field Seperator (IFS) variable 214 | # IFS is either set to space, tab and newline (word method) or just newline (character method) 215 | 216 | # Define a set of variables 217 | ROWCNT=0 # Counter for incrementing as rows of each report are read 218 | TOP5_LINENUM=0 # Counter for incrementing as wait details in Top 5 section are read 219 | AWR_FORMAT="Unknown" # Variable to hold the format version of the AWR report 220 | AWRLINE_SKIP=0 # When value n is greater than zero the next n non-empty lines will be skipped 221 | AWRSECTION_SKIP=0 # When value n is greater than zero the next n AWR sections will be skipped 222 | BAILOUT_COUNTER=0 # Counter for incrementing when searching for the header row of certain sections 223 | BAILOUT_LIMIT=10 # Threshold beyond which hander will abandon searching for the header row 224 | FOUND_SYS_DETAILS=$AWR_NOTFOUND # This is set to AWR_FOUND when the database system details are found 225 | FOUND_HOST_DETAILS=$AWR_NOTFOUND # This is set to AWR_FOUND when the host system details are found 226 | FOUND_TOP5_EVENTS=$AWR_NOTFOUND # This is set to AWR_FOUND when the Top 5 foreground event details are found (Top 10 in 12c) 227 | FOUND_FG_WAIT_CLASS=$AWR_NOTFOUND # This is set to AWR_FOUND when the foreground wait class details are found 228 | FOUND_FG_WAIT_EVENTS=$AWR_NOTFOUND # This is set to AWR_FOUND when the foreground wait event details are found 229 | FOUND_BG_WAIT_EVENTS=$AWR_NOTFOUND # This is set to AWR_FOUND when the background wait event details are found 230 | FOUND_HG_WAIT_EVENTS=$AWR_NOTFOUND # This is set to AWR_FOUND when the wait event histogram details are found 231 | TOTAL_WAIT_TIME=0 # Counter used in wait class section to sum wait times if DB TIME not present in report 232 | AWR_SECTION="AWRProfile" # Current section - influences which handler routine will be used to process data 233 | echodbg "State change AWR_SECTION: reset to Profile" 234 | 235 | # Reset the AWR section terminator varibles to those that match 10g and 11g 236 | AWR_SECTION_TERMINATOR_BY_WORD="$OLD_AWR_SECTION_TERMINATOR_BY_WORD" 237 | AWR_SECTION_TERMINATOR_BY_LINE="$OLD_AWR_SECTION_TERMINATOR_BY_LINE" 238 | 239 | # Process the file one line at a time using the read commant - each line will be read into the array AWRLINE and processed 240 | # For the first section of the AWR report (the Profile) we want each word on a line to live in a seperate element of an array 241 | # We therefore need to set the IFS (Internal Field Seperator) variable to recognise spaces and tabs as delimiters 242 | # Later on, when processing other sections, we will change this so that only new lines are recognised as delimiters 243 | set_ifs_to_word_delimited 244 | 245 | # Begin reading file line by line placing the contents into an array variable 246 | while read -r -a AWRLINE; do 247 | # Increment row counter 248 | let ROWCNT++ 249 | # Remove carriage returns and form feed characters from first element of array to aid in pattern matching later on 250 | AWRLINE[0]=$(echo ${AWRLINE[0]} | tr -d '\r\f') 251 | 252 | # If line is empty (after removal of control characters) then do not process 253 | if [ "${#AWRLINE[@]}" = 1 ] && [ -z "${AWRLINE[0]}" ]; then 254 | echodbg " Skipping blank line#line $ROWCNT Size=${#AWRLINE[@]} IFS=$IFS_DELIMITER =#${ENDCHAR}${AWRLINE[@]}${ENDCHAR}" 255 | continue 256 | 257 | # Check for situation where report was generated using SELECT output FROM TABLE(DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_TEXT) 258 | # and user did not set heading to 0 resulting in repeated header lines throughout report - skip these lines 259 | elif [ "${#AWRLINE[@]}" -le 2 ] && [ "${AWRLINE[0]:0:6}" = "OUTPUT" ]; then 260 | # The next line will be a set of SQLPlus underline characters (usually hyphens) which need to be ignored 261 | # Therefore increment the counter which controls line skipping 262 | echodbg " SQLPlus header at line $ROWCNT - ignoring this plus next line =#${ENDCHAR}${AWRLINE[@]}${ENDCHAR}" 263 | let AWRLINE_SKIP++ 264 | continue 265 | 266 | # If AWRLINE_SKIP greater than zero then decrement and ignore current line 267 | elif [ "$AWRLINE_SKIP" -gt 0 ]; then 268 | echodbg " Skipping line $ROWCNT due to AWRLINE_SKIP counter ($AWRLINE_SKIP) =#${ENDCHAR}${AWRLINE[@]}${ENDCHAR}" 269 | let AWRLINE_SKIP-- 270 | continue 271 | 272 | # Check for the standard AWR section terminator (a string of 61 hyphen characters) when IFS is set to word delimited 273 | elif [ "$IFS_DELIMITER" = "WORD" ] && [ "${AWRLINE[0]}" = "$AWR_SECTION_TERMINATOR_BY_WORD" ]; then 274 | echodbg " In $AWR_SECTION#line $ROWCNT Size=${#AWRLINE[@]} IFS=$IFS_DELIMITER =#${ENDCHAR}${AWRLINE[@]}${ENDCHAR}" 275 | if [ "$AWRSECTION_SKIP" -gt 0 ]; then 276 | let AWRSECTION_SKIP-- 277 | echodbg "Found AWR section terminator at $ROWCNT - decrementing AWRSECTION_SKIP counter to $AWRSECTION_SKIP" 278 | elif [ "$AWR_SECTION" != "SearchingForNextSection" ]; then 279 | echovrb "Found AWR section terminator at $ROWCNT - marking end of section $AWR_SECTION" 280 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 281 | AWR_SECTION="SearchingForNextSection" 282 | # Switch Internal Field Seperator to only recognise newlines as delimiters 283 | set_ifs_to_line_delimited 284 | fi 285 | continue 286 | 287 | # Check for the standard AWR section terminator (a string of 61 hyphen characters) when IFS is set to line delimited 288 | elif [ "$IFS_DELIMITER" = "LINE" ] && [ "${AWRLINE[0]:0:71}" = "$AWR_SECTION_TERMINATOR_BY_LINE" ]; then 289 | echodbg " In $AWR_SECTION#line $ROWCNT Size=${#AWRLINE[@]} IFS=$IFS_DELIMITER =#${ENDCHAR}${AWRLINE[@]}${ENDCHAR}" 290 | if [ "$AWRSECTION_SKIP" -gt 0 ]; then 291 | let AWRSECTION_SKIP-- 292 | echodbg "Found AWR section terminator at $ROWCNT - decrementing AWRSECTION_SKIP counter to $AWRSECTION_SKIP" 293 | elif [ "$AWR_SECTION" != "SearchingForNextSection" ]; then 294 | echovrb "Found AWR section terminator at $ROWCNT - marking end of section $AWR_SECTION" 295 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 296 | AWR_SECTION="SearchingForNextSection" 297 | # Switch Internal Field Seperator to only recognise newlines as delimiters 298 | set_ifs_to_line_delimited 299 | fi 300 | continue 301 | 302 | # If AWRSECTION_SKIP greater than zero then ignore current line 303 | elif [ "$AWRSECTION_SKIP" -gt 0 ]; then 304 | echodbg " Skipping line $ROWCNT due to AWRSECTION_SKIP counter ($AWRSECTION_SKIP) =#${ENDCHAR}${AWRLINE[@]}${ENDCHAR}" 305 | continue 306 | 307 | # If debug is enabled print the whole line 308 | else 309 | echodbg " In $AWR_SECTION#line $ROWCNT Size=${#AWRLINE[@]} IFS=$IFS_DELIMITER =#${ENDCHAR}${AWRLINE[@]}${ENDCHAR}" 310 | fi 311 | # Begin processing code - different sections of the report have different handling routines which are enabled through the AWR_SECTION variable 312 | 313 | ################################################################## Searching For Next Section ################################################################## 314 | if [ "$AWR_SECTION" = "SearchingForNextSection" ]; then 315 | # Routine for searching for the start of the next known section and identifying the correct handler routine 316 | # This section is also responsible for correctly settings the Internal Field Seperator prior to entering the next handler routine 317 | case "${AWRLINE[0]:0:40}" in 318 | "Top 5 Timed Events "*) 319 | # Start of the Top 5 Timed Events section found in 10g format AWR reports 320 | echovrb "Start of 10g Top 5 section found at line $ROWCNT" 321 | echodbg "State change AWR_SECTION: $AWR_SECTION -> Top5Foreground" 322 | AWR_SECTION="Top5Foreground" 323 | # There are three more rows of header to skip before processing this section 324 | AWRLINE_SKIP=2 325 | # Reset the bailout counter so that we can search for the header row of this section 326 | BAILOUT_COUNTER=0 327 | # Set Internal Field Seperator to read entire line into single array element 328 | set_ifs_to_line_delimited 329 | continue 330 | ;; 331 | "Top 5 Timed Foreground Events"*) 332 | # Start of the Top 5 Foreground Timed Events section found in 11g format AWR reports 333 | echovrb "Start of 11g Top 5 section found at line $ROWCNT" 334 | echodbg "State change AWR_SECTION: $AWR_SECTION -> Top5Foreground" 335 | AWR_SECTION="Top5Foreground" 336 | # Set Internal Field Seperator to read entire line into single array element 337 | set_ifs_to_line_delimited 338 | # There are five more rows of header to skip before processing this section 339 | AWRLINE_SKIP=4 340 | # Reset the bailout counter so that we can search for the header row of this section 341 | BAILOUT_COUNTER=0 342 | continue 343 | ;; 344 | "Top 10 Foreground Events by Total Wait T") 345 | # Start of the Top 10 Foreground Events section found in newer format 11g and 12c AWR reports 346 | # To process this we use the same handler as the Top 5 Events found in older 10g and 11g reports 347 | echovrb "Start of Top 10 section found at line $ROWCNT" 348 | echodbg "State change AWR_SECTION: $AWR_SECTION -> Top5Foreground" 349 | AWR_SECTION="Top5Foreground" 350 | # Set Internal Field Seperator to read entire line into single array element 351 | set_ifs_to_line_delimited 352 | # There are four more rows of header to skip before processing this section 353 | AWRLINE_SKIP=3 354 | # Reset the bailout counter so that we can search for the header row of this section 355 | BAILOUT_COUNTER=0 356 | continue 357 | ;; 358 | "Cache Sizes"*) 359 | # Start of the Cache Sizes section 360 | echovrb "Start of CacheSizes section found at line $ROWCNT" 361 | echodbg "State change AWR_SECTION: $AWR_SECTION -> CacheSizes" 362 | AWR_SECTION="CacheSizes" 363 | # Set Internal Field Seperator to read each word into a different element of the array 364 | set_ifs_to_word_delimited 365 | # There is one more row of header to skip before processing this section 366 | AWRLINE_SKIP=1 367 | continue 368 | ;; 369 | "Time Model Statistics "*) 370 | # Start of the Time Model Statistics section 371 | echovrb "Start of Time Model Statistics section found at line $ROWCNT" 372 | # We only need information from this section if this is a 10g format AWR Report 373 | if [ "$AWR_FORMAT" != "10" ]; then 374 | echovrb "Ignoring Time Model Statistics because AWR_FORMAT $AWR_FORMAT not 10" 375 | AWRSECTION_SKIP=1 376 | continue 377 | fi 378 | echodbg "State change AWR_SECTION: $AWR_SECTION -> TimeModelStatistics" 379 | AWR_SECTION="TimeModelStatistics" 380 | # Set Internal Field Seperator to read each word into a different element of the array 381 | set_ifs_to_word_delimited 382 | # There are six more rows of header to skip before processing this section 383 | AWRLINE_SKIP=6 384 | continue 385 | ;; 386 | "Operating System Statistics "*) 387 | # Start of the Operating System Statistics section 388 | echovrb "Start of Operating System Stats section found at line $ROWCNT" 389 | echodbg "State change AWR_SECTION: $AWR_SECTION -> OperatingSystemStats" 390 | AWR_SECTION="OperatingSystemStats" 391 | # Set Internal Field Seperator to read each word into a different element of the array 392 | set_ifs_to_word_delimited 393 | # Depending on the AWR format there are more rows of header to skip before processing the Operating System Stats section 394 | if [ "$AWR_FORMAT" = "10" ]; then 395 | AWRLINE_SKIP=2 396 | else 397 | AWRLINE_SKIP=5 398 | fi 399 | continue 400 | ;; 401 | "Wait Class "*) 402 | # If this is not 10g then ignore 403 | if [ "$AWR_FORMAT" != "10" ]; then 404 | echovrb "Ignoring Wait Class header because AWR_FORMAT $AWR_FORMAT not 10" 405 | continue 406 | fi 407 | # Start of Foreground Wait Class section in 10g versions 408 | echovrb "Start of Foreground Wait Class section found at line $ROWCNT" 409 | echodbg "State change AWR_SECTION: $AWR_SECTION -> ForegroundWaitClass" 410 | AWR_SECTION="ForegroundWaitClass" 411 | # Set the FOUND_FG_WAIT_CLASS variable to AWR_FOUND for use with 10g calculation of DB Time in post-processing section 412 | FOUND_FG_WAIT_CLASS=$AWR_FOUND 413 | # Set Internal Field Seperator to read entire line into single array element 414 | set_ifs_to_line_delimited 415 | # There are nine more rows of header to skip before processing the Foreground Wait Class section 416 | AWRLINE_SKIP=7 417 | continue 418 | ;; 419 | "Foreground Wait Class "*) 420 | # Start of Foreground Wait Class section in 11g and 12c versions 421 | echovrb "Start of Foreground Wait Class section found at line $ROWCNT" 422 | echodbg "State change AWR_SECTION: $AWR_SECTION -> ForegroundWaitClass" 423 | AWR_SECTION="ForegroundWaitClass" 424 | # Set Internal Field Seperator to read entire line into single array element 425 | set_ifs_to_line_delimited 426 | # There are nine more rows of header to skip before processing the Foreground Wait Class section 427 | AWRLINE_SKIP=7 428 | continue 429 | ;; 430 | "Wait Events "*) 431 | # Start of the Foreground Wait Events section in 10g versions 432 | echovrb "Start of Foreground Wait Events section found at line $ROWCNT" 433 | echodbg "State change AWR_SECTION: $AWR_SECTION -> ForegroundWaitEvents" 434 | AWR_SECTION="ForegroundWaitEvents" 435 | # Set Internal Field Seperator to read entire line into single array element 436 | set_ifs_to_line_delimited 437 | # There are nine more rows of header to skip before processing the Foreground Wait Class section 438 | AWRLINE_SKIP=3 439 | # Reset the bailout counter so that we can search for the header row of this section 440 | BAILOUT_COUNTER=0 441 | continue 442 | ;; 443 | "Foreground Wait Events "*) 444 | # Start of the Foreground Wait Events section in versions later than 10g 445 | echovrb "Start of Foreground Wait Events section found at line $ROWCNT" 446 | echodbg "State change AWR_SECTION: $AWR_SECTION -> ForegroundWaitEvents" 447 | AWR_SECTION="ForegroundWaitEvents" 448 | # Set Internal Field Seperator to read entire line into single array element 449 | set_ifs_to_line_delimited 450 | # There are eight more rows of header to skip before processing the Foreground Wait Class section 451 | AWRLINE_SKIP=3 452 | # Reset the bailout counter so that we can search for the header row of this section 453 | BAILOUT_COUNTER=0 454 | continue 455 | ;; 456 | "Background Wait Events "*) 457 | # Start of the Background Wait Events section 458 | echovrb "Start of Background Wait Events section found at line $ROWCNT" 459 | echodbg "State change AWR_SECTION: $AWR_SECTION -> BackgroundWaitEvents" 460 | AWR_SECTION="BackgroundWaitEvents" 461 | # Set Internal Field Seperator to read entire line into single array element 462 | set_ifs_to_line_delimited 463 | # Depending on the AWR format there are more rows of header to skip before processing the Background Wait Events section 464 | AWRLINE_SKIP=3 465 | # Reset the bailout counter so that we can search for the header row of this section 466 | BAILOUT_COUNTER=0 467 | continue 468 | ;; 469 | "Wait Event Histogram "*) 470 | # Start of the Wait Event Histogram section 471 | echovrb "Start of Wait Event Histogram section found at line $ROWCNT" 472 | echodbg "State change AWR_SECTION: $AWR_SECTION -> WaitEventHistogram" 473 | AWR_SECTION="WaitEventHistogram" 474 | # Set Internal Field Seperator to read entire line into single array element 475 | set_ifs_to_line_delimited 476 | # Depending on the AWR format there are more rows of header to skip before processing the Background Wait Events section 477 | AWRLINE_SKIP=8 478 | # Reset the bailout counter so that we can search for the header row of this section 479 | BAILOUT_COUNTER=0 480 | continue 481 | ;; 482 | "Instance Activity Stats "*) 483 | # Start of the Instance Activity Stats section in 10g and 11g format AWR reports 484 | echovrb "Start of Instance Activity Stats section found at line $ROWCNT" 485 | echodbg "State change AWR_SECTION: $AWR_SECTION -> InstanceActivityStats" 486 | AWR_SECTION="InstanceActivityStats" 487 | # Set Internal Field Seperator to read entire line into single array element 488 | set_ifs_to_line_delimited 489 | # Depending on the AWR format there are more rows of header to skip before processing the Instance Activity Stats section 490 | if [ "$AWR_FORMAT" = "10" ]; then 491 | AWRLINE_SKIP=2 492 | else 493 | AWRLINE_SKIP=3 494 | fi 495 | continue 496 | ;; 497 | "SQL ordered by"*) 498 | # One of the SQL sections - these should be ignored because punctuation characters in SQL can cause problems 499 | echodbg "Found start of SQL ordered by section at line $ROWCNT - setting AWRSECTION_SKIP" 500 | # There are eight more rows of header to skip before processing the Foreground Wait Class section 501 | let AWRSECTION_SKIP++ 502 | continue 503 | ;; 504 | "Other Instance Activity Stats "*) 505 | # Start of the Other Instance Activity Stats section in 12c format AWR reports 506 | # Use the normal Instance Activity Stats handler 507 | echovrb "Start of Other Instance Activity Stats section found at line $ROWCNT" 508 | echodbg "State change AWR_SECTION: $AWR_SECTION -> InstanceActivityStats" 509 | AWR_SECTION="InstanceActivityStats" 510 | # Set Internal Field Seperator to read entire line into single array element 511 | set_ifs_to_line_delimited 512 | # Depending on the AWR format there are more rows of header to skip before processing the Instance Activity Stats section 513 | AWRLINE_SKIP=3 514 | continue 515 | ;; 516 | "Instance Activity Stats - Thread Activit") 517 | # Start of the Instance Activity Stats - Thread Activity section which contains the Log Switches information 518 | echovrb "Start of Instance Activity Stats - Thread Activity section found at line $ROWCNT" 519 | echodbg "State change AWR_SECTION: $AWR_SECTION -> ThreadActivity" 520 | AWR_SECTION="ThreadActivity" 521 | # Set Internal Field Seperator to read each word into a different element of the array 522 | set_ifs_to_word_delimited 523 | # Depending on the AWR format there are more rows of header to skip before processing the Instance Activity Stats section 524 | AWRLINE_SKIP=3 525 | continue 526 | ;; 527 | esac 528 | 529 | # If we make it here, we are searching for the start of a new section and haven't found it, so move on to next line 530 | continue 531 | fi 532 | 533 | ################################################################## AWR Profile Section ################################################################## 534 | if [ "$AWR_SECTION" = "AWRProfile" ]; then 535 | # Routine for handling the AWR Profile section of the report 536 | if [ "$FOUND_SYS_DETAILS" = "$AWR_PENDING" ]; then 537 | # This line contains the database system details 538 | FOUND_SYS_DETAILS=$AWR_FOUND 539 | # Extract data 540 | PROFILE_DBNAME=${AWRLINE[0]} 541 | PROFILE_INSTANCENAME=${AWRLINE[2]} 542 | PROFILE_INSTANCENUM=${AWRLINE[3]} 543 | if [ "$AWR_FORMAT" = "10" ]; then 544 | PROFILE_DBVERSION=${AWRLINE[4]} 545 | PROFILE_CLUSTER=$(echo ${AWRLINE[5]} | cut -c1-1) 546 | if [ -n "${AWRLINE[6]}" ]; then 547 | # AWR reports in Oracle version 10 have the hostname at the end of the DB details line 548 | # The call to tr is necessary to remove the trailing return character 549 | DB_HOSTNAME=$(echo ${AWRLINE[6]} | tr -d '\r') 550 | DB_HOST_OS="Unknown" 551 | else 552 | echovrb "Unable to find Hostname at end of System Details section" 553 | fi 554 | echodbg "Sys Details: DBName=$PROFILE_DBNAME, InstName=$PROFILE_INSTANCENAME, InstNum=$PROFILE_INSTANCENUM, Ver=$PROFILE_DBVERSION, Cluster=$PROFILE_CLUSTER, Hostname=$DB_HOSTNAME, OS=$DB_HOST_OS" 555 | else 556 | PROFILE_DBVERSION=${AWRLINE[6]} 557 | PROFILE_CLUSTER=$(echo ${AWRLINE[7]} | cut -c1-1) 558 | echodbg "Sys Details: DBName=$PROFILE_DBNAME, InstName=$PROFILE_INSTANCENAME, InstNum=$PROFILE_INSTANCENUM, Ver=$PROFILE_DBVERSION, Cluster=$PROFILE_CLUSTER" 559 | fi 560 | continue 561 | elif [ "$FOUND_HOST_DETAILS" = "$AWR_PENDING" ]; then 562 | # This line contains the host system details 563 | FOUND_HOST_DETAILS=$AWR_FOUND 564 | # Call function to extract data 565 | DB_HOSTNAME=$(echo "${AWRLINE[0]}"| cut -c1-16|sed -e 's/^[ \t]*//;s/[ \t]*$//') 566 | DB_HOST_OS=$(echo "${AWRLINE[0]}"| cut -c17-49|sed -e 's/^[ \t]*//;s/[ \t]*$//') 567 | DB_HOST_MEM=$(echo "${AWRLINE[0]}"| cut -c69-79|sed -e 's/^[ \t]*//;s/[ \t]*$//') 568 | echodbg "Host Details: Hostname=$DB_HOSTNAME, OS=$DB_HOST_OS, HostMem=$DB_HOST_MEM" 569 | # Return Internal Field Seperator to reading each word into a different array element 570 | set_ifs_to_word_delimited 571 | continue 572 | fi 573 | 574 | # Examine first two words 575 | case ${AWRLINE[@]:0:2} in 576 | "DB Name") 577 | # Found Database System Details 578 | [[ "$FOUND_SYS_DETAILS" = "$AWR_FOUND" ]] && continue 579 | echovrb "Start of Database System details at line $ROWCNT" 580 | # AWR reports from 11g on have an extra "Startup Time" column in the profile 581 | if [ "${AWRLINE[@]:7:1}" = "Startup" ]; then 582 | AWR_FORMAT=11 583 | # Later on we will discover if it is actually a 12c report rather than 11g as we assume initially 584 | else 585 | # Assume this is version 10 format 586 | AWR_FORMAT=10 587 | fi 588 | echovrb "Using AWR Format $AWR_FORMAT" 589 | # Skip next line as this is part of the header 590 | AWRLINE_SKIP=1 591 | FOUND_SYS_DETAILS=$AWR_PENDING 592 | continue 593 | ;; 594 | "Host Name") 595 | # Found Host System Details 596 | [[ "$FOUND_HOST_DETAILS" = "$AWR_FOUND" ]] && continue 597 | echovrb "Start of Host System details at line $ROWCNT" 598 | # Skip next line as this is part of the header 599 | AWRLINE_SKIP=1 600 | FOUND_HOST_DETAILS=$AWR_PENDING 601 | # Set Internal Field Seperator to read full line into first array element 602 | set_ifs_to_line_delimited 603 | continue 604 | ;; 605 | "Begin Snap:") 606 | # Found details for start of snapshot 607 | AWR_BEGIN_SNAP=${AWRLINE[2]} 608 | AWR_BEGIN_TIME="${AWRLINE[3]} ${AWRLINE[4]}" 609 | echodbg "AWR_BEGIN_SNAP = ${ENDCHAR}$AWR_BEGIN_SNAP${ENDCHAR}" 610 | echodbg "AWR_BEGIN_TIME = ${ENDCHAR}$AWR_BEGIN_TIME${ENDCHAR}" 611 | continue 612 | ;; 613 | "End Snap:") 614 | # Found details for end of snapshot 615 | AWR_END_SNAP=${AWRLINE[2]} 616 | AWR_END_TIME="${AWRLINE[3]} ${AWRLINE[4]}" 617 | echodbg "AWR_END_SNAP = ${ENDCHAR}$AWR_END_SNAP${ENDCHAR}" 618 | echodbg "AWR_END_TIME = ${ENDCHAR}$AWR_END_TIME${ENDCHAR}" 619 | continue 620 | ;; 621 | "Elapsed:"*) 622 | # Found details for elapsed time 623 | AWR_ELAPSED_TIME=$(echo ${AWRLINE[1]} |sed -e 's/,//g') 624 | echodbg "AWR_ELAPSED_TIME = ${ENDCHAR}$AWR_ELAPSED_TIME${ENDCHAR}" 625 | # Calculate elapsed time in seconds for use when working out throughput values 626 | if [ -n "$AWR_ELAPSED_TIME" ]; then 627 | if [ "$AWR_ELAPSED_TIME" = 0 ]; then 628 | echovrb "Found zero value for AWR_ELAPSED_TIME" 629 | AWR_ELAPSED_TIME_SECS=0 630 | else 631 | echodbg "Calling BC: echo 'scale=3; $AWR_ELAPSED_TIME * 60' | bc -l" 632 | AWR_ELAPSED_TIME_SECS=`echo "scale=3; $AWR_ELAPSED_TIME * 60" | bc -l` 633 | fi 634 | echodbg "AWR_ELAPSED_TIME_SECS = ${ENDCHAR}$AWR_ELAPSED_TIME_SECS${ENDCHAR}" 635 | continue 636 | fi 637 | ;; 638 | "DB Time:") 639 | # Found details for DB time 640 | AWR_DB_TIME=$(echo ${AWRLINE[2]} |sed -e 's/,//g') 641 | echodbg "AWR_DB_TIME = ${ENDCHAR}$AWR_DB_TIME${ENDCHAR}" 642 | # If Elapsed Time known then calculate Average Active Sessions (AAS) 643 | if [ -n "$AWR_ELAPSED_TIME" ]; then 644 | if [ "$AWR_ELAPSED_TIME" = 0 ]; then 645 | echoinf "Cannot calculate Average Active Sessions due to zero AWR_ELAPSED_TIME value" 646 | else 647 | echodbg "Calling BC: AWR_AAS=echo 'scale=1; $AWR_DB_TIME / $AWR_ELAPSED_TIME' | bc -l" 648 | AWR_AAS=`echo "scale=1; $AWR_DB_TIME / $AWR_ELAPSED_TIME" | bc -l` 649 | fi 650 | else 651 | echoinf "Found DB Time but not Elapsed Time - unable to calculate Average Active Sessions" 652 | fi 653 | echodbg "AWR_ELAPSED_TIME = ${ENDCHAR}$AWR_ELAPSED_TIME${ENDCHAR}" 654 | continue 655 | ;; 656 | "Buffer Cache:") 657 | # Found Cache Sizes section containing database block size 658 | # The call to tr is necessary to remove the trailing return character 659 | DB_BLOCK_SIZE=$(echo ${AWRLINE[${#AWRLINE[@]}-1]} | tr -d '\r') 660 | echodbg "DB_BLOCK_SIZE = ${ENDCHAR}$DB_BLOCK_SIZE${ENDCHAR}" 661 | continue 662 | ;; 663 | "Redo size:") 664 | # Found details for redo bytes per second in the 10g and 11g format AWR reports 665 | # Because this number is occasionally very large Oracle may print it in scientific notation so we have to convert this if neccessary 666 | REDO_WRITE_THROUGHPUT=$(echo ${AWRLINE[2]} |sed -e 's/,//g'| sed -e 's/E+/\*10\^/') 667 | # Convert to MB/sec 668 | if [ -n "$REDO_WRITE_THROUGHPUT" ]; then 669 | if [ "$REDO_WRITE_THROUGHPUT" != 0 ]; then 670 | echodbg "Calling BC: REDO_WRITE_THROUGHPUT=echo 'scale=2; (\$(echo 'scale=6; $REDO_WRITE_THROUGHPUT / 1048576' | bc -l)+0.005)/1' | bc -l" 671 | REDO_WRITE_THROUGHPUT=`echo "scale=2; ($(echo "scale=6; $REDO_WRITE_THROUGHPUT / 1048576" | bc -l)+0.005)/1" | bc -l` 672 | fi 673 | fi 674 | echodbg "REDO_WRITE_THROUGHPUT = ${ENDCHAR}${REDO_WRITE_THROUGHPUT}${ENDCHAR}" 675 | continue 676 | ;; 677 | "Redo size") 678 | # Found details for redo bytes per second in the 12c format AWR reports 679 | # Because this number is occasionally very large Oracle may print it in scientific notation so we have to convert this if neccessary 680 | REDO_WRITE_THROUGHPUT=$(echo ${AWRLINE[3]} |sed -e 's/,//g'| sed -e 's/E+/\*10\^/') 681 | # Convert to MB/sec 682 | if [ -n "$REDO_WRITE_THROUGHPUT" ]; then 683 | if [ "$REDO_WRITE_THROUGHPUT" != 0 ]; then 684 | echodbg "Calling BC: REDO_WRITE_THROUGHPUT=echo 'scale=2; (\$(echo 'scale=6; $REDO_WRITE_THROUGHPUT / 1048576' | bc -l)+0.005)/1' | bc -l" 685 | REDO_WRITE_THROUGHPUT=`echo "scale=2; ($(echo "scale=6; $REDO_WRITE_THROUGHPUT / 1048576" | bc -l)+0.005)/1" | bc -l` 686 | fi 687 | fi 688 | echodbg "REDO_WRITE_THROUGHPUT = ${ENDCHAR}${REDO_WRITE_THROUGHPUT}${ENDCHAR}" 689 | # We now know that this is a 12c format AWR report so update the AWR_FORMAT variable accordingly 690 | AWR_FORMAT=12 691 | echovrb "Amending AWR Format to $AWR_FORMAT" 692 | # Amend the section terminator variables accordingly 693 | AWR_SECTION_TERMINATOR_BY_WORD="$NEW_AWR_SECTION_TERMINATOR_BY_WORD" 694 | AWR_SECTION_TERMINATOR_BY_LINE="$NEW_AWR_SECTION_TERMINATOR_BY_LINE" 695 | continue 696 | ;; 697 | "Logical reads:") 698 | # Found details for logical reads per second in the 10g and 11g format AWR reports 699 | AWR_LOGICAL_READS=$(echo ${AWRLINE[2]} |sed -e 's/,//g') 700 | echodbg "AWR_LOGICAL_READS = ${ENDCHAR}${AWR_LOGICAL_READS}${ENDCHAR}" 701 | continue 702 | ;; 703 | "Logical read") 704 | # Found details for logical reads per second in the 12c format AWR reports 705 | AWR_LOGICAL_READS=$(echo ${AWRLINE[3]} |sed -e 's/,//g') 706 | echodbg "AWR_LOGICAL_READS = ${ENDCHAR}${AWR_LOGICAL_READS}${ENDCHAR}" 707 | continue 708 | ;; 709 | "Block changes:") 710 | # Found details for block changes per second 711 | AWR_BLOCK_CHANGES=$(echo ${AWRLINE[2]} |sed -e 's/,//g') 712 | echodbg "AWR_BLOCK_CHANGES = ${ENDCHAR}${AWR_BLOCK_CHANGES}${ENDCHAR}" 713 | continue 714 | ;; 715 | "User calls:") 716 | # Found details for user calls per second 717 | AWR_USER_CALLS=$(echo ${AWRLINE[2]} |sed -e 's/,//g') 718 | echodbg "AWR_USER_CALLS = ${ENDCHAR}${AWR_USER_CALLS}${ENDCHAR}" 719 | continue 720 | ;; 721 | "Parses:"*) 722 | # Found details for parses per second in the 10g and 11g format AWR reports 723 | AWR_PARSES=$(echo ${AWRLINE[1]} |sed -e 's/,//g') 724 | echodbg "AWR_PARSES = ${ENDCHAR}${AWR_PARSES}${ENDCHAR}" 725 | continue 726 | ;; 727 | "Parses"*) 728 | # Found details for parses per second in the 12c format AWR reports 729 | AWR_PARSES=$(echo ${AWRLINE[2]} |sed -e 's/,//g') 730 | echodbg "AWR_PARSES = ${ENDCHAR}${AWR_PARSES}${ENDCHAR}" 731 | continue 732 | ;; 733 | "Hard parses:") 734 | # Found details for hard parses per second in the 10g and 11g format AWR reports 735 | AWR_HARD_PARSES=$(echo ${AWRLINE[2]} |sed -e 's/,//g') 736 | echodbg "AWR_HARD_PARSES = ${ENDCHAR}${AWR_HARD_PARSES}${ENDCHAR}" 737 | continue 738 | ;; 739 | "Hard parses") 740 | # Found details for hard parses per second in the 12c format AWR reports 741 | AWR_HARD_PARSES=$(echo ${AWRLINE[3]} |sed -e 's/,//g') 742 | echodbg "AWR_HARD_PARSES = ${ENDCHAR}${AWR_HARD_PARSES}${ENDCHAR}" 743 | continue 744 | ;; 745 | "Logons:"*) 746 | # Found details for logons per second 747 | AWR_LOGONS=$(echo ${AWRLINE[1]} |sed -e 's/,//g') 748 | echodbg "AWR_LOGONS = ${ENDCHAR}${AWR_LOGONS}${ENDCHAR}" 749 | continue 750 | ;; 751 | "Executes:"*) 752 | # Found details for executes per second in the 10g and 11g format AWR reports 753 | AWR_EXECUTES=$(echo ${AWRLINE[1]} |sed -e 's/,//g') 754 | echodbg "AWR_EXECUTES = ${ENDCHAR}${AWR_EXECUTES}${ENDCHAR}" 755 | continue 756 | ;; 757 | "Executes"*) 758 | # Found details for executes per second in the 12c format AWR reports 759 | AWR_EXECUTES=$(echo ${AWRLINE[2]} |sed -e 's/,//g') 760 | echodbg "AWR_EXECUTES = ${ENDCHAR}${AWR_EXECUTES}${ENDCHAR}" 761 | continue 762 | ;; 763 | "Transactions:"*) 764 | # Found details for transactions per second 765 | # The call to tr is necessary to remove the trailing return character 766 | AWR_TRANSACTIONS=$(echo ${AWRLINE[1]} |sed -e 's/,//g' | tr -d '\r') 767 | echodbg "AWR_TRANSACTIONS = ${ENDCHAR}${AWR_TRANSACTIONS}${ENDCHAR}" 768 | continue 769 | ;; 770 | "Buffer Hit") 771 | # Found buffer hit and in-memory sort ratios 772 | BUFFER_HIT_RATIO=${AWRLINE[3]} 773 | echodbg "BUFFER_HIT_RATION = ${ENDCHAR}${BUFFER_HIT_RATION}${ENDCHAR}" 774 | # The call to tr is necessary to remove the trailing return character 775 | INMEMORY_SORT_RATIO=$(echo ${AWRLINE[7]} | tr -d '\r') 776 | echodbg "INMEMORY_SORT_RATIO = ${ENDCHAR}${INMEMORY_SORT_RATIO}${ENDCHAR}" 777 | continue 778 | ;; 779 | "Instance Efficiency") 780 | # End of AWR Profile section 781 | echovrb "End of AWR Profile section found at line $ROWCNT" 782 | echodbg "State change AWR_SECTION: $AWR_SECTION -> InstanceEfficiency" 783 | AWR_SECTION="InstanceEfficiency" 784 | # Set Internal Field Seperator to read each word into a different element of the array 785 | set_ifs_to_word_delimited 786 | # Skip the following row which is a header 787 | AWRLINE_SKIP=1 788 | continue 789 | ;; 790 | esac 791 | continue 792 | fi # End of handler routine for profile section of AWR report 793 | 794 | ################################################################## Instance Efficiency ################################################################## 795 | if [ "$AWR_SECTION" = "InstanceEfficiency" ]; then 796 | # Routine for handling the Instance Efficiency section of the report 797 | # Examine two words 798 | case ${AWRLINE[@]:0:2} in 799 | "Buffer Hit") 800 | # Found buffer hit and in-memory sort ratios 801 | BUFFER_HIT_RATIO=${AWRLINE[3]} 802 | echodbg "BUFFER_HIT_RATIO = ${ENDCHAR}${BUFFER_HIT_RATIO}${ENDCHAR}" 803 | # The call to tr is necessary to remove the trailing return character 804 | INMEMORY_SORT_RATIO=$(echo ${AWRLINE[7]} | tr -d '\r') 805 | echodbg "INMEMORY_SORT_RATIO = ${ENDCHAR}${INMEMORY_SORT_RATIO}${ENDCHAR}" 806 | echovrb "End of Instance Efficiency section found at line $ROWCNT" 807 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 808 | AWR_SECTION="SearchingForNextSection" 809 | # Switch Internal Field Seperator to only recognise newlines as delimiters 810 | set_ifs_to_line_delimited 811 | continue 812 | ;; 813 | *) 814 | # Catch all other lines and ignore 815 | continue 816 | ;; 817 | esac 818 | fi 819 | 820 | ################################################################## Top 5 Foreground Events ################################################################## 821 | if [ "$AWR_SECTION" = "Top5Foreground" ]; then 822 | # Routine for handling the Top 5 section of the report 823 | if [ "$FOUND_TOP5_EVENTS" = "$AWR_NOTFOUND" ]; then 824 | # We have just begun processing the Top 5 section so first we need to discover the header row (a set of dashes showing the column headings) 825 | if [ "${AWRLINE[0]:0:6}" = "------" ]; then 826 | echodbg "Searching for header row... found" 827 | FOUND_TOP5_EVENTS=$AWR_FOUND 828 | process_header_row "${AWRLINE[0]}" 829 | if [ "$PROCESS_HEADER_ROW" != "SUCCESS" ]; then 830 | echovrb "Unable to determine width of rows in Top 5 / Top 10 Foreground Events section" 831 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 832 | AWR_SECTION="SearchingForNextSection" 833 | # Switch Internal Field Seperator to only recognise newlines as delimiters 834 | set_ifs_to_line_delimited 835 | # Give up trying to process this section 836 | if [ "$AWR_FORMAT" = "12" ]; then 837 | AWRLINE_SKIP=10 838 | else 839 | AWRLINE_SKIP=5 840 | fi 841 | fi 842 | else 843 | let BAILOUT_COUNTER++ 844 | if [ "$BAILOUT_COUNTER" -eq "$BAILOUT_LIMIT" ]; then 845 | echodbg "Failed to find header row (BAILOUT_COUNTER hit threshold = $BAILOUT_COUNTER)" 846 | echovrb "Unable to determine width of rows in Top 5 / Top 10 Foreground Events section" 847 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 848 | AWR_SECTION="SearchingForNextSection" 849 | # Switch Internal Field Seperator to only recognise newlines as delimiters 850 | set_ifs_to_line_delimited 851 | # Give up trying to process this section 852 | if [ "$AWR_FORMAT" = "12" ]; then 853 | AWRLINE_SKIP=10 854 | else 855 | AWRLINE_SKIP=5 856 | fi 857 | else 858 | echodbg "Searching for header row... not found (BAILOUT_COUNTER = $BAILOUT_COUNTER)" 859 | fi 860 | fi 861 | continue 862 | else 863 | # Start processing the Top 5 section 864 | let TOP5_LINENUM++ 865 | # If we are past the fifth line of the Top 5 then the section is over so exit the section handler 866 | # For the Top 10 sections in 12c format reports we do not care about events above the top 5 867 | if [ "$TOP5_LINENUM" -gt "5" ]; then 868 | # End of Top 5 section 869 | echovrb "End of Top 5 section found at line $ROWCNT" 870 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 871 | AWR_SECTION="SearchingForNextSection" 872 | # Switch Internal Field Seperator to only recognise newlines as delimiters 873 | set_ifs_to_line_delimited 874 | continue 875 | fi 876 | fi 877 | 878 | # The variables AWRCOLn are set in the process_header_row function call in the preceding if statement 879 | if [ "${AWRLINE[0]:0:6}" = "DB CPU" -o "${AWRLINE[0]:0:6}" = "CPU tim" ]; then 880 | # This is the DB CPU line which has a different format to the rest 881 | echodbg "Top 5 line $TOP5_LINENUM is DB CPU" 882 | TOP5EVENT_NAME="DB CPU" 883 | TOP5EVENT_WAITS="" 884 | TOP5EVENT_TIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL3}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 885 | TOP5EVENT_AVERAGE="" 886 | TOP5EVENT_PCT_DBTIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL5}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 887 | TOP5EVENT_CLASS="" 888 | else 889 | # This is a normal Top 5 line so handle accordingly 890 | TOP5EVENT_NAME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL1}|sed -e 's/^[ \t]*//;s/[ \t]*$//') 891 | TOP5EVENT_WAITS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL2}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 892 | TOP5EVENT_TIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL3}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 893 | TOP5EVENT_AVERAGE=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 894 | TOP5EVENT_PCT_DBTIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL5}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 895 | TOP5EVENT_CLASS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL6}|sed -e 's/^[ \t]*//;s/[ \t]*$//') 896 | 897 | if [ -n "$TOP5EVENT_WAITS" ]; then 898 | # Check the values extracted are valid numbers 899 | if [[ "$TOP5EVENT_TIME" != *[!0-9,.]* ]]; then 900 | if [[ "$TOP5EVENT_WAITS" != *[!0-9,]* ]]; then 901 | if [ "$TOP5EVENT_WAITS" = 0 ]; then 902 | echovrb "Found zero waits for Top 5 wait event $TOP5EVENT_NAME" 903 | else 904 | # See comments in header section for explanation of the way bc is used in calculating the average on the next lines 905 | echodbg "Calling BC: TOP5EVENT_AVERAGE=echo 'scale=3; (\$(echo 'scale=7; ($TOP5EVENT_TIME / $TOP5EVENT_WAITS) * 1000' | bc -l)+0.0005)/1' | bc -l" 906 | TOP5EVENT_AVERAGE=`echo "scale=3; ($(echo "scale=7; ($TOP5EVENT_TIME / $TOP5EVENT_WAITS) * 1000" | bc -l)+0.0005)/1" | bc -l` 907 | fi 908 | else 909 | echodbg "Unable to parse Top 5 wait event $TOP5EVENT_NAME due to non-numeric string found in TOP5EVENT_WAITS: $TOP5EVENT_WAITS" 910 | fi 911 | else 912 | echodbg "Unable to parse Top 5 wait event $TOP5EVENT_NAME due to non-numeric string found in TOP5EVENT_TIME: $TOP5EVENT_TIME" 913 | fi 914 | fi 915 | fi 916 | echodbg "Top 5 Line $TOP5_LINENUM: Name=$TOP5EVENT_NAME, Waits=$TOP5EVENT_WAITS, Time=$TOP5EVENT_TIME, Ave=$TOP5EVENT_AVERAGE, PctDBTime=$TOP5EVENT_PCT_DBTIME, Class=$TOP5EVENT_CLASS" 917 | 918 | # Now place discovered values into the correct array of variables based on TOP5_LINENUM 919 | #echodbg "eval TOP5EVENT${TOP5_LINENUM}_NAME='$TOP5EVENT_NAME'" 920 | eval TOP5EVENT${TOP5_LINENUM}_NAME='$TOP5EVENT_NAME' 921 | #echodbg "eval TOP5EVENT${TOP5_LINENUM}_NAME='$TOP5EVENT_WAITS'" 922 | eval TOP5EVENT${TOP5_LINENUM}_WAITS='$TOP5EVENT_WAITS' 923 | #echodbg "eval TOP5EVENT${TOP5_LINENUM}_NAME='$TOP5EVENT_TIME'" 924 | eval TOP5EVENT${TOP5_LINENUM}_TIME='$TOP5EVENT_TIME' 925 | #echodbg "eval TOP5EVENT${TOP5_LINENUM}_NAME='$TOP5EVENT_AVERAGE'" 926 | eval TOP5EVENT${TOP5_LINENUM}_AVERAGE='$TOP5EVENT_AVERAGE' 927 | #echodbg "eval TOP5EVENT${TOP5_LINENUM}_NAME='$TOP5EVENT_PCT_DBTIME'" 928 | eval TOP5EVENT${TOP5_LINENUM}_PCT_DBTIME='$TOP5EVENT_PCT_DBTIME' 929 | #echodbg "eval TOP5EVENT${TOP5_LINENUM}_NAME='$TOP5EVENT_CLASS'" 930 | eval TOP5EVENT${TOP5_LINENUM}_CLASS='$TOP5EVENT_CLASS' 931 | 932 | fi # End of handler routine for Top 5 section of AWR report 933 | 934 | ################################################################## Cache Sizes ################################################################## 935 | if [ "$AWR_SECTION" = "CacheSizes" ]; then 936 | # Routine for handling the Cache Sizes section of the report - only called with 12c format reports 937 | # Examine two words 938 | case ${AWRLINE[@]:0:2} in 939 | "Buffer Cache:") 940 | # Found Cache Sizes section containing database block size 941 | # The call to tr is necessary to remove the trailing return character 942 | DB_BLOCK_SIZE=$(echo ${AWRLINE[${#AWRLINE[@]}-1]} | tr -d '\r') 943 | echodbg "DB_BLOCK_SIZE = ${ENDCHAR}$DB_BLOCK_SIZE${ENDCHAR}" 944 | continue 945 | ;; 946 | "Shared Pool"*) 947 | # End of Cache Sizes section 948 | echovrb "End of Cache Sizes section found at line $ROWCNT" 949 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 950 | AWR_SECTION="SearchingForNextSection" 951 | # Switch Internal Field Seperator to only recognise newlines as delimiters 952 | set_ifs_to_line_delimited 953 | ;; 954 | *) 955 | # Catch all other lines and ignore 956 | continue 957 | ;; 958 | esac 959 | fi 960 | 961 | ################################################################## Time Model Statistics ################################################################## 962 | if [ "$AWR_SECTION" = "TimeModelStatistics" ]; then 963 | # Routine for handling the Time Model Statistics section of the report (only called for reports in 10g format) 964 | # Examine first two words 965 | case ${AWRLINE[@]:0:2} in 966 | "DB CPU") 967 | # Remember to strip out carriage returns and commas 968 | AWR_DB_CPU=$(echo "${AWRLINE[2]}" | tr -d '\r,') 969 | AWR_DB_CPU_PCT_DBTIME=$(echo "${AWRLINE[3]}" | tr -d '\r,') 970 | echodbg "AWR_DB_CPU = ${ENDCHAR}${AWR_DB_CPU}${ENDCHAR}" 971 | echodbg "AWR_DB_CPU_PCT_DBTIME = ${ENDCHAR}${AWR_DB_CPU_PCT_DBTIME}${ENDCHAR}" 972 | ;; 973 | *) 974 | # Ignore other lines 975 | continue 976 | esac 977 | continue 978 | fi 979 | 980 | ################################################################## Operating System Stats ################################################################## 981 | if [ "$AWR_SECTION" = "OperatingSystemStats" ]; then 982 | # Routine for handling the Operating System Stats section of the report 983 | # Examine first word 984 | case ${AWRLINE[@]:0:1} in 985 | "BUSY_TIME") 986 | # Remember to strip out carriage returns and commas 987 | OS_BUSY_TIME=$(echo "${AWRLINE[1]}" | tr -d '\r,') 988 | echodbg "OS_BUSY_TIME = ${ENDCHAR}${OS_BUSY_TIME}${ENDCHAR}" 989 | ;; 990 | "IDLE_TIME") 991 | # Remember to strip out carriage returns and commas 992 | OS_IDLE_TIME=$(echo "${AWRLINE[1]}" | tr -d '\r,') 993 | echodbg "OS_IDLE_TIME = ${ENDCHAR}${OS_IDLE_TIME}${ENDCHAR}" 994 | ;; 995 | "IOWAIT_TIME") 996 | # Remember to strip out carriage returns and commas 997 | OS_IOWAIT_TIME=$(echo "${AWRLINE[1]}" | tr -d '\r,') 998 | echodbg "OS_IOWAIT_TIME = ${ENDCHAR}${OS_IOWAIT_TIME}${ENDCHAR}" 999 | ;; 1000 | "SYS_TIME") 1001 | # Remember to strip out carriage returns and commas 1002 | OS_SYS_TIME=$(echo "${AWRLINE[1]}" | tr -d '\r,') 1003 | echodbg "OS_SYS_TIME = ${ENDCHAR}${OS_SYS_TIME}${ENDCHAR}" 1004 | ;; 1005 | "USER_TIME") 1006 | # Remember to strip out carriage returns and commas 1007 | OS_USER_TIME=$(echo "${AWRLINE[1]}" | tr -d '\r,') 1008 | echodbg "OS_USER_TIME = ${ENDCHAR}${OS_USER_TIME}${ENDCHAR}" 1009 | ;; 1010 | "OS_CPU_WAIT_TIME") 1011 | # Remember to strip out carriage returns and commas 1012 | OS_CPU_WAIT_TIME=$(echo "${AWRLINE[1]}" | tr -d '\r,') 1013 | echodbg "OS_CPU_WAIT_TIME = ${ENDCHAR}${OS_CPU_WAIT_TIME}${ENDCHAR}" 1014 | ;; 1015 | "RSRC_MGR_CPU_WAIT_TIME") 1016 | # Remember to strip out carriage returns and commas 1017 | OS_RSRC_MGR_WAIT_TIME=$(echo "${AWRLINE[1]}" | tr -d '\r,') 1018 | echodbg "OS_RSRC_MGR_WAIT_TIME = ${ENDCHAR}${OS_RSRC_MGR_WAIT_TIME}${ENDCHAR}" 1019 | ;; 1020 | "PHYSICAL_MEMORY_BYTES") 1021 | # Reports in 10g format to not show server memory in header section 1022 | if [ "$AWR_FORMAT" = "10" ]; then 1023 | # Convert from bytes to GB remembering to strip out carriage returns and commas 1024 | echodbg "Calling BC: DB_HOST_MEM=echo \"scale=3; $(echo ${AWRLINE[1]} | tr -d '\r,') / 1073741824\" | bc -l" 1025 | DB_HOST_MEM=`echo "scale=3; $(echo ${AWRLINE[1]} | tr -d '\r,') / 1073741824" | bc -l` 1026 | echodbg "DB_HOST_MEM = ${ENDCHAR}${DB_HOST_MEM}${ENDCHAR}" 1027 | fi 1028 | ;; 1029 | "NUM_CPUS") 1030 | # Remember to strip out carriage returns and commas 1031 | DB_NUM_CPUS=$(echo "${AWRLINE[1]}" | tr -d '\r,') 1032 | echodbg "DB_NUM_CPUS = ${ENDCHAR}${DB_NUM_CPUS}${ENDCHAR}" 1033 | ;; 1034 | *) 1035 | # Ignore other lines 1036 | continue 1037 | esac 1038 | continue 1039 | fi 1040 | 1041 | ################################################################## Foreground Wait Class ################################################################## 1042 | if [ "$AWR_SECTION" = "ForegroundWaitClass" ]; then 1043 | # Routine for handling the Foreground Wait Class section of the report 1044 | # For 10g AWR format this includes a tracker for totalling wait time in order to calculate DB CPU 1045 | case ${AWRLINE[0]:0:20} in 1046 | "Wait Class"*) 1047 | # Still in the header so ignore and carry on to the next line 1048 | echodbg "Still in section header - ignore" 1049 | continue 1050 | ;; 1051 | "--------"*) 1052 | # The header row - call process_header_row function to find widths of columns 1053 | process_header_row "${AWRLINE[0]}" 1054 | if [ "$PROCESS_HEADER_ROW" != "SUCCESS" ]; then 1055 | echovrb "Unable to determine width of rows in Foreground Wait Class section" 1056 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 1057 | AWR_SECTION="SearchingForNextSection" 1058 | # Switch Internal Field Seperator to only recognise newlines as delimiters 1059 | set_ifs_to_line_delimited 1060 | # Give up trying to process this section 1061 | let AWRSECTION_SKIP++ 1062 | fi 1063 | continue 1064 | ;; 1065 | "DB CPU"*) 1066 | # This string will only be found in 11g and above AWR reports 1067 | # The variables AWRCOLn are set in the process_header_row function call earlier in the handler 1068 | AWR_DB_CPU=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1069 | AWR_DB_CPU_PCT_DBTIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL6}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1070 | echovrb "Processing Foreground Wait Class DB CPU" 1071 | echodbg "AWR_DB_CPU = ${ENDCHAR}${AWR_DB_CPU}${ENDCHAR}" 1072 | echodbg "AWR_DB_CPU_PCT_DBTIME = ${ENDCHAR}${AWR_DB_CPU_PCT_DBTIME}${ENDCHAR}" 1073 | continue 1074 | ;; 1075 | "Administrative"*) 1076 | WAIT_CLASS_NAME="ADMIN" 1077 | echovrb "Processing Foreground Wait Class Administrative" 1078 | ;; 1079 | "Application"*) 1080 | WAIT_CLASS_NAME="APPLN" 1081 | echovrb "Processing Foreground Wait Class Application" 1082 | ;; 1083 | "Cluster"*) 1084 | WAIT_CLASS_NAME="CLSTR" 1085 | echovrb "Processing Foreground Wait Class Cluster" 1086 | ;; 1087 | "Commit"*) 1088 | WAIT_CLASS_NAME="COMMT" 1089 | echovrb "Processing Foreground Wait Class Commit" 1090 | ;; 1091 | "Concurrency"*) 1092 | WAIT_CLASS_NAME="CNCUR" 1093 | echovrb "Processing Foreground Wait Class Concurrency" 1094 | ;; 1095 | "Configuration"*) 1096 | WAIT_CLASS_NAME="CONFG" 1097 | echovrb "Processing Foreground Wait Class Configuration" 1098 | ;; 1099 | "Network"*) 1100 | WAIT_CLASS_NAME="NETWK" 1101 | echovrb "Processing Foreground Wait Class Network" 1102 | ;; 1103 | "Other"*) 1104 | WAIT_CLASS_NAME="OTHER" 1105 | echovrb "Processing Foreground Wait Class Other" 1106 | ;; 1107 | "Scheduler"*) 1108 | WAIT_CLASS_NAME="SCHED" 1109 | echovrb "Processing Foreground Wait Class Scheduler" 1110 | ;; 1111 | "User I/O"*) 1112 | WAIT_CLASS_NAME="USRIO" 1113 | echovrb "Processing Foreground Wait Class User I/O" 1114 | ;; 1115 | "System I/O"*) 1116 | WAIT_CLASS_NAME="SYSIO" 1117 | echovrb "Processing Foreground Wait Class System I/O" 1118 | ;; 1119 | *) 1120 | # One of the other wait classes that we do not explicitely capture 1121 | echovrb "Ignoring wait class: ${AWRLINE[0]:0:20}" 1122 | # If this is 10g add to the running total for calculating DB Time 1123 | if [ "$AWR_FORMAT" = '10' ]; then 1124 | # Attempt to extract value for total wait time 1125 | # The variables AWRCOLn are set in the process_header_row function call earlier in the handler 1126 | TOTAL_WAIT_TIME_TMP=$(echo '${AWRLINE[0]}'| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1127 | echodbg "TOTAL_WAIT_TIME_TMP = ${ENDCHAR}${TOTAL_WAIT_TIME_TMP}${ENDCHAR}" 1128 | # First check that the value we extract is actually a number, otherwise things will go bad when we inject it into the calculation below 1129 | if [ -n "$TOTAL_WAIT_TIME_TMP" ]; then 1130 | if [[ "$TOTAL_WAIT_TIME_TMP" != *[!0-9,]* ]]; then 1131 | echodbg "Calling BC: TOTAL_WAIT_TIME=echo 'scale=3; $TOTAL_WAIT_TIME + $TOTAL_WAIT_TIME_TMP' | bc -l" 1132 | TOTAL_WAIT_TIME=`echo "scale=3; $TOTAL_WAIT_TIME + $TOTAL_WAIT_TIME_TMP" | bc -l` 1133 | echodbg "TOTAL_WAIT_TIME = ${ENDCHAR}${TOTAL_WAIT_TIME}${ENDCHAR}" 1134 | else 1135 | # Value extracted was non-blank but non-numeric 1136 | echodbg "Unable to determine TOTAL_WAIT_TIME from non-numeric string: $TOTAL_WAIT_TIME_TMP" 1137 | fi 1138 | else 1139 | # Value extracted was blank 1140 | echodbg "Unable to determine TOTAL_WAIT_TIME from empty variable TOTAL_WAIT_TIME_TMP" 1141 | fi 1142 | unset TOTAL_WAIT_TIME_TMP 1143 | fi 1144 | continue 1145 | ;; 1146 | esac 1147 | 1148 | # Get the values for number of waits and wait time, then calculate average wait time 1149 | # The format of this section is slightly different between releases 10 and 11 1150 | # For 10g we keep a running total to calculate the percentage of DB Time, for 11g we just read it from the report 1151 | # The 12c format matches the 11g format for once, so we reuse the same code 1152 | # The variables AWRCOLn are set in the process_header_row function call earlier in the handler 1153 | WAIT_CLASS_NUM_WAITS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL2}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1154 | WAIT_CLASS_WAIT_TIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1155 | if [ "$AWR_FORMAT" = '10' ]; then 1156 | if [ -n "$WAIT_CLASS_WAIT_TIME" ]; then 1157 | echodbg "Calling BC: TOTAL_WAIT_TIME=echo 'scale=3; $TOTAL_WAIT_TIME + $WAIT_CLASS_WAIT_TIME' | bc -l" 1158 | TOTAL_WAIT_TIME=`echo "scale=3; $TOTAL_WAIT_TIME + $WAIT_CLASS_WAIT_TIME" | bc -l` 1159 | echodbg "TOTAL_WAIT_TIME = ${ENDCHAR}${TOTAL_WAIT_TIME}${ENDCHAR}" 1160 | fi 1161 | unset WAIT_CLASS_PCT_DBTIME 1162 | elif [ "$AWR_FORMAT" = '11' ] || [ "$AWR_FORMAT" = '12' ]; then 1163 | WAIT_CLASS_PCT_DBTIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL6}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1164 | else 1165 | # Set WAIT_CLASS_WAIT_TIME to zero to avoid breaking the call to BC below 1166 | WAIT_CLASS_WAIT_TIME=0 1167 | fi 1168 | # Calculate average wait - but first check that the number of waits is greater than zero 1169 | if [ -n "$WAIT_CLASS_NUM_WAITS" ]; then 1170 | if [ "$WAIT_CLASS_NUM_WAITS" != "0" ]; then 1171 | # See comments in header section for explanation of the way bc is used in calculating the average values below 1172 | echodbg "Calling BC: WAIT_CLASS_AVEWAIT=echo 'scale=3; (\$(echo 'scale=7; ($WAIT_CLASS_WAIT_TIME / $WAIT_CLASS_NUM_WAITS) * 1000' | bc -l)+0.0005)/1' | bc -l" 1173 | WAIT_CLASS_AVEWAIT=`echo "scale=3; ($(echo "scale=7; ($WAIT_CLASS_WAIT_TIME / $WAIT_CLASS_NUM_WAITS) * 1000" | bc -l)+0.0005)/1" | bc -l` 1174 | else 1175 | WAIT_CLASS_AVEWAIT=0 1176 | fi 1177 | else 1178 | unset WAIT_CLASS_AVEWAIT 1179 | fi 1180 | 1181 | echodbg "Foreground Wait Class $WAIT_CLASS_NAME: Waits=$WAIT_CLASS_NUM_WAITS, Time=$WAIT_CLASS_WAIT_TIME, PctDBTime=$WAIT_CLASS_PCT_DBTIME, Ave=$WAIT_CLASS_AVEWAIT" 1182 | 1183 | # Now place discovered values into the correct array of variables based on the WAIT_CLASS_NAME 1184 | eval WCLASS_${WAIT_CLASS_NAME}_NUM_WAITS='$WAIT_CLASS_NUM_WAITS' 1185 | eval WCLASS_${WAIT_CLASS_NAME}_WAIT_TIME='$WAIT_CLASS_WAIT_TIME' 1186 | [[ -n "$WAIT_CLASS_AVEWAIT" ]] && eval WCLASS_${WAIT_CLASS_NAME}_AVEWAIT='$WAIT_CLASS_AVEWAIT' 1187 | [[ -n "$WAIT_CLASS_PCT_DBTIME" ]] && eval WCLASS_${WAIT_CLASS_NAME}_PCT_DBTIME='$WAIT_CLASS_PCT_DBTIME' 1188 | 1189 | fi # End of handler routine for Foreground Wait Class section of AWR report 1190 | 1191 | ################################################################## Foreground Wait Events ################################################################## 1192 | if [ "$AWR_SECTION" = "ForegroundWaitEvents" ]; then 1193 | # Routine for handling the Foreground Wait Events section of the report 1194 | # The format of this section is slightly different between releases 10 and 11 1195 | 1196 | if [ "$FOUND_FG_WAIT_EVENTS" = "$AWR_NOTFOUND" ]; then 1197 | # We have just begun processing the Foreground Wait Events section so first we need to discover the header row (a set of dashes showing the column headings) 1198 | if [ "${AWRLINE[0]:0:6}" = "------" ]; then 1199 | echodbg "Searching for header row... found" 1200 | FOUND_FG_WAIT_EVENTS=$AWR_FOUND 1201 | process_header_row "${AWRLINE[0]}" 1202 | if [ "$PROCESS_HEADER_ROW" != "SUCCESS" ]; then 1203 | echovrb "Unable to determine width of rows in Foreground Wait Events section" 1204 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 1205 | AWR_SECTION="SearchingForNextSection" 1206 | # Switch Internal Field Seperator to only recognise newlines as delimiters 1207 | set_ifs_to_line_delimited 1208 | # Give up trying to process this section 1209 | if [ "$AWR_FORMAT" = "12" ]; then 1210 | AWRLINE_SKIP=10 1211 | else 1212 | AWRLINE_SKIP=5 1213 | fi 1214 | fi 1215 | else 1216 | let BAILOUT_COUNTER++ 1217 | if [ "$BAILOUT_COUNTER" -eq "$BAILOUT_LIMIT" ]; then 1218 | echodbg "Failed to find header row (BAILOUT_COUNTER hit threshold = $BAILOUT_COUNTER)" 1219 | echovrb "Unable to determine width of rows in Foreground Wait Events section" 1220 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 1221 | AWR_SECTION="SearchingForNextSection" 1222 | # Switch Internal Field Seperator to only recognise newlines as delimiters 1223 | set_ifs_to_line_delimited 1224 | # Give up trying to process this section 1225 | if [ "$AWR_FORMAT" = "12" ]; then 1226 | AWRLINE_SKIP=10 1227 | else 1228 | AWRLINE_SKIP=5 1229 | fi 1230 | else 1231 | echodbg "Searching for header row... not found (BAILOUT_COUNTER = $BAILOUT_COUNTER)" 1232 | fi 1233 | fi 1234 | continue 1235 | fi 1236 | 1237 | # Start processing the section 1238 | case ${AWRLINE[0]:0:26} in 1239 | "cell multiblock physical r") 1240 | [[ "$EXADATA_FLAG" = "N" ]] && echovrb "Found evidence of Exadata system" 1241 | EXADATA_FLAG="Y" 1242 | ;; 1243 | "cell single block physical") 1244 | [[ "$EXADATA_FLAG" = "N" ]] && echovrb "Found evidence of Exadata system" 1245 | EXADATA_FLAG="Y" 1246 | ;; 1247 | "db file sequential read"*) 1248 | WAIT_NAME="DFSR" 1249 | ;; 1250 | "db file scattered read"*) 1251 | WAIT_NAME="DFXR" 1252 | ;; 1253 | "direct path read"*) 1254 | # This could be either direct path read or direct path read temp - so check and act accordingly 1255 | if [ "${AWRLINE[0]:0:21}" = "direct path read temp" ]; then 1256 | WAIT_NAME="DPRT" 1257 | else 1258 | WAIT_NAME="DPRD" 1259 | fi 1260 | ;; 1261 | "direct path write"*) 1262 | # This could be either direct path write or direct path write temp - so check and act accordingly 1263 | if [ "${AWRLINE[0]:0:22}" = "direct path write temp" ]; then 1264 | WAIT_NAME="DPWT" 1265 | else 1266 | WAIT_NAME="DPWR" 1267 | fi 1268 | ;; 1269 | "log file sync"*) 1270 | WAIT_NAME="LFSY" 1271 | ;; 1272 | *) 1273 | # Catch all other lines and set WAIT_NAME to be blank 1274 | WAIT_NAME="" 1275 | continue 1276 | ;; 1277 | esac 1278 | 1279 | # Now check WAIT_TIME and if set begin handling the line 1280 | # The variables AWRCOLn are set in the process_header_row function call earlier in the handler 1281 | if [ -n "$WAIT_NAME" ]; then 1282 | if [ "$AWR_FORMAT" = "10" ]; then 1283 | WAIT_NUM_WAITS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL2}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1284 | WAIT_TIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1285 | # No %DB Time column present in 10g reports - calculate value manually then round to one decimal place 1286 | if [ -n "$AWR_DB_TIME" ] && [ "$AWR_DB_TIME" != "0" ]; then 1287 | # See comments in header section for explanation of the way bc is used in calculating the average on the next line 1288 | echodbg "Calling BC: WAIT_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1289 | WAIT_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1290 | else 1291 | WAIT_PCT_DBTIME="" 1292 | fi 1293 | elif [ "$AWR_FORMAT" = "11" ] || [ "$AWR_FORMAT" = "12" ]; then 1294 | WAIT_NUM_WAITS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL2}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1295 | WAIT_TIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1296 | WAIT_PCT_DBTIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL7}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1297 | else 1298 | # Set WAIT_TIME to zero to avoid breaking call to BC below 1299 | WAIT_TIME=0 1300 | fi 1301 | # Calculate the average wait time in milliseconds with three decimal places 1302 | if [ -n "$WAIT_NUM_WAITS" ] && [ "$WAIT_NUM_WAITS" != "0" ]; then 1303 | # See comments in header section for explanation of the way bc is used in calculating the average on the next line 1304 | echodbg "Calling BC: WAIT_AVERAGE=echo 'scale=3; (\$(echo 'scale=7; ($WAIT_TIME / $WAIT_NUM_WAITS) * 1000' | bc -l)+0.0005)/1' | bc -l" 1305 | WAIT_AVERAGE=`echo "scale=3; ($(echo "scale=7; ($WAIT_TIME / $WAIT_NUM_WAITS) * 1000" | bc -l)+0.0005)/1" | bc -l` 1306 | else 1307 | WAIT_AVERAGE="" 1308 | fi 1309 | 1310 | echodbg "Foreground Wait Events $WAIT_NAME: Waits=$WAIT_NUM_WAITS, Time=$WAIT_TIME, PctDBTime=$WAIT_PCT_DBTIME, Ave=$WAIT_AVERAGE" 1311 | 1312 | # Set variable based on name of wait 1313 | eval WAIT_${WAIT_NAME}_WAITS='$WAIT_NUM_WAITS' 1314 | eval WAIT_${WAIT_NAME}_TIME='$WAIT_TIME' 1315 | eval WAIT_${WAIT_NAME}_AVERAGE='$WAIT_AVERAGE' 1316 | eval WAIT_${WAIT_NAME}_PCT_DBTIME='$WAIT_PCT_DBTIME' 1317 | fi 1318 | continue 1319 | fi # End of handler routine for Foreground Wait Events section of AWR report 1320 | 1321 | ################################################################## Background Wait Events ################################################################## 1322 | if [ "$AWR_SECTION" = "BackgroundWaitEvents" ]; then 1323 | # Routine for handling the Background Wait Events section of the report 1324 | # The format of this section is slightly different between releases 10 and 11 1325 | 1326 | if [ "$FOUND_BG_WAIT_EVENTS" = "$AWR_NOTFOUND" ]; then 1327 | # We have just begun processing the Background Wait Events section so first we need to discover the header row (a set of dashes showing the column headings) 1328 | if [ "${AWRLINE[0]:0:6}" = "------" ]; then 1329 | echodbg "Searching for header row... found" 1330 | FOUND_BG_WAIT_EVENTS=$AWR_FOUND 1331 | process_header_row "${AWRLINE[0]}" 1332 | if [ "$PROCESS_HEADER_ROW" != "SUCCESS" ]; then 1333 | echovrb "Unable to determine width of rows in Background Wait Events section" 1334 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 1335 | AWR_SECTION="SearchingForNextSection" 1336 | # Switch Internal Field Seperator to only recognise newlines as delimiters 1337 | set_ifs_to_line_delimited 1338 | # Give up trying to process this section 1339 | if [ "$AWR_FORMAT" = "12" ]; then 1340 | AWRLINE_SKIP=10 1341 | else 1342 | AWRLINE_SKIP=5 1343 | fi 1344 | fi 1345 | else 1346 | let BAILOUT_COUNTER++ 1347 | if [ "$BAILOUT_COUNTER" -eq "$BAILOUT_LIMIT" ]; then 1348 | echodbg "Failed to find header row (BAILOUT_COUNTER hit threshold = $BAILOUT_COUNTER)" 1349 | echovrb "Unable to determine width of rows in Background Wait Events section" 1350 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 1351 | AWR_SECTION="SearchingForNextSection" 1352 | # Switch Internal Field Seperator to only recognise newlines as delimiters 1353 | set_ifs_to_line_delimited 1354 | # Give up trying to process this section 1355 | if [ "$AWR_FORMAT" = "12" ]; then 1356 | AWRLINE_SKIP=10 1357 | else 1358 | AWRLINE_SKIP=5 1359 | fi 1360 | else 1361 | echodbg "Searching for header row... not found (BAILOUT_COUNTER = $BAILOUT_COUNTER)" 1362 | fi 1363 | fi 1364 | continue 1365 | fi 1366 | 1367 | # Start processing the section 1368 | case ${AWRLINE[0]:0:26} in 1369 | "db file parallel write"*) 1370 | WAIT_NAME="DFPW" 1371 | ;; 1372 | "log file parallel write"*) 1373 | WAIT_NAME="LFPW" 1374 | ;; 1375 | "log file sequential read"*) 1376 | WAIT_NAME="LFSR" 1377 | ;; 1378 | "log file parallel write"*) 1379 | WAIT_NAME="LFPW" 1380 | ;; 1381 | "LNS wait on SENDREQ"*) 1382 | echovrb "Found evidence of Data Guard in use on this system" 1383 | DATA_GUARD_FLAG="Y" 1384 | ;; 1385 | *) 1386 | # Catch all other lines and set WAIT_NAME to be blank 1387 | WAIT_NAME="" 1388 | ;; 1389 | esac 1390 | 1391 | # Now check WAIT_TIME and if set begin handling the line 1392 | # The variables AWRCOLn are set in the process_header_row function call earlier in the handler 1393 | if [ -n "$WAIT_NAME" ]; then 1394 | if [ "$AWR_FORMAT" = "10" ]; then 1395 | WAIT_NUM_WAITS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL2}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1396 | WAIT_TIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1397 | # No %BG Time column present in 10g reports - cannot calculate manually so leave blank 1398 | WAIT_PCT_DBTIME="" 1399 | elif [ "$AWR_FORMAT" = "11" ] || [ "$AWR_FORMAT" = "12" ]; then 1400 | WAIT_NUM_WAITS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL2}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1401 | WAIT_TIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1402 | WAIT_PCT_DBTIME=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL7}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1403 | else 1404 | # Set WAIT_TIME to zero to avoid breaking call to BC below 1405 | WAIT_TIME=0 1406 | fi 1407 | 1408 | # Calculate the average wait time in milliseconds with three decimal places 1409 | if [ -n "$WAIT_NUM_WAITS" ] && [ "$WAIT_NUM_WAITS" != "0" ]; then 1410 | # See comments in header section for explanation of the way bc is used in calculating the average on the next line 1411 | echodbg "Calling BC: WAIT_AVERAGE=echo 'scale=3; (\$(echo 'scale=7; ($WAIT_TIME / $WAIT_NUM_WAITS) * 1000' | bc -l)+0.0005)/1' | bc -l" 1412 | WAIT_AVERAGE=`echo "scale=3; ($(echo "scale=7; ($WAIT_TIME / $WAIT_NUM_WAITS) * 1000" | bc -l)+0.0005)/1" | bc -l` 1413 | else 1414 | WAIT_AVERAGE="" 1415 | fi 1416 | 1417 | echodbg "Background Wait Events $WAIT_NAME: Waits=$WAIT_NUM_WAITS, Time=$WAIT_TIME, PctDBTime=$WAIT_PCT_DBTIME, Ave=$WAIT_AVERAGE" 1418 | 1419 | # Set variable based on name of wait 1420 | eval WAIT_${WAIT_NAME}_WAITS='$WAIT_NUM_WAITS' 1421 | eval WAIT_${WAIT_NAME}_TIME='$WAIT_TIME' 1422 | eval WAIT_${WAIT_NAME}_AVERAGE='$WAIT_AVERAGE' 1423 | eval WAIT_${WAIT_NAME}_PCT_DBTIME='$WAIT_PCT_DBTIME' 1424 | fi 1425 | continue 1426 | fi # End of handler routine for Background Wait Events section of AWR report 1427 | 1428 | ################################################################## Wait Event Histogram ################################################################## 1429 | if [ "$AWR_SECTION" = "WaitEventHistogram" ]; then 1430 | # Routine for handling the Background Wait Events section of the report 1431 | # The format of this section is slightly different between releases 10 and 11 1432 | 1433 | if [ "$FOUND_HG_WAIT_EVENTS" = "$AWR_NOTFOUND" ]; then 1434 | # We have just begun processing the Wait Event Histogram section so first we need to discover the header row (a set of dashes showing the column headings) 1435 | if [ "${AWRLINE[0]:0:6}" = "------" ]; then 1436 | echodbg "Searching for header row... found" 1437 | FOUND_HG_WAIT_EVENTS=$AWR_FOUND 1438 | process_header_row "${AWRLINE[0]}" 1439 | if [ "$PROCESS_HEADER_ROW" != "SUCCESS" ]; then 1440 | echovrb "Unable to determine width of rows in Wait Event Histogram section" 1441 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 1442 | AWR_SECTION="SearchingForNextSection" 1443 | # Switch Internal Field Seperator to only recognise newlines as delimiters 1444 | set_ifs_to_line_delimited 1445 | fi 1446 | else 1447 | let BAILOUT_COUNTER++ 1448 | if [ "$BAILOUT_COUNTER" -eq "$BAILOUT_LIMIT" ]; then 1449 | echodbg "Failed to find header row (BAILOUT_COUNTER hit threshold = $BAILOUT_COUNTER)" 1450 | echovrb "Unable to determine width of rows in Wait Event Histogram section" 1451 | echodbg "State change AWR_SECTION: $AWR_SECTION -> SearchingForNextSection" 1452 | AWR_SECTION="SearchingForNextSection" 1453 | # Switch Internal Field Seperator to only recognise newlines as delimiters 1454 | set_ifs_to_line_delimited 1455 | # Give up trying to process this section 1456 | echodbg "Searching for header row... not found (BAILOUT_COUNTER = $BAILOUT_COUNTER)" 1457 | fi 1458 | fi 1459 | continue 1460 | fi 1461 | 1462 | # Start processing the section 1463 | case ${AWRLINE[0]:0:26} in 1464 | "db file sequential read"*) 1465 | WAIT_NAME="DFSR" 1466 | ;; 1467 | "log file parallel write"*) 1468 | WAIT_NAME="LFPW" 1469 | ;; 1470 | *) 1471 | # Catch all other lines and set WAIT_NAME to be blank 1472 | WAIT_NAME="" 1473 | ;; 1474 | esac 1475 | 1476 | # Now check WAIT_TIME and if set begin handling the line 1477 | # The variables AWRCOLn are set in the process_header_row function call earlier in the handler 1478 | if [ -n "$WAIT_NAME" ]; then 1479 | HGRM_1MS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL3}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1480 | HGRM_2MS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL4}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1481 | HGRM_4MS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL5}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1482 | HGRM_8MS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL6}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1483 | HGRM_16MS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL7}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1484 | HGRM_32MS=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL8}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1485 | HGRM_LT1S=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL9}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1486 | HGRM_GT1S=$(echo "${AWRLINE[0]}"| cut -c${AWRCOL10}|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1487 | 1488 | echodbg "Wait Event Histogram $WAIT_NAME: <1ms=$HGRM_1MS, <2ms=$HGRM_2MS, <4ms=$HGRM_4MS, <8ms=$HGRM_8MS, <16ms=$HGRM_16MS, <32ms=$HGRM_32MS, <1s=$HGRM_LT1S, >1s=$HGRM_GT1S" 1489 | 1490 | # Set variable based on name of wait 1491 | eval HGRM_${WAIT_NAME}_1MS='$HGRM_1MS' 1492 | eval HGRM_${WAIT_NAME}_2MS='$HGRM_2MS' 1493 | eval HGRM_${WAIT_NAME}_4MS='$HGRM_4MS' 1494 | eval HGRM_${WAIT_NAME}_8MS='$HGRM_8MS' 1495 | eval HGRM_${WAIT_NAME}_16MS='$HGRM_16MS' 1496 | eval HGRM_${WAIT_NAME}_32MS='$HGRM_32MS' 1497 | eval HGRM_${WAIT_NAME}_LT1S='$HGRM_LT1S' 1498 | eval HGRM_${WAIT_NAME}_GT1S='$HGRM_GT1S' 1499 | fi 1500 | continue 1501 | fi # End of handler routine for Wait Event Histogram section of AWR report 1502 | 1503 | ################################################################## Instance Activity Stats ################################################################## 1504 | if [ "$AWR_SECTION" = "InstanceActivityStats" ]; then 1505 | # Routine for handling the Instance Activity Stats section of the report 1506 | case ${AWRLINE[0]:0:32} in 1507 | "physical read total IO requests"*) 1508 | READ_IOPS=$(echo "${AWRLINE[0]}"| cut -c52-66|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1509 | echodbg "READ_IOPS = ${ENDCHAR}${READ_IOPS}${ENDCHAR}" 1510 | ;; 1511 | "physical read total bytes "*) 1512 | # Because this number is often very large Oracle may print it in scientific notation so we have to convert this if neccessary 1513 | READ_THROUGHPUT=$(echo "${AWRLINE[0]}"| cut -c52-66|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g'| sed -e 's/E+/\*10\^/') 1514 | # Convert to MB/sec 1515 | if [ -n "$READ_THROUGHPUT" ]; then 1516 | echodbg "Calling BC: READ_THROUGHPUT=echo 'scale=2; (\$(echo 'scale=6; $READ_THROUGHPUT / 1048576' | bc -l)+0.005)/1' | bc -l" 1517 | READ_THROUGHPUT=`echo "scale=2; ($(echo "scale=6; $READ_THROUGHPUT / 1048576" | bc -l)+0.005)/1" | bc -l` 1518 | echodbg "READ_THROUGHPUT = ${ENDCHAR}${READ_THROUGHPUT}${ENDCHAR}" 1519 | else 1520 | echovrb "WARNING: Unable to calculate value for READ_THROUGHPUT: $READ_THROUGHPUT" 1521 | READ_THROUGHPUT="" 1522 | fi 1523 | ;; 1524 | "physical write total IO requests") 1525 | ALL_WRITE_IOPS=$(echo "${AWRLINE[0]}"| cut -c52-66|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1526 | echodbg "ALL_WRITE_IOPS = ${ENDCHAR}${ALL_WRITE_IOPS}${ENDCHAR}" 1527 | ;; 1528 | "physical write total bytes "*) 1529 | # Because this number is often very large Oracle may print it in scientific notation so we have to convert this if neccessary 1530 | ALL_WRITE_THROUGHPUT=$(echo "${AWRLINE[0]}"| cut -c52-66|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g'| sed -e 's/E+/\*10\^/') 1531 | # Convert to MB/sec 1532 | if [ -n "$ALL_WRITE_THROUGHPUT" ]; then 1533 | echodbg "Calling BC: ALL_WRITE_THROUGHPUT=echo 'scale=2; (\$(echo 'scale=6; $ALL_WRITE_THROUGHPUT / 1048576' | bc -l)+0.005)/1' | bc -l" 1534 | ALL_WRITE_THROUGHPUT=`echo "scale=2; ($(echo "scale=6; $ALL_WRITE_THROUGHPUT / 1048576" | bc -l)+0.005)/1" | bc -l` 1535 | echodbg "ALL_WRITE_THROUGHPUT = ${ENDCHAR}${ALL_WRITE_THROUGHPUT}${ENDCHAR}" 1536 | else 1537 | echovrb "WARNING: Unable to calculate value for ALL_WRITE_THROUGHPUT: $ALL_WRITE_THROUGHPUT" 1538 | ALL_WRITE_THROUGHPUT="" 1539 | fi 1540 | ;; 1541 | "redo writes"*) 1542 | REDO_WRITE_IOPS=$(echo "${AWRLINE[0]}"| cut -c52-66|sed -e 's/^[ \t]*//;s/[ \t]*$//;s/,//g') 1543 | echodbg "REDO_WRITE_IOPS = ${ENDCHAR}${REDO_WRITE_IOPS}${ENDCHAR}" 1544 | ;; 1545 | " ----------------------") 1546 | # End of Instance Activity Stats section of the report 1547 | echovrb "End of Instance Activity Stats section found at line $ROWCNT" 1548 | echovrb "No further sections to search for - jump to post-processing" 1549 | AWR_SECTION="EndOfReport" 1550 | # This is the last section so break out of the while loop to begin post processing 1551 | break 1552 | ;; 1553 | esac 1554 | continue 1555 | fi 1556 | 1557 | ################################################################## Thread Activity ################################################################## 1558 | if [ "$AWR_SECTION" = "ThreadActivity" ]; then 1559 | # Routine for handling the Instance Activity Stats - Thread Activity section of the report 1560 | # Examine two words 1561 | case ${AWRLINE[@]:0:2} in 1562 | "log switches") 1563 | # Read information on log switches - remove commas and any carriage return 1564 | AWR_LOG_SWITCHES_TOTAL=$(echo ${AWRLINE[3]} |sed -e 's/,//g') 1565 | AWR_LOG_SWITCHES_PERHOUR=$(echo ${AWRLINE[4]} |sed -e 's/,//g' | tr -d '\r') 1566 | echodbg "AWR_LOG_SWITCHES_TOTAL = ${ENDCHAR}${AWR_LOG_SWITCHES_TOTAL}${ENDCHAR}" 1567 | echodbg "AWR_LOG_SWITCHES_PERHOUR = ${ENDCHAR}${AWR_LOG_SWITCHES_PERHOUR}${ENDCHAR}" 1568 | echovrb "Finished scanning file at line $ROWCNT" 1569 | break 1570 | ;; 1571 | *) 1572 | # Catch all other lines and ignore 1573 | continue 1574 | ;; 1575 | esac 1576 | fi 1577 | 1578 | # End of the while read loop 1579 | done < $AWRFILE 1580 | # Finished reading AWR report on line by line basis 1581 | 1582 | ################################################################## Post Processing Section ################################################################## 1583 | # Start post processing section for files of known format 1584 | if [ "$AWR_FORMAT" != 'Unknown' ]; then 1585 | echovrb "Start post-processing section" 1586 | # Based on comparison of NUM_CPUS and Average Active Sessions, set BUSY flag to Y or N 1587 | if [ -n "$DB_NUM_CPUS" ] && [ -n "$AWR_AAS" ]; then 1588 | # Set BUSY flag if AAS higher than number of CPUs 1589 | echodbg "Calling BC: echo '$AWR_AAS > $DB_NUM_CPUS' | bc -l" 1590 | if [ $(echo "$AWR_AAS > $DB_NUM_CPUS" | bc -l) = 1 ]; then 1591 | AWR_BUSY_FLAG="Y" 1592 | else 1593 | AWR_BUSY_FLAG="N" 1594 | fi 1595 | fi 1596 | 1597 | # Calculate total and data write IOPS values 1598 | TOTAL_IOPS=0 1599 | DATA_WRITE_IOPS=0 1600 | if [ -n "$READ_IOPS" ]; then 1601 | echodbg "Calling BC: TOTAL_IOPS=echo 'scale=1; $TOTAL_IOPS + $READ_IOPS' | bc -l" 1602 | TOTAL_IOPS=`echo "scale=1; $TOTAL_IOPS + $READ_IOPS" | bc -l` 1603 | echodbg "TOTAL_IOPS = ${ENDCHAR}${TOTAL_IOPS}${ENDCHAR}" 1604 | fi 1605 | if [ -n "$ALL_WRITE_IOPS" ]; then 1606 | echodbg "Calling BC: TOTAL_IOPS=echo 'scale=1; $TOTAL_IOPS + $ALL_WRITE_IOPS' | bc -l" 1607 | TOTAL_IOPS=`echo "scale=1; $TOTAL_IOPS + $ALL_WRITE_IOPS" | bc -l` 1608 | echodbg "TOTAL_IOPS = ${ENDCHAR}${TOTAL_IOPS}${ENDCHAR}" 1609 | if [ -n "$REDO_WRITE_IOPS" ]; then 1610 | echodbg "Calling BC: ALL_WRITE_IOPS=echo 'scale=1; $ALL_WRITE_IOPS - $REDO_WRITE_IOPS' | bc -l" 1611 | DATA_WRITE_IOPS=`echo "scale=1; $ALL_WRITE_IOPS - $REDO_WRITE_IOPS" | bc -l` 1612 | echodbg "DATA_WRITE_IOPS = ${ENDCHAR}${DATA_WRITE_IOPS}${ENDCHAR}" 1613 | fi 1614 | fi 1615 | [[ "$TOTAL_IOPS" = "0" ]] && unset TOTAL_IOPS 1616 | [[ "$READ_IOPS" = "0" ]] && unset READ_IOPS 1617 | [[ "$ALL_WRITE_IOPS" = "0" ]] && unset ALL_WRITE_IOPS 1618 | [[ "$DATA_WRITE_IOPS" = "0" ]] && unset DATA_WRITE_IOPS 1619 | 1620 | # Calculate total and data write throughput values 1621 | TOTAL_THROUGHPUT=0 1622 | DATA_WRITE_THROUGHPUT=0 1623 | if [ -n "$READ_THROUGHPUT" ]; then 1624 | echodbg "Calling BC: TOTAL_THROUGHPUT=echo 'scale=1; $TOTAL_THROUGHPUT + $READ_THROUGHPUT' | bc -l" 1625 | TOTAL_THROUGHPUT=`echo "scale=1; $TOTAL_THROUGHPUT + $READ_THROUGHPUT" | bc -l` 1626 | echodbg "TOTAL_THROUGHPUT = ${ENDCHAR}${TOTAL_THROUGHPUT}${ENDCHAR}" 1627 | fi 1628 | if [ -n "$ALL_WRITE_THROUGHPUT" ]; then 1629 | echodbg "Calling BC: TOTAL_THROUGHPUT=echo 'scale=1; $TOTAL_THROUGHPUT + $ALL_WRITE_THROUGHPUT | bc -l" 1630 | TOTAL_THROUGHPUT=`echo "scale=1; $TOTAL_THROUGHPUT + $ALL_WRITE_THROUGHPUT" | bc -l` 1631 | echodbg "TOTAL_THROUGHPUT = ${ENDCHAR}${TOTAL_THROUGHPUT}${ENDCHAR}" 1632 | if [ -n "$REDO_WRITE_THROUGHPUT" ]; then 1633 | echodbg "Calling BC: ALL_WRITE_THROUGHPUT=echo 'scale=1; $ALL_WRITE_THROUGHPUT - $REDO_WRITE_THROUGHPUT' | bc -l" 1634 | DATA_WRITE_THROUGHPUT=`echo "scale=1; $ALL_WRITE_THROUGHPUT - $REDO_WRITE_THROUGHPUT" | bc -l` 1635 | echodbg "DATA_WRITE_THROUGHPUT = ${ENDCHAR}${DATA_WRITE_THROUGHPUT}${ENDCHAR}" 1636 | fi 1637 | fi 1638 | [[ "$TOTAL_THROUGHPUT" = "0" ]] && unset TOTAL_THROUGHPUT 1639 | [[ "$READ_THROUGHPUT" = "0" ]] && unset READ_THROUGHPUT 1640 | [[ "$ALL_WRITE_THROUGHPUT" = "0" ]] && unset ALL_WRITE_THROUGHPUT 1641 | [[ "$DATA_WRITE_THROUGHPUT" = "0" ]] && unset DATA_WRITE_THROUGHPUT 1642 | 1643 | # No %DB Time column present in 10g reports - calculate value for wait classes manually then round to one decimal place 1644 | if [ "$AWR_FORMAT" = '10' ] && [ "$FOUND_FG_WAIT_CLASS"="$AWR_FOUND" ]; then 1645 | echovrb "Calculating Wait Class data: note that %DBTime in 10g reports can total to >100%" 1646 | echovrb " - this is a known issue and is fixed in 11g" 1647 | # First check that we have a value for %DB Time otherwise skip the calculation section 1648 | if [ -z "$AWR_DB_TIME" ] || [ "$AWR_DB_TIME" = 0 ]; then 1649 | echovrb "WARNING: Unable to calculate Wait Class %DBTime values due to unknown value for DB Time: $AWR_DB_TIME" 1650 | continue 1651 | fi 1652 | # See comments in header section for explanation of the way bc is used in calculating the average on the following lines 1653 | if [ -n "$WCLASS_ADMIN_WAIT_TIME" ]; then 1654 | echodbg "Calling BC: WCLASS_ADMIN_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_ADMIN_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1655 | WCLASS_ADMIN_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_ADMIN_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1656 | echovrb "Calculated Administrative Wait Class %DBTime as $WCLASS_ADMIN_PCT_DBTIME %" 1657 | else 1658 | echovrb "No values found for Administrative Wait Class" 1659 | fi 1660 | if [ -n "$WCLASS_APPLN_WAIT_TIME" ]; then 1661 | echodbg "Calling BC: WCLASS_APPLN_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_APPLN_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1662 | WCLASS_APPLN_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_APPLN_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1663 | echovrb "Calculated Application Wait Class %DBTime as $WCLASS_APPLN_PCT_DBTIME %" 1664 | else 1665 | echovrb "No values found for Application Wait Class" 1666 | fi 1667 | if [ -n "$WCLASS_CLSTR_WAIT_TIME" ]; then 1668 | echodbg "Calling BC: WCLASS_CLSTR_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_CLSTR_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1669 | WCLASS_CLSTR_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_CLSTR_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1670 | echovrb "Calculated Cluster Wait Class %DBTime as $WCLASS_CLSTR_PCT_DBTIME %" 1671 | else 1672 | echovrb "No values found for Cluster Wait Class" 1673 | fi 1674 | if [ -n "$WCLASS_COMMT_WAIT_TIME" ]; then 1675 | echodbg "Calling BC: WCLASS_COMMT_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_COMMT_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1676 | WCLASS_COMMT_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_COMMT_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1677 | echovrb "Calculated Commit Wait Class %DBTime as $WCLASS_COMMT_PCT_DBTIME %" 1678 | else 1679 | echovrb "No values found for Commit Wait Class" 1680 | fi 1681 | if [ -n "$WCLASS_CNCUR_WAIT_TIME" ]; then 1682 | echodbg "Calling BC: WCLASS_CNCUR_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_CNCUR_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1683 | WCLASS_CNCUR_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_CNCUR_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1684 | echovrb "Calculated Concurrency Wait Class %DBTime as $WCLASS_CNCUR_PCT_DBTIME %" 1685 | else 1686 | echovrb "No values found for Concurrency Wait Class" 1687 | fi 1688 | if [ -n "$WCLASS_CONFG_WAIT_TIME" ]; then 1689 | echodbg "Calling BC: WCLASS_CONFG_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_CONFG_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1690 | WCLASS_CONFG_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_CONFG_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1691 | echovrb "Calculated Configuration Wait Class %DBTime as $WCLASS_CONFG_PCT_DBTIME %" 1692 | else 1693 | echovrb "No values found for Configuration Wait Class" 1694 | fi 1695 | if [ -n "$WCLASS_NETWK_WAIT_TIME" ]; then 1696 | echodbg "Calling BC: WCLASS_NETWK_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_NETWK_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1697 | WCLASS_NETWK_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_NETWK_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1698 | echovrb "Calculated Network Wait Class %DBTime as $WCLASS_NETWK_PCT_DBTIME %" 1699 | else 1700 | echovrb "No values found for Network Wait Class" 1701 | fi 1702 | if [ -n "$WCLASS_OTHER_WAIT_TIME" ]; then 1703 | echodbg "Calling BC: WCLASS_OTHER_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_OTHER_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1704 | WCLASS_OTHER_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_OTHER_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1705 | echovrb "Calculated Other Wait Class %DBTime as $WCLASS_OTHER_PCT_DBTIME %" 1706 | else 1707 | echovrb "No values found for Other Wait Class" 1708 | fi 1709 | if [ -n "$WCLASS_SCHED_WAIT_TIME" ]; then 1710 | echodbg "Calling BC: WCLASS_SCHED_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_SCHED_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1711 | WCLASS_SCHED_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_SCHED_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1712 | echovrb "Calculated Scheduler Wait Class %DBTime as $WCLASS_SCHED_PCT_DBTIME %" 1713 | else 1714 | echovrb "No values found for Scheduler Wait Class" 1715 | fi 1716 | if [ -n "$WCLASS_USRIO_WAIT_TIME" ]; then 1717 | echodbg "Calling BC: WCLASS_USRIO_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_USRIO_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1718 | WCLASS_USRIO_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_USRIO_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1719 | echovrb "Calculated User I/O %DBTime as $WCLASS_USRIO_PCT_DBTIME %" 1720 | else 1721 | echovrb "No values found for User I/O Wait Class" 1722 | fi 1723 | if [ -n "$WCLASS_SYSIO_WAIT_TIME" ]; then 1724 | echodbg "Calling BC: WCLASS_SYSIO_PCT_DBTIME=echo 'scale=1; (\$(echo 'scale=5; ($WCLASS_SYSIO_WAIT_TIME/($AWR_DB_TIME*60))*100' | bc -l)+0.05)/1' | bc -l" 1725 | WCLASS_SYSIO_PCT_DBTIME=`echo "scale=1; ($(echo "scale=5; ($WCLASS_SYSIO_WAIT_TIME/($AWR_DB_TIME*60))*100" | bc -l)+0.05)/1" | bc -l` 1726 | echovrb "Calculated System I/O %DBTime as $WCLASS_SYSIO_PCT_DBTIME %" 1727 | else 1728 | echovrb "No values found for System I/O Wait Class" 1729 | fi 1730 | fi 1731 | 1732 | # Print warnings if certain sections were not found 1733 | [[ "$FOUND_SYS_DETAILS" != "$AWR_FOUND" ]] && echoinf "Unable to find database system details" 1734 | if [ "$AWR_FORMAT" -ne "10" ]; then 1735 | [[ "$FOUND_HOST_DETAILS" != "$AWR_FOUND" ]] && echoinf "Unable to find host system details" 1736 | [[ -z "$AWR_AAS" ]] && echoinf "Unable to calculate Average Active Sessions" 1737 | [[ -z "$AWR_BUSY_FLAG" ]] && echoinf "Unable to determine value for BUSY flag" 1738 | fi 1739 | 1740 | # Raise error if any critical values are null 1741 | if [ -z "$PROFILE_DBNAME" ]; then 1742 | echoerr "Post-process complete: unable to determine Database name" 1743 | elif [ -z "$READ_IOPS" ]; then 1744 | echoerr "Post-process complete: unable to determine read IOPS values" 1745 | elif [ -z "$ALL_WRITE_IOPS" ]; then 1746 | echoerr "Post-process complete: unable to determine write IOPS values" 1747 | elif [ -z "$READ_THROUGHPUT" ]; then 1748 | echoerr "Post-process complete: unable to determine read throughput values" 1749 | elif [ -z "$ALL_WRITE_THROUGHPUT" ]; then 1750 | echoerr "Post-process complete: unable to determine write throughput values" 1751 | else 1752 | echovrb "Post-processing complete" 1753 | fi 1754 | fi 1755 | } 1756 | 1757 | # Function for printing the header row in the CSV file i.e. the descriptions of each column 1758 | print_header_row() { 1759 | # Write header row for CSV file 1760 | echocsv "Filename,Database Name,Instance Number,Instance Name,Database Version,Cluster,Hostname,Host OS,Num CPUs,Server Memory (GB),DB Block Size,Begin Snap,Begin Time,End Snap,End Time,Elapsed Time (mins),DB Time (mins),Average Active Sessions,Busy Flag,Logical Reads/sec,Block Changes/sec,Read IOPS,Write IOPS,Redo IOPS,All Write IOPS,Total IOPS,Read Throughput (MiB/sec),Write Throughput (MiB/sec),Redo Throughput (MiB/sec),All Write Throughput (MiB/sec),Total Throughput (MiB/sec),DB CPU Time (s),DB CPU %DBTime,Wait Class User I/O Waits,Wait Class User I/O Time (s),Wait Class User I/O Latency (ms),Wait Class User I/O %DBTime,User Calls/sec,Parses/sec,Hard Parses/sec,Logons/sec,Executes/sec,Transactions/sec,Buffer Hit Ratio (%),In-Memory Sort Ratio (%),Log Switches (Total),Log Switches (Per Hour),Top5 Event1 Name,Top5 Event1 Class,Top5 Event1 Waits,Top5 Event1 Time (s),Top5 Event1 Average Time (ms),Top5 Event1 %DBTime,Top5 Event2 Name,Top5 Event2 Class,Top5 Event2 Waits,Top5 Event2 Time (s),Top5 Event2 Average Time (ms),Top5 Event2 %DBTime,Top5 Event3 Name,Top5 Event3 Class,Top5 Event3 Waits,Top5 Event3 Time (s),Top5 Event3 Average Time (ms),Top5 Event3 %DBTime,Top5 Event4 Name,Top5 Event4 Class,Top5 Event4 Waits,Top5 Event4 Time (s),Top5 Event4 Average Time (ms),Top5 Event4 %DBTime,Top5 Event5 Name,Top5 Event5 Class,Top5 Event5 Waits,Top5 Event5 Time (s),Top5 Event5 Average Time (ms),Top5 Event5 %DBTime,db file sequential read Waits,db file sequential read Time (s),db file sequential read Latency (ms),db file sequential read %DBTime,db file scattered read Waits,db file scattered read Time (s),db file scattered read Latency (ms),db file scattered read %DBTime,direct path read Waits,direct path read Time (s),direct path read Latency (ms),direct path read %DBTime,direct path write Waits,direct path write Time (s),direct path write Latency (ms),direct path write %DBTime,direct path read temp Waits,direct path read temp Time (s),direct path read temp Latency (ms),direct path read temp %DBTime,direct path write temp Waits,direct path write temp Time (s),direct path write temp Latency (ms),direct path write temp %DBTime,log file sync Waits,log file sync Time (s),log file sync Latency (ms),log file sync %DBTime,db file parallel write Waits,db file parallel write Time (s),db file parallel write Latency (ms),db file parallel write %DBTime,log file parallel write Waits,log file parallel write Time (s),log file parallel write Latency (ms),log file parallel write %DBTime,log file sequential read Waits,log file sequential read Time (s),log file sequential read Latency (ms),log file sequential read %DBTime,OS busy time,OS idle time,OS iowait time,OS sys time,OS user time,OS cpu wait time,OS resource mgr wait time,Data Guard Flag,Exadata Flag,Wait Class Admin Waits,Wait Class Admin Time (s),Wait Class Admin Latency (ms),Wait Class Admin %DBTime,Wait Class Application Waits,Wait Class Application Time (s),Wait Class Application Latency (ms),Wait Class Application %DBTime,Wait Class Cluster Waits,Wait Class Cluster Time (s),Wait Class Cluster Latency (ms),Wait Class Cluster %DBTime,Wait Class Commit Waits,Wait Class Commit Time (s),Wait Class Commit Latency (ms),Wait Class Commit %DBTime,Wait Class Concurrency Waits,Wait Class Concurrency Time (s),Wait Class Concurrency Latency (ms),Wait Class Concurrency %DBTime,Wait Class Configuration Waits,Wait Class Configuration Time (s),Wait Class Configuration Latency (ms),Wait Class Configuration %DBTime,Wait Class Network Waits,Wait Class Network Time (s),Wait Class Network Latency (ms),Wait Class Network %DBTime,Wait Class Other Waits,Wait Class Other Time (s),Wait Class Other Latency (ms),Wait Class Other %DBTime,Wait Class System I/O Waits,Wait Class System I/O Time (s),Wait Class System I/O Latency (ms),Wait Class System I/O %DBTime,Histogram <1ms db file sequential read,Histogram <2ms db file sequential read,Histogram <4ms db file sequential read,Histogram <8ms db file sequential read,Histogram <16ms db file sequential read,Histogram <32ms db file sequential read,Histogram <1s db file sequential read,Histogram >1s db file sequential read,Histogram <1ms log file parallel write,Histogram <2ms log file parallel write,Histogram <4ms log file parallel write,Histogram <8ms log file parallel write,Histogram <16ms log file parallel write,Histogram <32ms log file parallel write,Histogram <1s log file parallel write,Histogram >1s log file parallel write" 1761 | } 1762 | 1763 | # Function for printing extracted AWR information when in verbose mode 1764 | print_report_info() { 1765 | # Print harvested information to errinf function 1766 | echoprt " Filename = $AWRFILENAME" 1767 | echoprt " AWR Format = $AWR_FORMAT" 1768 | echoprt " Database Name = $PROFILE_DBNAME" 1769 | echoprt " Instance Number = $PROFILE_INSTANCENUM" 1770 | echoprt " Instance Name = $PROFILE_INSTANCENAME" 1771 | echoprt " Database Version = $PROFILE_DBVERSION" 1772 | echoprt " Cluster Y/N = $PROFILE_CLUSTER" 1773 | echoprt " Hostname = $DB_HOSTNAME" 1774 | echoprt " Host OS = $DB_HOST_OS" 1775 | echoprt " Number of CPUs = $DB_NUM_CPUS" 1776 | echoprt " Server Memory = $DB_HOST_MEM" 1777 | echoprt " DB Blocksize = $DB_BLOCK_SIZE" 1778 | echoprt " Begin Snap = $AWR_BEGIN_SNAP" 1779 | echoprt " Begin Time = $AWR_BEGIN_TIME" 1780 | echoprt " End Snap = $AWR_END_SNAP" 1781 | echoprt " End Time = $AWR_END_TIME" 1782 | echoprt " Elapsed Time = $AWR_ELAPSED_TIME" 1783 | echoprt " DB Time = $AWR_DB_TIME" 1784 | echoprt " AAS = $AWR_AAS" 1785 | echoprt " Busy? = $AWR_BUSY_FLAG" 1786 | echoprt " Logical Reads/sec = $AWR_LOGICAL_READS" 1787 | echoprt " Block Changes/sec = $AWR_BLOCK_CHANGES" 1788 | echoprt " Read IOPS = $READ_IOPS" 1789 | echoprt " Data Write IOPS = $DATA_WRITE_IOPS" 1790 | echoprt " Redo Write IOPS = $REDO_WRITE_IOPS" 1791 | echoprt " Total Write IOPS = $ALL_WRITE_IOPS" 1792 | echoprt " Total IOPS = $TOTAL_IOPS" 1793 | echoprt " Read Throughput (MiB/sec) = $READ_THROUGHPUT" 1794 | echoprt " Data Write Throughput (MiB/sec) = $DATA_WRITE_THROUGHPUT" 1795 | echoprt " Redo Write Throughput (MiB/sec) = $REDO_WRITE_THROUGHPUT" 1796 | echoprt " Total Write Throughput (MiB/sec) = $ALL_WRITE_THROUGHPUT" 1797 | echoprt " Total Throughput (MiB/sec) = $TOTAL_THROUGHPUT" 1798 | echoprt " DB CPU Time ms = $AWR_DB_CPU" 1799 | echoprt " DB CPU %DBTime = $AWR_DB_CPU_PCT_DBTIME" 1800 | echoprt " Wait Class User IO Num Waits = $WCLASS_USRIO_NUM_WAITS" 1801 | echoprt " Wait Class User IO Wait Time = $WCLASS_USRIO_WAIT_TIME" 1802 | echoprt " Wait Class User IO Latency ms = $WCLASS_USRIO_AVEWAIT" 1803 | echoprt " Wait Class User IO %DBTime = $WCLASS_USRIO_PCT_DBTIME" 1804 | echoprt " User Calls/sec = $AWR_USER_CALLS" 1805 | echoprt " Parses/sec = $AWR_PARSES" 1806 | echoprt " Hard Parses/sec = $AWR_HARD_PARSES" 1807 | echoprt " Logons/sec = $AWR_LOGONS" 1808 | echoprt " Executes/sec = $AWR_EXECUTES" 1809 | echoprt " Transactions/sec = $AWR_TRANSACTIONS" 1810 | echoprt " Buffer Hit Ratio = $BUFFER_HIT_RATIO" 1811 | echoprt " In-Memory Sort Ratio = $INMEMORY_SORT_RATIO" 1812 | echoprt " Log Switches Total = $AWR_LOG_SWITCHES_TOTAL" 1813 | echoprt " Log Switches Per Hour = $AWR_LOG_SWITCHES_PERHOUR" 1814 | echoprt " Top 5 Timed Event1 Name = $TOP5EVENT1_NAME" 1815 | echoprt " Top 5 Timed Event1 Class = $TOP5EVENT1_CLASS" 1816 | echoprt " Top 5 Timed Event1 Waits = $TOP5EVENT1_WAITS" 1817 | echoprt " Top 5 Timed Event1 Time ms = $TOP5EVENT1_TIME" 1818 | echoprt " Top 5 Timed Event1 Average = $TOP5EVENT1_AVERAGE" 1819 | echoprt " Top 5 Timed Event1 %DBTime = $TOP5EVENT1_PCT_DBTIME" 1820 | echoprt " Top 5 Timed Event2 Name = $TOP5EVENT2_NAME" 1821 | echoprt " Top 5 Timed Event2 Class = $TOP5EVENT2_CLASS" 1822 | echoprt " Top 5 Timed Event2 Waits = $TOP5EVENT2_WAITS" 1823 | echoprt " Top 5 Timed Event2 Time ms = $TOP5EVENT2_TIME" 1824 | echoprt " Top 5 Timed Event2 Average = $TOP5EVENT2_AVERAGE" 1825 | echoprt " Top 5 Timed Event2 %DBTime = $TOP5EVENT2_PCT_DBTIME" 1826 | echoprt " Top 5 Timed Event3 Name = $TOP5EVENT3_NAME" 1827 | echoprt " Top 5 Timed Event3 Class = $TOP5EVENT3_CLASS" 1828 | echoprt " Top 5 Timed Event3 Waits = $TOP5EVENT3_WAITS" 1829 | echoprt " Top 5 Timed Event3 Time ms = $TOP5EVENT3_TIME" 1830 | echoprt " Top 5 Timed Event3 Average = $TOP5EVENT3_AVERAGE" 1831 | echoprt " Top 5 Timed Event3 %DBTime = $TOP5EVENT3_PCT_DBTIME" 1832 | echoprt " Top 5 Timed Event4 Name = $TOP5EVENT4_NAME" 1833 | echoprt " Top 5 Timed Event4 Class = $TOP5EVENT4_CLASS" 1834 | echoprt " Top 5 Timed Event4 Waits = $TOP5EVENT4_WAITS" 1835 | echoprt " Top 5 Timed Event4 Time ms = $TOP5EVENT4_TIME" 1836 | echoprt " Top 5 Timed Event4 Average = $TOP5EVENT4_AVERAGE" 1837 | echoprt " Top 5 Timed Event4 %DBTime = $TOP5EVENT4_PCT_DBTIME" 1838 | echoprt " Top 5 Timed Event5 Name = $TOP5EVENT5_NAME" 1839 | echoprt " Top 5 Timed Event5 Class = $TOP5EVENT5_CLASS" 1840 | echoprt " Top 5 Timed Event5 Waits = $TOP5EVENT5_WAITS" 1841 | echoprt " Top 5 Timed Event5 Time ms = $TOP5EVENT5_TIME" 1842 | echoprt " Top 5 Timed Event5 Average = $TOP5EVENT5_AVERAGE" 1843 | echoprt " Top 5 Timed Event5 %DBTime = $TOP5EVENT5_PCT_DBTIME" 1844 | echoprt " FG db file sequential read Waits = $WAIT_DFSR_WAITS" 1845 | echoprt " FG db file sequential read Time ms = $WAIT_DFSR_TIME" 1846 | echoprt " FG db file sequential read Average = $WAIT_DFSR_AVERAGE" 1847 | echoprt " FG db file sequential read %DBTime = $WAIT_DFSR_PCT_DBTIME" 1848 | echoprt " FG db file scattered read Waits = $WAIT_DFXR_WAITS" 1849 | echoprt " FG db file scattered read Time ms = $WAIT_DFXR_TIME" 1850 | echoprt " FG db file scattered read Average = $WAIT_DFXR_AVERAGE" 1851 | echoprt " FG db file scattered read %DBTime = $WAIT_DFXR_PCT_DBTIME" 1852 | echoprt " FG direct path read Waits = $WAIT_DPRD_WAITS" 1853 | echoprt " FG direct path read Time ms = $WAIT_DPRD_TIME" 1854 | echoprt " FG direct path read Average = $WAIT_DPRD_AVERAGE" 1855 | echoprt " FG direct path read %DBTime = $WAIT_DPRD_PCT_DBTIME" 1856 | echoprt " FG direct path write Waits = $WAIT_DPWR_WAITS" 1857 | echoprt " FG direct path write Time ms = $WAIT_DPWR_TIME" 1858 | echoprt " FG direct path write Average = $WAIT_DPWR_AVERAGE" 1859 | echoprt " FG direct path write %DBTime = $WAIT_DPWR_PCT_DBTIME" 1860 | echoprt " FG direct path read temp Waits = $WAIT_DPRT_WAITS" 1861 | echoprt " FG direct path read temp Time ms = $WAIT_DPRT_TIME" 1862 | echoprt " FG direct path read temp Average = $WAIT_DPRT_AVERAGE" 1863 | echoprt " FG direct path read temp %DBTime = $WAIT_DPRT_PCT_DBTIME" 1864 | echoprt " FG direct path write temp Waits = $WAIT_DPWT_WAITS" 1865 | echoprt " FG direct path write temp Time ms = $WAIT_DPWT_TIME" 1866 | echoprt " FG direct path write temp Average = $WAIT_DPWT_AVERAGE" 1867 | echoprt " FG direct path write temp %DBTime = $WAIT_DPWT_PCT_DBTIME" 1868 | echoprt " FG log file sync Waits = $WAIT_LFSY_WAITS" 1869 | echoprt " FG log file sync Time ms = $WAIT_LFSY_TIME" 1870 | echoprt " FG log file sync Average = $WAIT_LFSY_AVERAGE" 1871 | echoprt " FG log file sync %DBTime = $WAIT_LFSY_PCT_DBTIME" 1872 | echoprt " BG db file parallel write Waits = $WAIT_DFPW_WAITS" 1873 | echoprt " BG db file parallel write Time ms = $WAIT_DFPW_TIME" 1874 | echoprt " BG db file parallel write Average = $WAIT_DFPW_AVERAGE" 1875 | echoprt " BG db file parallel write %BGTime = $WAIT_DFPW_PCT_DBTIME" 1876 | echoprt " BG log file parallel write Waits = $WAIT_LFPW_WAITS" 1877 | echoprt " BG log file parallel write Time ms = $WAIT_LFPW_TIME" 1878 | echoprt " BG log file parallel write Average = $WAIT_LFPW_AVERAGE" 1879 | echoprt " BG log file parallel write %BGTime = $WAIT_LFPW_PCT_DBTIME" 1880 | echoprt " BG log file sequential read Waits = $WAIT_LFSR_WAITS" 1881 | echoprt " BG log file sequential read Time ms = $WAIT_LFSR_TIME" 1882 | echoprt " BG log file sequential read Average = $WAIT_LFSR_AVERAGE" 1883 | echoprt " BG log file sequential read %BGTime = $WAIT_LFSR_PCT_DBTIME" 1884 | echoprt " OS busy time (sec/100) = $OS_BUSY_TIME" 1885 | echoprt " OS idle time (sec/100) = $OS_IDLE_TIME" 1886 | echoprt " OS iowait time (sec/100) = $OS_IOWAIT_TIME" 1887 | echoprt " OS sys time (sec/100) = $OS_SYS_TIME" 1888 | echoprt " OS user time (sec/100) = $OS_USER_TIME" 1889 | echoprt " OS cpu wait time (sec/100) = $OS_CPU_WAIT_TIME" 1890 | echoprt " OS resource mgr wait time (sec/100) = $OS_RSRC_MGR_WAIT_TIME" 1891 | echoprt " Data Guard in use? = $DATA_GUARD_FLAG" 1892 | echoprt " Exadata in use? = $EXADATA_FLAG" 1893 | echoprt " Wait Class Admin Num Waits = $WCLASS_ADMIN_NUM_WAITS" 1894 | echoprt " Wait Class Admin Wait Time = $WCLASS_ADMIN_WAIT_TIME" 1895 | echoprt " Wait Class Admin Latency ms = $WCLASS_ADMIN_AVEWAIT" 1896 | echoprt " Wait Class Admin %DBTime = $WCLASS_ADMIN_PCT_DBTIME" 1897 | echoprt " Wait Class Application Num Waits = $WCLASS_APPLN_NUM_WAITS" 1898 | echoprt " Wait Class Application Wait Time = $WCLASS_APPLN_WAIT_TIME" 1899 | echoprt " Wait Class Application Latency ms = $WCLASS_APPLN_AVEWAIT" 1900 | echoprt " Wait Class Application %DBTime = $WCLASS_APPLN_PCT_DBTIME" 1901 | echoprt " Wait Class Cluster Num Waits = $WCLASS_CLSTR_NUM_WAITS" 1902 | echoprt " Wait Class Cluster Wait Time = $WCLASS_CLSTR_WAIT_TIME" 1903 | echoprt " Wait Class Cluster Latency ms = $WCLASS_CLSTR_AVEWAIT" 1904 | echoprt " Wait Class Cluster %DBTime = $WCLASS_CLSTR_PCT_DBTIME" 1905 | echoprt " Wait Class Commit Num Waits = $WCLASS_COMMT_NUM_WAITS" 1906 | echoprt " Wait Class Commit Wait Time = $WCLASS_COMMT_WAIT_TIME" 1907 | echoprt " Wait Class Commit Latency ms = $WCLASS_COMMT_AVEWAIT" 1908 | echoprt " Wait Class Commit %DBTime = $WCLASS_COMMT_PCT_DBTIME" 1909 | echoprt " Wait Class Concurrency Num Waits = $WCLASS_CNCUR_NUM_WAITS" 1910 | echoprt " Wait Class Concurrency Wait Time = $WCLASS_CNCUR_WAIT_TIME" 1911 | echoprt " Wait Class Concurrency Latency ms = $WCLASS_CNCUR_AVEWAIT" 1912 | echoprt " Wait Class Concurrency %DBTime = $WCLASS_CNCUR_PCT_DBTIME" 1913 | echoprt " Wait Class Configuration Num Waits = $WCLASS_CONFG_NUM_WAITS" 1914 | echoprt " Wait Class Configuration Wait Time = $WCLASS_CONFG_WAIT_TIME" 1915 | echoprt " Wait Class Configuration Latency ms = $WCLASS_CONFG_AVEWAIT" 1916 | echoprt " Wait Class Configuration %DBTime = $WCLASS_CONFG_PCT_DBTIME" 1917 | echoprt " Wait Class Network Num Waits = $WCLASS_NETWK_NUM_WAITS" 1918 | echoprt " Wait Class Network Wait Time = $WCLASS_NETWK_WAIT_TIME" 1919 | echoprt " Wait Class Network Latency ms = $WCLASS_NETWK_AVEWAIT" 1920 | echoprt " Wait Class Network %DBTime = $WCLASS_NETWK_PCT_DBTIME" 1921 | echoprt " Wait Class Other Num Waits = $WCLASS_OTHER_NUM_WAITS" 1922 | echoprt " Wait Class Other Wait Time = $WCLASS_OTHER_WAIT_TIME" 1923 | echoprt " Wait Class Other Latency ms = $WCLASS_OTHER_AVEWAIT" 1924 | echoprt " Wait Class Other %DBTime = $WCLASS_OTHER_PCT_DBTIME" 1925 | echoprt " Wait Class System IO Num Waits = $WCLASS_SYSIO_NUM_WAITS" 1926 | echoprt " Wait Class System IO Wait Time = $WCLASS_SYSIO_WAIT_TIME" 1927 | echoprt " Wait Class System IO Latency ms = $WCLASS_SYSIO_AVEWAIT" 1928 | echoprt " Wait Class System IO %DBTime = $WCLASS_SYSIO_PCT_DBTIME" 1929 | echoprt " Histogram db file sequential read <1ms = $HGRM_DFSR_1MS" 1930 | echoprt " Histogram db file sequential read <2ms = $HGRM_DFSR_2MS" 1931 | echoprt " Histogram db file sequential read <4ms = $HGRM_DFSR_4MS" 1932 | echoprt " Histogram db file sequential read <8ms = $HGRM_DFSR_8MS" 1933 | echoprt " Histogram db file sequential read <16ms = $HGRM_DFSR_16MS" 1934 | echoprt " Histogram db file sequential read <32ms = $HGRM_DFSR_32MS" 1935 | echoprt " Histogram db file sequential read <1s = $HGRM_DFSR_LT1S" 1936 | echoprt " Histogram db file sequential read >1s = $HGRM_DFSR_GT1S" 1937 | echoprt " Histogram log file parallel write <1ms = $HGRM_LFPW_1MS" 1938 | echoprt " Histogram log file parallel write <2ms = $HGRM_LFPW_2MS" 1939 | echoprt " Histogram log file parallel write <4ms = $HGRM_LFPW_4MS" 1940 | echoprt " Histogram log file parallel write <8ms = $HGRM_LFPW_8MS" 1941 | echoprt " Histogram log file parallel write <16ms = $HGRM_LFPW_16MS" 1942 | echoprt " Histogram log file parallel write <32ms = $HGRM_LFPW_32MS" 1943 | echoprt " Histogram log file parallel write <1s = $HGRM_LFPW_LT1S" 1944 | echoprt " Histogram log file parallel write >1s = $HGRM_LFPW_GT1S" 1945 | } 1946 | 1947 | # Start of main program - check that parameters have been passed in 1948 | echo "" 1>&2 1949 | [[ "$#" -eq 0 ]] && usage 1950 | 1951 | # Process calling parameters 1952 | while getopts ":hHnpsvX" opt; do 1953 | case $opt in 1954 | h) 1955 | # Print usage information and then exit 1956 | usage 1957 | ;; 1958 | H) 1959 | # Print the header row and then exit 1960 | [[ "$HEADERROW" = 0 ]] && usage "Header and NoHeader are conflicting options" 1961 | HEADERROW=2 1962 | ;; 1963 | n) 1964 | # Do not print the header row in the CSV file 1965 | [[ "$HEADERROW" = 2 ]] && usage "Header and NoHeader are conflicting options" 1966 | HEADERROW=0 1967 | ;; 1968 | p) 1969 | [[ "$SILENT" = 1 ]] && usage "Silent and Print Report Info are conflicting options" 1970 | PRINT_REPORT_INFO=1 1971 | ;; 1972 | s) 1973 | [[ "$VERBOSE" = 1 ]] && usage "Silent and Verbose are conflicting options" 1974 | [[ "$PRINT_REPORT_INFO" = 1 ]] && usage "Silent and Print Report Info are conflicting options" 1975 | SILENT=1 1976 | ;; 1977 | v) 1978 | [[ "$SILENT" = 1 ]] && usage "Silent and Verbose are conflicting options" 1979 | VERBOSE=1 1980 | PRINT_REPORT_INFO=1 1981 | echovrb "Running in verbose mode" 1982 | ;; 1983 | X) 1984 | DEBUG=1 1985 | echodbg "Running in debug mode - expect lots of output..." 1986 | ;; 1987 | \?) 1988 | usage "Invalid option -$OPTARG" 1989 | ;; 1990 | esac 1991 | done 1992 | 1993 | # If debug mode enabled, automatically enable verbose mode and disable silent mode 1994 | if [ "$DEBUG" = 1 ]; then 1995 | VERBOSE=1 1996 | SILENT=0 1997 | # Add an field terminator for use with debugging the contents of variables 1998 | ENDCHAR="|" 1999 | echodbg "Script called with parameters: $*" 2000 | fi 2001 | 2002 | # Determine if we are just printing the header row and then exiting 2003 | if [ "$HEADERROW" = 2 ]; then 2004 | echoinf "Printing header row and then exiting (found -H flag)" 2005 | print_header_row 2006 | exit $EXIT_SUCCESS 2007 | fi 2008 | 2009 | # Check that basic calculator is installed, otherwise exit with error 2010 | command -v bc >/dev/null 2>&1 2011 | if [ "$?" = 0 ]; then 2012 | echodbg "Found basic calculator installed in path $PATH" 2013 | else 2014 | echovrb "Basic Calculator not found in path $PATH" 2015 | echoerr "Basic Calculator (bc) not found - see Appendix in Manual if using Cygwin" 2016 | exit $EXIT_FAILURE 2017 | fi 2018 | 2019 | # Set Internal Field Seperator to be word delimited 2020 | set_ifs_to_word_delimited 2021 | 2022 | # Once switches have been processed, check filenames have been passed in too 2023 | shift $(($OPTIND - 1)) 2024 | [[ "$#" -eq 0 ]] && usage "Filename(s) required" 2025 | 2026 | # Determine if we should print the header row as the first line of the CSV file 2027 | if [ "$HEADERROW" = 1 ]; then 2028 | echovrb "Printing header row" 2029 | print_header_row 2030 | else 2031 | echoinf "Printing of header row disabled with -n flag" 2032 | fi 2033 | 2034 | # Main loop - Iterate through all files 2035 | while (( "$#" )); do 2036 | let FILECNT++ 2037 | # Check file is readable 2038 | if [ -r "$1" ]; then 2039 | AWRFILE=$1 2040 | echovrb " " 2041 | echoinf "Parsing file $AWRFILE at `date +'%F %T'`" 2042 | # Perform checks to ensure file is an AWR report but not in HTML format 2043 | CHECK_HTML=$(sed -n -e '1,5 p' $AWRFILE | grep -i "" | wc -l) 2044 | CHECK_STATSPACK=$(sed -n -e '1,5 p' $AWRFILE | grep STATSPACK | wc -l) 2045 | CHECK_AWR=$(sed -n -e '1,5 p' $AWRFILE | grep "WORKLOAD REPOSITORY" | wc -l) 2046 | if [ "$CHECK_HTML" -gt "0" ]; then 2047 | # File was in HTML format 2048 | echoerr "$1 is in HTML format - ignoring..." 2049 | elif [ "$CHECK_STATSPACK" -gt "0" ]; then 2050 | # File was STATSPACK and not AWR Report 2051 | echoerr "$1 is a STATSPACK file - ignoring..." 2052 | elif [ "$CHECK_AWR" -gt "0" ]; then 2053 | # Reset global variables 2054 | unset PROFILE_DBNAME PROFILE_INSTANCENUM PROFILE_INSTANCENAME PROFILE_DBVERSION PROFILE_CLUSTER DB_HOSTNAME DB_HOST_OS DB_NUM_CPUS DB_HOST_MEM DB_BLOCK_SIZE AWR_BEGIN_SNAP AWR_BEGIN_TIME AWR_END_SNAP AWR_END_TIME AWR_ELAPSED_TIME AWR_ELAPSED_TIME_SECS AWR_DB_TIME AWR_AAS AWR_BUSY_FLAG AWR_LOGICAL_READS AWR_BLOCK_CHANGES READ_IOPS DATA_WRITE_IOPS REDO_WRITE_IOPS ALL_WRITE_IOPS TOTAL_IOPS READ_THROUGHPUT DATA_WRITE_THROUGHPUT REDO_WRITE_THROUGHPUT ALL_WRITE_THROUGHPUT TOTAL_THROUGHPUT AWR_DB_CPU AWR_DB_CPU_PCT_DBTIME WCLASS_USRIO_NUM_WAITS WCLASS_USRIO_WAIT_TIME WCLASS_USRIO_AVEWAIT WCLASS_USRIO_PCT_DBTIME AWR_USER_CALLS AWR_PARSES AWR_HARD_PARSES AWR_LOGONS AWR_EXECUTES AWR_TRANSACTIONS BUFFER_HIT_RATIO INMEMORY_SORT_RATIO AWR_LOG_SWITCHES_TOTAL AWR_LOG_SWITCHES_PERHOUR 2055 | unset TOP5EVENT1_NAME TOP5EVENT1_CLASS TOP5EVENT1_WAITS TOP5EVENT1_TIME TOP5EVENT1_AVERAGE TOP5EVENT1_PCT_DBTIME TOP5EVENT2_NAME TOP5EVENT2_CLASS TOP5EVENT2_WAITS TOP5EVENT2_TIME TOP5EVENT2_AVERAGE TOP5EVENT2_PCT_DBTIME TOP5EVENT3_NAME TOP5EVENT3_CLASS TOP5EVENT3_WAITS TOP5EVENT3_TIME TOP5EVENT3_AVERAGE TOP5EVENT3_PCT_DBTIME TOP5EVENT4_NAME TOP5EVENT4_CLASS TOP5EVENT4_WAITS TOP5EVENT4_TIME TOP5EVENT4_AVERAGE TOP5EVENT4_PCT_DBTIME TOP5EVENT5_NAME TOP5EVENT5_CLASS TOP5EVENT5_WAITS TOP5EVENT5_TIME TOP5EVENT5_AVERAGE TOP5EVENT5_PCT_DBTIME 2056 | unset WAIT_DFSR_WAITS WAIT_DFSR_TIME WAIT_DFSR_AVERAGE WAIT_DFSR_PCT_DBTIME WAIT_DFXR_WAITS WAIT_DFXR_TIME WAIT_DFXR_AVERAGE WAIT_DFXR_PCT_DBTIME WAIT_DPRD_WAITS WAIT_DPRD_TIME WAIT_DPRD_AVERAGE WAIT_DPRD_PCT_DBTIME WAIT_DPWR_WAITS WAIT_DPWR_TIME WAIT_DPWR_AVERAGE WAIT_DPWR_PCT_DBTIME WAIT_DPRT_WAITS WAIT_DPRT_TIME WAIT_DPRT_AVERAGE WAIT_DPRT_PCT_DBTIME WAIT_DPWT_WAITS WAIT_DPWT_TIME WAIT_DPWT_AVERAGE WAIT_DPWT_PCT_DBTIME WAIT_LFSY_WAITS WAIT_LFSY_TIME WAIT_LFSY_AVERAGE WAIT_LFSY_PCT_DBTIME WAIT_DFPW_WAITS WAIT_DFPW_TIME WAIT_DFPW_AVERAGE WAIT_DFPW_PCT_DBTIME WAIT_LFPW_WAITS WAIT_LFPW_TIME WAIT_LFPW_AVERAGE WAIT_LFPW_PCT_DBTIME WAIT_LFSR_WAITS WAIT_LFSR_TIME WAIT_LFSR_AVERAGE WAIT_LFSR_PCT_DBTIME 2057 | unset OS_BUSY_TIME OS_IDLE_TIME OS_IOWAIT_TIME OS_SYS_TIME OS_USER_TIME OS_CPU_WAIT_TIME OS_RSRC_MGR_WAIT_TIME DATA_GUARD_FLAG EXADATA_FLAG WCLASS_ADMIN_NUM_WAITS WCLASS_ADMIN_WAIT_TIME WCLASS_ADMIN_AVEWAIT WCLASS_ADMIN_PCT_DBTIME WCLASS_APPLN_NUM_WAITS WCLASS_APPLN_WAIT_TIME WCLASS_APPLN_AVEWAIT WCLASS_APPLN_PCT_DBTIME WCLASS_CLSTR_NUM_WAITS WCLASS_CLSTR_WAIT_TIME WCLASS_CLSTR_AVEWAIT WCLASS_CLSTR_PCT_DBTIME WCLASS_COMMT_NUM_WAITS WCLASS_COMMT_WAIT_TIME WCLASS_COMMT_AVEWAIT WCLASS_COMMT_PCT_DBTIME WCLASS_CNCUR_NUM_WAITS WCLASS_CNCUR_WAIT_TIME WCLASS_CNCUR_AVEWAIT WCLASS_CNCUR_PCT_DBTIME WCLASS_CONFG_NUM_WAITS WCLASS_CONFG_WAIT_TIME WCLASS_CONFG_AVEWAIT WCLASS_CONFG_PCT_DBTIME WCLASS_NETWK_NUM_WAITS WCLASS_NETWK_WAIT_TIME WCLASS_NETWK_AVEWAIT WCLASS_NETWK_PCT_DBTIME WCLASS_OTHER_NUM_WAITS WCLASS_OTHER_WAIT_TIME WCLASS_OTHER_AVEWAIT WCLASS_OTHER_PCT_DBTIME WCLASS_SYSIO_NUM_WAITS WCLASS_SYSIO_WAIT_TIME WCLASS_SYSIO_AVEWAIT WCLASS_SYSIO_PCT_DBTIME 2058 | unset HGRM_DFSR_1MS HGRM_DFSR_2MS HGRM_DFSR_4MS HGRM_DFSR_8MS HGRM_DFSR_16MS HGRM_DFSR_32MS HGRM_DFSR_LT1S HGRM_DFSR_GT1S HGRM_LFPW_1MS HGRM_LFPW_2MS HGRM_LFPW_4MS HGRM_LFPW_8MS HGRM_LFPW_16MS HGRM_LFPW_32MS HGRM_LFPW_LT1S HGRM_LFPW_GT1S 2059 | # Set Data Guard and Exadata flags to N 2060 | DATA_GUARD_FLAG="N" 2061 | EXADATA_FLAG="N" 2062 | # Strip any path from filename 2063 | AWRFILENAME=`basename $AWRFILE` 2064 | # Harvest data from report 2065 | process_awr_report 2066 | # Print harvested information to errinf function 2067 | [[ "$PRINT_REPORT_INFO" = 1 ]] && print_report_info 2068 | # Write values to CSV file 2069 | echocsv "$AWRFILENAME,$PROFILE_DBNAME,$PROFILE_INSTANCENUM,$PROFILE_INSTANCENAME,$PROFILE_DBVERSION,$PROFILE_CLUSTER,$DB_HOSTNAME,$DB_HOST_OS,$DB_NUM_CPUS,$DB_HOST_MEM,$DB_BLOCK_SIZE,$AWR_BEGIN_SNAP,$AWR_BEGIN_TIME,$AWR_END_SNAP,$AWR_END_TIME,$AWR_ELAPSED_TIME,$AWR_DB_TIME,$AWR_AAS,$AWR_BUSY_FLAG,$AWR_LOGICAL_READS,$AWR_BLOCK_CHANGES,$READ_IOPS,$DATA_WRITE_IOPS,$REDO_WRITE_IOPS,$ALL_WRITE_IOPS,$TOTAL_IOPS,$READ_THROUGHPUT,$DATA_WRITE_THROUGHPUT,$REDO_WRITE_THROUGHPUT,$ALL_WRITE_THROUGHPUT,$TOTAL_THROUGHPUT,$AWR_DB_CPU,$AWR_DB_CPU_PCT_DBTIME,$WCLASS_USRIO_NUM_WAITS,$WCLASS_USRIO_WAIT_TIME,$WCLASS_USRIO_AVEWAIT,$WCLASS_USRIO_PCT_DBTIME,$AWR_USER_CALLS,$AWR_PARSES,$AWR_HARD_PARSES,$AWR_LOGONS,$AWR_EXECUTES,$AWR_TRANSACTIONS,$BUFFER_HIT_RATIO,$INMEMORY_SORT_RATIO,$AWR_LOG_SWITCHES_TOTAL,$AWR_LOG_SWITCHES_PERHOUR,$TOP5EVENT1_NAME,$TOP5EVENT1_CLASS,$TOP5EVENT1_WAITS,$TOP5EVENT1_TIME,$TOP5EVENT1_AVERAGE,$TOP5EVENT1_PCT_DBTIME,$TOP5EVENT2_NAME,$TOP5EVENT2_CLASS,$TOP5EVENT2_WAITS,$TOP5EVENT2_TIME,$TOP5EVENT2_AVERAGE,$TOP5EVENT2_PCT_DBTIME,$TOP5EVENT3_NAME,$TOP5EVENT3_CLASS,$TOP5EVENT3_WAITS,$TOP5EVENT3_TIME,$TOP5EVENT3_AVERAGE,$TOP5EVENT3_PCT_DBTIME,$TOP5EVENT4_NAME,$TOP5EVENT4_CLASS,$TOP5EVENT4_WAITS,$TOP5EVENT4_TIME,$TOP5EVENT4_AVERAGE,$TOP5EVENT4_PCT_DBTIME,$TOP5EVENT5_NAME,$TOP5EVENT5_CLASS,$TOP5EVENT5_WAITS,$TOP5EVENT5_TIME,$TOP5EVENT5_AVERAGE,$TOP5EVENT5_PCT_DBTIME,$WAIT_DFSR_WAITS,$WAIT_DFSR_TIME,$WAIT_DFSR_AVERAGE,$WAIT_DFSR_PCT_DBTIME,$WAIT_DFXR_WAITS,$WAIT_DFXR_TIME,$WAIT_DFXR_AVERAGE,$WAIT_DFXR_PCT_DBTIME,$WAIT_DPRD_WAITS,$WAIT_DPRD_TIME,$WAIT_DPRD_AVERAGE,$WAIT_DPRD_PCT_DBTIME,$WAIT_DPWR_WAITS,$WAIT_DPWR_TIME,$WAIT_DPWR_AVERAGE,$WAIT_DPWR_PCT_DBTIME,$WAIT_DPRT_WAITS,$WAIT_DPRT_TIME,$WAIT_DPRT_AVERAGE,$WAIT_DPRT_PCT_DBTIME,$WAIT_DPWT_WAITS,$WAIT_DPWT_TIME,$WAIT_DPWT_AVERAGE,$WAIT_DPWT_PCT_DBTIME,$WAIT_LFSY_WAITS,$WAIT_LFSY_TIME,$WAIT_LFSY_AVERAGE,$WAIT_LFSY_PCT_DBTIME,$WAIT_DFPW_WAITS,$WAIT_DFPW_TIME,$WAIT_DFPW_AVERAGE,$WAIT_DFPW_PCT_DBTIME,$WAIT_LFPW_WAITS,$WAIT_LFPW_TIME,$WAIT_LFPW_AVERAGE,$WAIT_LFPW_PCT_DBTIME,$WAIT_LFSR_WAITS,$WAIT_LFSR_TIME,$WAIT_LFSR_AVERAGE,$WAIT_LFSR_PCT_DBTIME,$OS_BUSY_TIME,$OS_IDLE_TIME,$OS_IOWAIT_TIME,$OS_SYS_TIME,$OS_USER_TIME,$OS_CPU_WAIT_TIME,$OS_RSRC_MGR_WAIT_TIME,$DATA_GUARD_FLAG,$EXADATA_FLAG,$WCLASS_ADMIN_NUM_WAITS,$WCLASS_ADMIN_WAIT_TIME,$WCLASS_ADMIN_AVEWAIT,$WCLASS_ADMIN_PCT_DBTIME,$WCLASS_APPLN_NUM_WAITS,$WCLASS_APPLN_WAIT_TIME,$WCLASS_APPLN_AVEWAIT,$WCLASS_APPLN_PCT_DBTIME,$WCLASS_CLSTR_NUM_WAITS,$WCLASS_CLSTR_WAIT_TIME,$WCLASS_CLSTR_AVEWAIT,$WCLASS_CLSTR_PCT_DBTIME,$WCLASS_COMMT_NUM_WAITS,$WCLASS_COMMT_WAIT_TIME,$WCLASS_COMMT_AVEWAIT,$WCLASS_COMMT_PCT_DBTIME,$WCLASS_CNCUR_NUM_WAITS,$WCLASS_CNCUR_WAIT_TIME,$WCLASS_CNCUR_AVEWAIT,$WCLASS_CNCUR_PCT_DBTIME,$WCLASS_CONFG_NUM_WAITS,$WCLASS_CONFG_WAIT_TIME,$WCLASS_CONFG_AVEWAIT,$WCLASS_CONFG_PCT_DBTIME,$WCLASS_NETWK_NUM_WAITS,$WCLASS_NETWK_WAIT_TIME,$WCLASS_NETWK_AVEWAIT,$WCLASS_NETWK_PCT_DBTIME,$WCLASS_OTHER_NUM_WAITS,$WCLASS_OTHER_WAIT_TIME,$WCLASS_OTHER_AVEWAIT,$WCLASS_OTHER_PCT_DBTIME,$WCLASS_SYSIO_NUM_WAITS,$WCLASS_SYSIO_WAIT_TIME,$WCLASS_SYSIO_AVEWAIT,$WCLASS_SYSIO_PCT_DBTIME,$HGRM_DFSR_1MS,$HGRM_DFSR_2MS,$HGRM_DFSR_4MS,$HGRM_DFSR_8MS,$HGRM_DFSR_16MS,$HGRM_DFSR_32MS,$HGRM_DFSR_LT1S,$HGRM_DFSR_GT1S,$HGRM_LFPW_1MS,$HGRM_LFPW_2MS,$HGRM_LFPW_4MS,$HGRM_LFPW_8MS,$HGRM_LFPW_16MS,$HGRM_LFPW_32MS,$HGRM_LFPW_LT1S,$HGRM_LFPW_GT1S" 2070 | else 2071 | # File was not an AWR report 2072 | echoerr "$1 is not an AWR file" 2073 | fi 2074 | else 2075 | # File was not readable so throw error 2076 | echoerr "Cannot read file $1 - ignoring..." 2077 | fi 2078 | shift 2079 | 2080 | done 2081 | 2082 | echoinf "No more files found" 2083 | # Print summary information 2084 | echoinf "" 2085 | echoinf "______SUMMARY______" 2086 | echoinf "Files found : $FILECNT" 2087 | echoinf "Files processed : $(($FILECNT - $ERRORCNT))" 2088 | echoinf "Processing errors : $ERRORCNT" 2089 | echoinf "" 2090 | 2091 | # Calculate exit status and then exit 2092 | if [ "$FILECNT" -eq 0 ]; then 2093 | echoinf "Completed with no files processes" 2094 | exit $EXIT_FAILURE 2095 | elif [ "$ERRORCNT" -gt 0 ]; then 2096 | echoinf "Completed with $ERRORCNT errors" 2097 | exit $EXIT_PARTIAL_SUCCESS 2098 | else 2099 | echoinf "Completed successfully" 2100 | exit $EXIT_SUCCESS 2101 | fi 2102 | # EOF 2103 | -------------------------------------------------------------------------------- /setup-kaminario-mpath.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # setup-kaminario-mpath.sh - script for configuring the multipath.conf file with Kaminario devices 3 | # Author: flashdba (http://flashdba.com) 4 | # The output can be cut and pasted into the "multipaths {}" section of /etc/multipath.conf 5 | # Alternatively the -l option can be used to print a list of devices 6 | # 7 | # For educational purposes only - no warranty is provided 8 | # Test thoroughly - use at your own risk 9 | 10 | # TODO: Currently only written for use with Red Hat 6 / Oracle Linux 6 / SLES 11 11 | 12 | # Setup variables and arrays 13 | VERBOSE=0 14 | LISTMODE=0 15 | MULTIPATH_DEVICES=() 16 | 17 | # Setup print functions 18 | echoerr() { echo "Error: $@" 1>&2; } 19 | echovrb() { [[ "$VERBOSE" = 1 ]] && echo "Info : ${@}" 1>&2; } 20 | echoout() { echo "$@"; } 21 | echolst() { echo "$@" | tr '±' '\t' | expand -t 5 1>&2; } 22 | 23 | # Function for printing usage information 24 | usage() { 25 | echo "" 1>&2 26 | if [ "$#" -gt 0 ]; then 27 | echo "Error: $@" 1>&2 28 | echo "" 1>&2 29 | fi 30 | echo "Usage: $0 [-v ]" 1>&2 31 | echo "" 1>&2 32 | echo " Script for configuring the /etc/multipath.conf file" 1>&2 33 | echo " Creates entries for the \"multipath \{\}\" section" 1>&2 34 | echo " Requires the sg3_utils package to be present" 1>&2 35 | echo " Errors and info are printed to stderr" 1>&2 36 | echo "" 1>&2 37 | echo " Options:" 1>&2 38 | echo " -h Help (print help and version information)" 1>&2 39 | echo " -l List (print a list of devices and their details)" 1>&2 40 | echo " -v Verbose (show processing details)" 1>&2 41 | echo "" 1>&2 42 | exit 1 43 | } 44 | 45 | while getopts ":hvl" opt; do 46 | case $opt in 47 | h) 48 | usage 49 | ;; 50 | v) 51 | VERBOSE=1 52 | echovrb "Running in verbose mode" 53 | ;; 54 | l) 55 | LISTMODE=1 56 | echovrb "Running in list mode" 57 | ;; 58 | \?) 59 | echo "Invalid option: -$OPTARG" >&2 60 | usage 61 | ;; 62 | esac 63 | done 64 | 65 | # Check that the s3_utils package has been installed and is in the path 66 | if hash sg_inq 2> /dev/null; then 67 | echovrb "Using sg_inq `sg_inq -V 2>&1`" 68 | else 69 | echoerr "sg3_utils package not installed - exiting..." 70 | exit 1 71 | fi 72 | 73 | # Build a list of multipath devices to scan 74 | MULTIPATH_FILELIST=$( ls -1 /dev/dm-* ) 75 | 76 | # Iterate through the list 77 | for MPDEVICE in $MULTIPATH_FILELIST; do 78 | 79 | echovrb "Issuing inquiry to device $MPDEVICE" 80 | 81 | # Issue sg3 inquiry to device 82 | SG3_OUTPUT=`sg_inq -i $MPDEVICE 2> /dev/null` 83 | SG3_RETVAL=$? 84 | 85 | # If inquiry returned error code then skip 86 | if [ "$SG3_RETVAL" -ne 0 ]; then 87 | echovrb "Skipping device $MPDEVICE" 88 | continue 89 | fi 90 | 91 | # Scan output to find vendor id 92 | SG3_VENDORID=`echo "$SG3_OUTPUT" | grep "vendor id:" | cut -d':' -f2- | sed 's/^ *//g' | sed 's/ *$//g' ` 2> /dev/null 93 | 94 | # Check the vendor is KMNRIO otherwise skip 95 | if [ "$SG3_VENDORID" != "KMNRIO" ]; then 96 | echovrb "Ignoring device on $MPDEVICE with vendor id = $SG3_VENDORID" 97 | continue 98 | fi 99 | 100 | # Get the sysfs device location (required for udevinfo) 101 | MPATH_DEVBASE=`basename $MPDEVICE` 102 | MPATH_SYSFS="/block/$MPATH_DEVBASE" 103 | 104 | # Process device specific details 105 | LUN_NAME=`echo "$SG3_OUTPUT" | grep "vendor specific:" | awk '{print ($3)}'` 106 | LUN_UUID=`udevadm info --query=property --path=$MPATH_SYSFS 2> /dev/null | grep "DM_UUID=" | sed 's/^DM_UUID=mpath-*//g'` 107 | echovrb "Found Kaminario device on $MPDEVICE: LUN Name = $LUN_NAME UUID = $LUN_UUID" 108 | 109 | # Add details to an array variable of Kaminario devices 110 | MULTIPATH_DEVICES+=(`echo "$LUN_NAME:$LUN_UUID:$MPDEVICE"`) 111 | done 112 | 113 | # Sort the array into alphabetical order based on LUN name 114 | echovrb "Sorting discovered devices into alphabetical order..." 115 | MULTIPATH_DEVICES=($(for MPDEVICE in ${MULTIPATH_DEVICES[@]}; do 116 | echo $MPDEVICE 117 | done | sort)) 118 | echovrb "Sort complete" 119 | 120 | if [ "$LISTMODE" = 1 ]; then 121 | echolst "Device Name±LUN Name±WWID" 122 | echolst "-----------±--------±----------------------------------" 123 | else 124 | if [ -r /etc/multipath.conf ]; then 125 | echovrb "Backup up /etc/multipath.conf to /tmp" 126 | cp /etc/multipath.conf /tmp 127 | fi 128 | fi 129 | 130 | echovrb "Printing multipath.conf configuration details..." 131 | echovrb "" 132 | 133 | # Now print the multipath.conf output for each device, converting the LUN name to lowercase 134 | for MPDEVICE in ${MULTIPATH_DEVICES[@]}; do 135 | MP_WWID=`echo $MPDEVICE | cut -d':' -f2` 136 | MP_ALIAS=`echo $MPDEVICE | cut -d':' -f1 | tr '[:upper:]' '[:lower:]'` 137 | MP_DEVNAME=`echo $MPDEVICE | cut -d':' -f3` 138 | 139 | if [ "$LISTMODE" = 1 ]; then 140 | echolst "$MP_DEVNAME ±$MP_ALIAS±$MP_WWID" 141 | else 142 | echoout " multipath {" 143 | echoout " wwid $MP_WWID" 144 | echoout " alias $MP_ALIAS" 145 | echoout " }" 146 | fi 147 | done 148 | 149 | echovrb "Successful completion" 150 | exit 0 151 | -------------------------------------------------------------------------------- /setup-violin-mpath.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # setup-violin-mpath.sh : script for configuring the multipath.conf file with Violin devices 4 | # The output can be cut and pasted into the "multipaths {}" section 5 | # of /etc/multipath.conf or alternatively the -l option can be used 6 | # to print a list of devices 7 | # 8 | # See GitHub repository at https://github.com/flashdba/scripts 9 | # 10 | # ########################################################################### 11 | # # # 12 | # # Copyright (C) {2014,2015} Author: flashdba (http://flashdba.com) # 13 | # # # 14 | # # This program is free software; you can redistribute it and/or modify # 15 | # # it under the terms of the GNU General Public License as published by # 16 | # # the Free Software Foundation; either version 2 of the License, or # 17 | # # (at your option) any later version. # 18 | # # # 19 | # # This program is distributed in the hope that it will be useful, # 20 | # # but WITHOUT ANY WARRANTY; without even the implied warranty of # 21 | # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 22 | # # GNU General Public License for more details. # 23 | # # # 24 | # # You should have received a copy of the GNU General Public License along # 25 | # # with this program; if not, write to the Free Software Foundation, Inc., # 26 | # # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 27 | # # # 28 | # ########################################################################### 29 | 30 | # TODO: Currently only written for use with Red Hat 6 / Oracle Linux 6 / SLES 11 31 | 32 | # Setup variables and arrays 33 | VERBOSE=0 34 | LISTMODE=0 35 | MULTIPATH_DEVICES=() 36 | 37 | # Setup print functions 38 | echoerr() { echo "Error: $@" 1>&2; } 39 | echovrb() { [[ "$VERBOSE" = 1 ]] && echo "Info : ${@}" 1>&2; } 40 | echoout() { echo "$@"; } 41 | echolst() { echo "$@" | tr '±' '\t' | expand -t 5 1>&2; } 42 | 43 | # Function for printing usage information 44 | usage() { 45 | echo "" 1>&2 46 | if [ "$#" -gt 0 ]; then 47 | echo "Error: $@" 1>&2 48 | echo "" 1>&2 49 | fi 50 | echo "Usage: $0 [-v ]" 1>&2 51 | echo "" 1>&2 52 | echo " Script for configuring the /etc/multipath.conf file" 1>&2 53 | echo " Creates entries for the \"multipath \{\}\" section" 1>&2 54 | echo " Requires the sg3_utils package to be present" 1>&2 55 | echo " Errors and info are printed to stderr" 1>&2 56 | echo "" 1>&2 57 | echo " Options:" 1>&2 58 | echo " -h Help (print help and version information)" 1>&2 59 | echo " -l List (print a list of devices and their details)" 1>&2 60 | echo " -v Verbose (show processing details)" 1>&2 61 | echo "" 1>&2 62 | exit 1 63 | } 64 | 65 | while getopts ":hvl" opt; do 66 | case $opt in 67 | h) 68 | usage 69 | ;; 70 | v) 71 | VERBOSE=1 72 | echovrb "Running in verbose mode" 73 | ;; 74 | l) 75 | LISTMODE=1 76 | echovrb "Running in list mode" 77 | ;; 78 | \?) 79 | echo "Invalid option: -$OPTARG" >&2 80 | usage 81 | ;; 82 | esac 83 | done 84 | 85 | # Check that the s3_utils package has been installed and is in the path 86 | if hash sg_inq 2> /dev/null; then 87 | echovrb "Using sg_inq `sg_inq -V 2>&1`" 88 | else 89 | echoerr "sg3_utils package not installed - exiting..." 90 | exit 1 91 | fi 92 | 93 | # Build a list of multipath devices to scan 94 | MULTIPATH_FILELIST=$( ls -1 /dev/dm-* ) 95 | 96 | # Iterate through the list 97 | for MPDEVICE in $MULTIPATH_FILELIST; do 98 | 99 | echovrb "Issuing inquiry to device $MPDEVICE" 100 | 101 | # Issue sg3 inquiry to device 102 | SG3_OUTPUT=`sg_inq -i $MPDEVICE 2> /dev/null` 103 | SG3_RETVAL=$? 104 | 105 | # If inquiry returned error code then skip 106 | if [ "$SG3_RETVAL" -ne 0 ]; then 107 | echovrb "Skipping device $MPDEVICE" 108 | continue 109 | fi 110 | 111 | # Scan output to find vendor id 112 | SG3_VENDORID=`echo "$SG3_OUTPUT" | grep "vendor id:" | cut -d':' -f2- | sed 's/^ *//g' | sed 's/ *$//g' ` 2> /dev/null 113 | 114 | # Check the vendor is VIOLIN otherwise skip 115 | if [ "$SG3_VENDORID" != "VIOLIN" ]; then 116 | echovrb "Ignoring device on $MPDEVICE with vendor id = $SG3_VENDORID" 117 | continue 118 | fi 119 | 120 | # Get the sysfs device location (required for udevinfo) 121 | MPATH_DEVBASE=`basename $MPDEVICE` 122 | MPATH_SYSFS="/block/$MPATH_DEVBASE" 123 | 124 | # Process device specific details 125 | LUN_CONTAINER=`echo "$SG3_OUTPUT" | grep "vendor specific:" | cut -d':' -f2 | sed 's/^ *//g'` 126 | LUN_NAME=`echo "$SG3_OUTPUT" | grep "vendor specific:" | cut -d':' -f3` 127 | LUN_SERIAL=`echo "$SG3_OUTPUT" | grep "vendor specific:" | cut -d':' -f4` 128 | LUN_UUID=`udevadm info --query=property --path=$MPATH_SYSFS 2> /dev/null | grep "DM_UUID=" | sed 's/^DM_UUID=mpath-*//g'` 129 | echovrb "Found Violin device on $MPDEVICE: Container = $LUN_CONTAINER LUN Name = $LUN_NAME Serial = $LUN_SERIAL UUID = $LUN_UUID" 130 | 131 | # Add details to an array variable of Violin devices 132 | MULTIPATH_DEVICES+=(`echo "$LUN_NAME:$LUN_UUID:$LUN_CONTAINER:$LUN_SERIAL:$MPDEVICE"`) 133 | done 134 | 135 | # Sort the array into alphabetical order based on LUN name 136 | echovrb "Sorting discovered devices into alphabetical order..." 137 | MULTIPATH_DEVICES=($(for MPDEVICE in ${MULTIPATH_DEVICES[@]}; do 138 | echo $MPDEVICE 139 | done | sort)) 140 | echovrb "Sort complete" 141 | 142 | if [ "$LISTMODE" = 1 ]; then 143 | echolst "Device Name±Container ±LUN Name±WWID" 144 | echolst "-----------±-----------±--------±----------------------------------" 145 | else 146 | if [ -r /etc/multipath.conf ]; then 147 | echovrb "Backup up /etc/multipath.conf to /tmp" 148 | cp /etc/multipath.conf /tmp 149 | fi 150 | fi 151 | 152 | echovrb "Printing multipath.conf configuration details..." 153 | echovrb "" 154 | 155 | # Now print the multipath.conf output for each device, converting the LUN name to lowercase 156 | for MPDEVICE in ${MULTIPATH_DEVICES[@]}; do 157 | MP_WWID=`echo $MPDEVICE | cut -d':' -f2` 158 | MP_ALIAS=`echo $MPDEVICE | cut -d':' -f1 | tr '[:upper:]' '[:lower:]'` 159 | MP_CONTAINER=`echo $MPDEVICE | cut -d':' -f3` 160 | MP_DEVNAME=`echo $MPDEVICE | cut -d':' -f5` 161 | 162 | if [ "$LISTMODE" = 1 ]; then 163 | echolst "$MP_DEVNAME ±$MP_CONTAINER±$MP_ALIAS±$MP_WWID" 164 | else 165 | echoout " multipath {" 166 | echoout " # Container $MP_CONTAINER" 167 | echoout " wwid $MP_WWID" 168 | echoout " alias $MP_ALIAS" 169 | echoout " }" 170 | fi 171 | done 172 | 173 | echovrb "Successful completion" 174 | exit 0 175 | -------------------------------------------------------------------------------- /show_physical_io.sql: -------------------------------------------------------------------------------- 1 | -- show_physical_io.sql : script to display physical IO statistics from DBA_HIST_SYSSTAT 2 | -- specifically redo size, physical reads and physical writes 3 | -- 4 | -- See GitHub repository at https://github.com/flashdba/scripts 5 | -- 6 | -- ########################################################################### 7 | -- # # 8 | -- # Copyright (C) {2014,2015} Author: flashdba (http://flashdba.com) # 9 | -- # # 10 | -- # This program is free software; you can redistribute it and/or modify # 11 | -- # it under the terms of the GNU General Public License as published by # 12 | -- # the Free Software Foundation; either version 2 of the License, or # 13 | -- # (at your option) any later version. # 14 | -- # # 15 | -- # This program is distributed in the hope that it will be useful, # 16 | -- # but WITHOUT ANY WARRANTY; without even the implied warranty of # 17 | -- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 18 | -- # GNU General Public License for more details. # 19 | -- # # 20 | -- # You should have received a copy of the GNU General Public License along # 21 | -- # with this program; if not, write to the Free Software Foundation, Inc., # 22 | -- # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 23 | -- # # 24 | -- ########################################################################### 25 | 26 | set lines 140 pages 45 27 | accept num_days prompt 'Enter the number of days to report on [default is 0.5]: ' 28 | set verify off 29 | 30 | SELECT redo_hist.snap_id AS SnapshotID 31 | , TO_CHAR(redo_hist.snaptime, 'DD-MON HH24:MI:SS') as SnapshotTime 32 | , ROUND(redo_hist.statval/elapsed_time/1048576,2) AS Redo_MBsec 33 | , SUBSTR(RPAD('*', 20 * ROUND ((redo_hist.statval/elapsed_time) / MAX (redo_hist.statval/elapsed_time) OVER (), 2), '*'), 1, 20) AS Redo_Graph 34 | , ROUND(physical_read_hist.statval/elapsed_time/1048576,2) AS Read_MBsec 35 | , SUBSTR(RPAD('*', 20 * ROUND ((physical_read_hist.statval/elapsed_time) / MAX (physical_read_hist.statval/elapsed_time) OVER (), 2), '*'), 1, 20) AS Read_Graph 36 | , ROUND(physical_write_hist.statval/elapsed_time/1048576,2) AS Write_MBsec 37 | , SUBSTR(RPAD('*', 20 * ROUND ((physical_write_hist.statval/elapsed_time) / MAX (physical_write_hist.statval/elapsed_time) OVER (), 2), '*'), 1, 20) AS Write_Graph 38 | FROM (SELECT s.snap_id 39 | ,g.value AS stattot 40 | ,s.end_interval_time AS snaptime 41 | ,NVL(DECODE(GREATEST(VALUE, NVL(lag (VALUE) OVER (PARTITION BY s.dbid, s.instance_number, g.stat_name 42 | ORDER BY s.snap_id), 0)), VALUE, VALUE - LAG (VALUE) OVER (PARTITION BY s.dbid, s.instance_number, g.stat_name 43 | ORDER BY s.snap_id), VALUE), 0) AS statval 44 | ,(EXTRACT(day FROM s.end_interval_time)-EXTRACT(day FROM s.begin_interval_time))*86400 + 45 | (EXTRACT(hour FROM s.end_interval_time)-EXTRACT(hour FROM s.begin_interval_time))*3600 + 46 | (EXTRACT(minute FROM s.end_interval_time)-EXTRACT(minute FROM s.begin_interval_time))*60 + 47 | (EXTRACT(second FROM s.end_interval_time)-EXTRACT(second FROM s.begin_interval_time)) as elapsed_time 48 | FROM dba_hist_snapshot s, 49 | dba_hist_sysstat g, 50 | v$instance i 51 | WHERE s.snap_id = g.snap_id 52 | AND s.begin_interval_time >= sysdate-NVL('&num_days', 0.5) 53 | AND s.instance_number = i.instance_number 54 | AND s.instance_number = g.instance_number 55 | AND g.stat_name = 'redo size') redo_hist, 56 | (SELECT s.snap_id 57 | ,g.value AS stattot 58 | ,NVL(DECODE(GREATEST(VALUE, NVL(lag (VALUE) OVER (PARTITION BY s.dbid, s.instance_number, g.stat_name 59 | ORDER BY s.snap_id), 0)), VALUE, VALUE - LAG (VALUE) OVER (PARTITION BY s.dbid, s.instance_number, g.stat_name 60 | ORDER BY s.snap_id), VALUE), 0) AS statval 61 | FROM dba_hist_snapshot s, 62 | dba_hist_sysstat g, 63 | v$instance i 64 | WHERE s.snap_id = g.snap_id 65 | AND s.begin_interval_time >= sysdate-NVL('&num_days', 0.5) 66 | AND s.instance_number = i.instance_number 67 | AND s.instance_number = g.instance_number 68 | AND g.stat_name = 'physical read total bytes') physical_read_hist, 69 | (SELECT s.snap_id 70 | ,g.value AS stattot 71 | ,NVL(DECODE(GREATEST(VALUE, NVL(lag (VALUE) OVER (PARTITION BY s.dbid, s.instance_number, g.stat_name 72 | ORDER BY s.snap_id), 0)), VALUE, VALUE - LAG (VALUE) OVER (PARTITION BY s.dbid, s.instance_number, g.stat_name 73 | ORDER BY s.snap_id), VALUE), 0) AS statval 74 | FROM dba_hist_snapshot s, 75 | dba_hist_sysstat g, 76 | v$instance i 77 | WHERE s.snap_id = g.snap_id 78 | AND s.begin_interval_time >= sysdate-NVL('&num_days', 0.5) 79 | AND s.instance_number = i.instance_number 80 | AND s.instance_number = g.instance_number 81 | AND g.stat_name = 'physical write total bytes') physical_write_hist 82 | WHERE redo_hist.snap_id = physical_read_hist.snap_id 83 | AND redo_hist.snap_id = physical_write_hist.snap_id 84 | ORDER BY 1; 85 | -------------------------------------------------------------------------------- /slob_harness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # slob_harness.sh - Simple harness for running Oracle tests using SLOB 4 | # 5 | # Script Author: flashdba (http://flashdba.com) 6 | # For details of SLOB please see https://kevinclosson.net/slob/ 7 | # 8 | # For educational purposes only - no warranty is provided 9 | # Test thoroughly - use at your own risk 10 | 11 | SLOB_LOGDIR=logs 12 | SLOB_OUTDIR=AWRs 13 | [ ! -d "$SLOB_OUTDIR" ] && mkdir -p "$SLOB_OUTDIR" 14 | [ ! -d "$SLOB_LOGDIR" ] && mkdir -p "$SLOB_LOGDIR" 15 | [ -f slob.conf ] && cp slob.conf $SLOB_OUTDIR 16 | 17 | # Controls for loop - remember that the loop counter controls the number of threads per schema, not the total number of sessions 18 | SLOB_MINCOUNT=1 19 | SLOB_MAXCOUNT=16 20 | SLOB_INCREMENT=2 21 | SLOB_SCHEMAS=4 22 | 23 | SLOB_RUNLIST=`seq -s " " $SLOB_MINCOUNT $SLOB_INCREMENT $SLOB_MAXCOUNT` 24 | [ "$1" = "-t" ] && echo "Test Plan: execute with $SLOB_SCHEMAS schemas and thread counts: $SLOB_RUNLIST" && exit 0 25 | echo "Starting $0 at `date +'%F %T'` with $SLOB_SCHEMAS schemas and thread counts: $SLOB_RUNLIST" 26 | 27 | for SLOB_THREADS in $SLOB_RUNLIST 28 | do 29 | SLOB_SESSIONS=$(( $SLOB_THREADS * $SLOB_SCHEMAS )) 30 | echo "Running SLOB with $SLOB_SESSIONS sessions ($SLOB_SCHEMAS schemas and $SLOB_THREADS threads) at `date +'%F %T'`" 31 | echo "Executing: sh ./runit.sh -s $SLOB_SCHEMAS -t $SLOB_THREADS" > $SLOB_LOGDIR/runit.$SLOB_SESSIONS.log 32 | sh ./runit.sh -s $SLOB_SCHEMAS -t $SLOB_THREADS >> $SLOB_LOGDIR/runit.$SLOB_SESSIONS.log 2>&1 33 | 34 | if [ $SLOB_SESSIONS -lt 10 ]; then 35 | [ -f awr.txt ] && mv awr.txt $SLOB_OUTDIR/awr.00$SLOB_SESSIONS.txt 36 | elif [ $SLOB_SESSIONS -lt 100 ]; then 37 | [ -f awr.txt ] && mv awr.txt $SLOB_OUTDIR/awr.0$SLOB_SESSIONS.txt 38 | else 39 | [ -f awr.txt ] && mv awr.txt $SLOB_OUTDIR/awr.$SLOB_SESSIONS.txt 40 | fi 41 | done 42 | 43 | echo "$0 completed at `date +'%F %T'`" 44 | exit 0 45 | --------------------------------------------------------------------------------