Sybase Brand Color Bar
delete

Search for    in all of Sybase.com
view all search results right arrow
  blank

 
 
CLICK TO EXPAND NAVIGATION
CLICK TO EXPAND NAVIGATION
 
 
 
 
Support > Technical Documents > Document Types > Technote > Best Practices Document for ASE Monitoring

Best Practices Document for ASE Monitoring

This document discusses some of the best practice ideas on what aspects of a production ASE environment should be monitored.
 
RSS Feed
 
 
 

Best Practice

Subject: Sybase ASE Monitoring

Author(s): Tom Oorebeek, Staff DBA, Sybase IT

 

Reviewer(s): Hema Seshadri, Sr. DBA Manager, Sybase IT

 

Abstract:

 

In today's information driven world, high availability and optimal performance of database infrastructure is more important than ever. Many business aspects rely on being able to retrieve real-time data from their databases. Monitoring this critical infrastructure ensures maximum uptime. Monitoring is important not just from an overall availability and performance perspective, but also from the perspective of the end-user such that business productivity is not compromised. This document discusses some of the best practice ideas on what aspects of a production ASE environment should be monitored.

 

Introduction.

1 Best Practices: ASE Monitoring.

1.1 ASE versions.

1.2 Operating systems.

1.3 Tools.

1.4 Monitoring aspects.

1.5 What next ?

2 What to monitor ?

2.1 The ASE itself

2.2 Licenses

2.3 Database Availability.

2.4 Data Storage.

2.5 Disk Space.

2.6 Database & Transaction Log dumps.

2.7 User Activity

2.8 Error Logs

2.9 Blocking

2.10 Data Consistency

Appendix A

Template error checking script

Filename:      STARTSERVER

Filename:      admindump

Filename:      cnt_sessions

Filename:      dba.pl

Filename:      db_spy

Filename:      hostname.fs_spaceused.ini

Filename:      fs_spaceused

Filename:      logscan.ini

Filename:      logscan

Filename:      object_addition

Filename:      run_sysmon

Filename:      sp_block.sql

Filename:      sp_echotime.sql

Filename:      sp_devusage.sql

Filename:      sp_hogs.sql

Filename:      sp_lockname.sql

Filename:      sp_w.sql

 

Introduction

  • - This Best Practices document is to help a Sybase DBA understand the various aspects of ASE monitoring and provide a quick start for setting up such monitoring.

1 Best Practices: ASE Monitoring

1.1 ASE versions

This document applies to all currently supported ASE versions. If certain features are specific to a particular version, it will be mentioned in the description at hand.

1.2 Operating systems

The monitoring aspects are generic across H/W platforms, although the sample scripts in Appendix A were written for the UNIX platform.

1.3 Tools

Various tools are available in the market for monitoring an ASE, e.g. Sybase SCC, Sybase Central, sysmon, MDA Tables, DB Artisan, DB Virtualizer, or Nimbus. This document focuses on what to monitor rather than recommending a tool or method to monitor. As necessary, references are made to automatic/unattended monitoring through scripts and cronjobs (Unix environments only).

A standard ASE server software installation includes software like Historical Server and Monitor Server, but these are separate products with their own manuals. As such these products are not described here either.

 

1.4 Monitoring aspects

What aspects of an ASE should be monitored? How often?  Although the type, frequency and threshold levels for monitoring a system will vary from environment to environment, some aspects are essential to all ASE environments.

 

  • ASE Availability
  • Licenses
  • Database availability
  • Data storage
    • Devices
    • Database segments
    • Log
  • User Activity
  • Error logs
  • Blocking
  • Data Consistency

1.5 What next ?

You followed the best practices and did setup extensive monitoring. Now, what?

Whether you choose to page a on call DBA, email the DBA or an entire alias, or fix the problem on a proactive basis, is up to you. This document does not spell out the actions to follow an alert from your monitoring tool, although certain recommendations may be made.

Typical Sybase environments have multiple ASEs that cater to a variety of business applications. It is recommended to buy or build a tool that provides an enterprise view of these systems, with the ability to drill down to issues for any given system.

A dashboard approach to the problem that is tied in to the monitoring system, allows for the monitoring script/feature to display the server status based on the alerts just received. For example, a server down status might mark the server icon red. An error 1105 situation might mark the server orange. A server with no monitoring alerts would stay green and so on. As alerts are attended to, the server status would change accordingly.

2 What to monitor ?

2.1 The ASE itself

 

  1. Is the server up and running?

Ping the database server frequently to ensure it is alive and responding to commands. Check for the process at O/S level and also ping the database for a simple command. Ensure it returns the expect results. This confirms the basic availability of your server. Page the on call DBA if the server process does not show up or respond.

Do the same for your Backup Server process.

 

  1. If it was just rebooted,
    • Did it start up correctly with all options enabled?
    • Is the license valid?
    • Did it come up with async I/O?
    • Did all the databases come up correctly?
    • Check for anything abnormal 

ASE startup messages are more or less standard server messages, like opening of the allocated devices and databases, but others, depending on configuration and/or traceflags, can show extra information about various aspects of the running ASE, like: connections (successful and failure logins), licenses etc.

See sample STARTSERVER script file in Appendix A for built-in error checking.

Once a server has started, the errorlog should be checked for startup behavior and non-standard messages, whereas a running server should have its errorlog automatically and periodically be scanned and non-standard messages be emailed to the concerned DBA(s).

To decide if a message is important enough for reporting, one could setup search strings per different type of messages, like errors (fatal or not), warnings and operational messages.
A separate category would be messages that could be picked up as errors or warnings, but can be skipped during normal processing. This type of messages would include objects names with the word error or msg in it.

 

Be sure to include keywords such as E(e)rror, stack, infected, warning, msg, instead,  will shutdown, failed and any other keywords/phrases applicable to your environment. Filter on errors you know to be informational. See your ASE Error Messages Guide for details on informational errors. Error numbers of the pattern 6?? (6 followed by two digits) tend to be severe. Set up special alerts for this - for example, email messages with the word 'PANIC' or 'SEVERE ALERT' in them.

 

 

2.2 Licenses

 

Many Sybase products are offered with several editions and license types. Some features are not part of the core product and as such, require active licenses. Most customers use the SYSAM manager to manage licenses. Some may have a central licensing server.

 

Monitor your license server process. Ensure it is up and running. Look for errors. If you use stand alone licensing, check for keywords such as 'grace', 'will shutdown', 'Failed to obtain' and 'expire'.

 

You can specify the email address to send licensing warnings  and errors during ASE installation or by using the sp_lmconfig command after installation.

 

2.3 Database Availability

The server itself may be up and running, but are the individual databases available to the users? For example, after a scheduled downtime where a particular database was made offline to users, setup monitoring that will alert a DBA if a database is unintentionally left in dbo or read-only mode. Or sql queries may be timing out on a particular user database.

 

Another example would be that the database is available to users, but is perhaps in log suspend or is refusing connections for some reason.

  • - Setup alerts for free log space per user database. Set up your alerts such that they escalate in priority if the situation does not improve.
  • - You may set your last chance thresholds to dump the log or abort the transaction, but there could be scenarios where the LCT action does not have a chance to kick in. Be sure to check for 1105 and log suspend errors.

In addition to alerts, one should check the general response time that will alert the DBA if a simple query such as 'sp_who' does not return in a reasonable amount of time.  Be sure to use a non-privileged account when checking database availability as discussed in this section.

 

2.4 Data Storage

Device and database space is more or less static and pre-allocated. Usage information is provided by the standard procedures, sp_helpdevice (with ASE 15.x also showing free space) and sp_helpdb (also showing free space per fragment).

However, these standard procedures do not show the details required for continuous monitoring or they show too much detail, like per each fragment, when we are only interested in overall data, log and/or index segments.

Most important space monitoring is the current level of segment (data and/or log) space usage and the growth per day, week or month. Keeping historical space and growth information allows for better resource (disk space) capacity planning and allocation.

 

Devices

In general database devices are created on raw partitions and are therefore not monitored with O/S commands. However, in case an ASE also uses filesystems to store (some of) its database devices, these filesystems should also be monitored. Examples are the devices for tempdb and/or development and test ASEs.

Again, in general, these filesystem devices are more or less static, but since ASE 12.5 introduced the disk resize command, even these existing devices can grow and fill up the filesystem they are stored on. Growth and usage of these devices should therefore also be monitored.

 

See the fs_spaceused script and sp_devusage stored procedure code in Appendix A.

2.5 Disk Space

 

Depending on the Operating System being used, disk space usage can be monitored using the df (Solaris, AIX) or bdf (HP-UX) commands. Important directories to monitor at the O/S level are:

- The Sybase software installation tree ("Sybase directory")
- Errorlog directory
- Possible device directories
- Database dump directories (if dumping to disk)

 

The Sybase software directory is more or less static, apart from the ever growing errorlog and configuration files. For best practices, you may want to consider separating these files from the main installation directory for easier maintenance.

Each ASE has its own startup files like the RUNSERVER startup script, configuration files and its errorlog. Separating these files under there own folder structure enables better handling, monitoring and also allows easier upgrading of the ASE software in the future.
As an example one could store the software and startup files using the following tree setup: (using PROD_ASE as example server name)

Sample SYBASE software tree:


Directory:                 Contents:
--------------------       ---------------------------------------
/sybase/PROD_ASE           Startup script(s) and sub directories.

/sybase/PROD_ASE/cfg       Configuration files

/sybase/PROD_ASE/log       ASE error logs

/sybase/sybase_12.5.4             Version 12.5.4 software tree

/sybase/sybase_15.0.3             Version 15.0.3 software tree

/sybase                           Link to the actual version directory currently being used.

A tree setup of DBA script and log directories eases the way the monitoring environment can be maintained and copied to other hosts/ASE's.

 

Sample DBA software tree:

 

Directory:    Contents:
--------------       -----------------------------------------------------
/dba/jobs     DBA scripts for standard ASE tasks and monitoring.

/dba/input    DBA input files, used by the DBA scripts

/dba/output   DBA output files, like *.bcp etc.

/dba/log      DBA script logfiles and central server logfile(s).

/dba/sysmon   DBA script logfiles for a specific job, e.g.: run_sysmon

The above mentioned directories are used in the script samples in Appendix A.

 

2.6 Database & Transaction Log dumps

To provide for easy recovery, it is recommended that you backup your Sybase databases periodically. Backups may be done directly to tape or, first backed up to disk filesystems and later backed up at the  O/S or network level. In this latter method, both the software being used (Sybase directory, startup directories, scripts and log files) as well as the database dumps can be stored on one tape or combination of tapes.

Directories used for database dumps have to be checked at least once a day, once the database dumps have been made, as once the data volume grows, also the size of the database dump files will grow.  For performance reasons it is possible to dump databases to parallel stripes, meaning multiple dump directories (and/or filesystems) can be used for one database dump. Be sure to monitor space in each of the dump directories, so your nightly backups succeed.

 

Transactional log dumps are periodically taken to ensure point-in-time recovery. Keep these tran log dump files in a separate directory from your full backups and monitor this directory for free space as well.

Setup your monitoring to confirm daily successful backups. In addition to lack of disk space being a possible issue, there could be other failures, including disk failures or errors. Check the backup server errorlog for error keywords.

2.7 User Activity

User Activity is significant to system performance and health. It needs to be monitored from a historical perspective as well real-time to identify performance problems as they happen. Gather information on active user sessions, CPU cycles, cache hits, and disk I/O over a period of time. This will help you set up alert thresholds.

User connections

Monitor the total number of currently connected clients/users on a regular basis. This will help establish a baseline. Regular checking if a server (almost) hits its maximum number of user connections prevents users from being locked out (signaled with Error 1601 messages in the log). One way to check the number of current connections is the standard procedure sp_who, but more detailed and summary providing scripts and procedures are referenced in this document. See the sp_w procedure, db_spy and cnt_sessions scripts in Appendix A.


CPU, Disk I/O, cache hits

A standard ASE procedure that can be  used to monitor for contention and bottlenecks in real-time is sp_sysmon. Running this procedure on a regular basis with a reasonable timeframe (e.g. 5-15 minutes per run) gives us information about various ASE counters and behavior, for that timeframe. When combined with information gathered on active processes (see sample db_spy script in Appendix A), one should be able to pinpoint server or process misbehavior to certain processes and/or configuration issues. Several third party monitoring tools use this method of gathering information in their monitoring.

For details on using and interpreting sp_sysmon, please see the standard documentation set: Performance and Tuning Guide, chapter: Monitoring Performance with sp_sysmon.

There are tools available on the O/S side of the house as well to check for disk I/O bottlenecks on devices that house the database and log files.

See sample script run_sysmon in Appendix A.



MDA tables / Problem SQL

ASE 12.x introduced new Monitoring and Diagnostic (MDA) tables, which store information about currently executing processes and statements and allows a DBA to get detailed information about  ASE resources.

ASE 15.x has even more and better detailed MDA table information and as such version 15.X allows us to better monitor current behavior of the ASE.

In ASE 12.0, the MDA tables have to be installed separately using the installmontables scripts (supplied by Sybase).

In version 15.0 the MDA table installation has been incorporated in the standard installmaster script. This means every 15.x ASE already has these tables installed, but some configuration options have to be set, to be able to use them.

Typical problems faced by DBAs include sudden slow performance, hung queries, queries consuming 100% CPU and the like. Tools such as MDA Tables can be a big help here. Since problems don't always occur when a DBA is at their desk, it helps to collect historical information that can be used as a baseline. Some of the things MDA collects that can help you monitor as well as root cause a problem:

  • Process Activity: CPU usage, IO activity, resource usage
  • Resource usage: Data cache, procedure cache, engines
  • Object usage: Tables, partitions, indexes, stored procedures
  • Query history: SQL text, statement metrics, query plans, errors

 

The ASE documentation set has a separate chapter about how to use the MDA tables.
Please refer to the following manual for more information on this topic:

Adaptive Server Enterprise 15.0 > Performance and Tuning: Monitoring and Analyzing > Monitoring Tables 

2.8 Error Logs


All logfiles associated with your ASE (ASE errorlog, backup server log, monitoring or maintenance jobs output logs) should be scanned for errors, warnings and other important messages. At a minimum this scanning should report the existence of any messages (found/not found or success/failure). One step further would be to also report the object (e.g. database or segment) the messages are related to.

 

Be sure to include keywords such as E(e)rror, stack, infected, warning, msg, instead,  will shutdown, failed and any other keywords/phrases applicable to your environment. Filter on errors you know to be informational. See your ASE Error Messages Guide for details on informational errors. Error numbers of the pattern 6?? (6 followed by two digits) tend to be severe. Set up special alerts for this - for example, email messages with the word 'PANIC' or 'SEVERE ALERT' in them.

 

Be  sure to monitor space for your ASE errorlogs. In the default setup, ASE always appends to the current errorlog, so this file is always growing and can become too large to query or edit with an editor. In case of an ASE reboot, it is therefore advised to rename the old errorlog (adding date/timestamp) and have the ASE create a new errorlog during every reboot.


See "Template error checking script"  for a sample error checking framework in Appendix A.

 

2.9 Blocking

Most blocking conflicts are temporary in nature, and will resolve themselves eventually in a very short period of time. However, potentially  bad application design or thoughtless adhoc user transactions can cause massive blocking impacting multiple users of the database. At such times, the server may be up and running, but for all practical purposes it is unavailable to the user.

 

Setup your monitoring to check for blocking that is non-transient. Any process (spid) that blocks for more than say, 2 minutes should be watched. Depending on the tolerance level of your user base, setup the alert to page the oncall DBA upon reaching a certain threshold. Often times, agreements with the business allow for spids blocking > 'x' minutes to be killed by the monitoring script.

See script sp_block in Appendix A for an example.

2.10 Data Consistency

Data consistency must be checked periodically. dbcc checkdb, dbcc checkcatalog and dbcc checkalloc are options that may take awhile to run on large databases, possibly blocking regular user access to the objects currently being checked.

An alternative is dbcc checkstorage which includes many dbcc checks, as well as an archive db setup, which  provides the possibility for offline dbcc checks. Neither will however fix errors reported. Setup your monitoring to first check for successful running and completion of this job and two, to report on faults reported.

Appendix A


Each sample script below executes the tasks it is written for, stores output of the job in the script's logfile, writes status information to a central logfile (per server) and where possible also writes timing and status information to a central database.

 

Remark:

All scripts below use the here shown OS/Unix and SQL code setup, but some of them are shown as stripped versions to make it easier to understand the purpose of the script, instead of supplying a full blown, ready to run script.

Also OS specifics, like setting up a perl environment, and/or particular database/table layouts are not detailed, but just their sample usage is shown.

 

Template error checking script

 

. /sybase/SYBASE.sh                                    # Set SYBASE environment

 

STATUS=SUCCESS                                                # Initial script statu

DOMAIL=true                                            # Send mail in case of error

FNDERR='ERROR|error|^Msg|^DB-LIB|^CT-LIB'                     # Find during error checking

SKPERR='_error|error_'                                        # Skip during error checking

( this info can also be gathered from separately stored ini files, see e.g. logscan.ini )

LOGDIR=/dba/log                                        # Set log directory

SVRLOG=$LOGDIR/$SERVER.LOG                             # Server central logfile

LOGFIL=$LOGDIR/$SERVER.$SCRIPT.log.'date +'%m%d.%H%M'' # Script logfile with timestamp

ERRFIL=$LOGDIR/$SERVER.$SCRIPT.log.errors                     # Error file

SYBUSR=dba                                             # Get server login name

SYBPWD='cat /dba/input/.dba_pwd'                       # Get server password

MAILER="/usr/bin/mail"                                        # Mail utility

RUNSQL="$SYBASE/$SYBASE_OCS/bin/isql -U$SYBUSR -S$SERVER -w300"      # Define isql command

RB_INS="### Your own utility to insert monitoring data into a database, here called runbook"

 

>> $SVRLOG echo "'date '+%m%d.%H%M'' $SCRIPT started"  # Add info to central logfile

>  $LOGFIL echo "'date +'%Y.%m.%d %H:%M:%S'' Start $SCRIPT"   # Open script logfile

 

## LOOP PER DATABASE OR OTHER OBJECT ...

 

   BEGERR='egrep "$FNDERR" $LOGFIL | egrep -v "$SKPERR" | wc -l'     # BEGIN error count

   $RUNSQL <<-ENDSQL >> $LOGFIL

       $SYBPWD                    -- Prevent password display in ps -ef

       SQL_statements             -- Do here whatever you want to do in this script
       go

       ENDSQL

   ENDERR='egrep "$FNDERR" $LOGFIL | egrep -v "$SKPERR" | wc -l'     # END error count

 

   if [ $ENDERR -gt $BEGERR ]                                        # Did errors occur?

   then

      STATUS="ERROR_Detected"

      >> $LOGFIL echo "'date +'%Y.%m.%d %H:%M:%S'' $SCRIPT $STATUS."

   else

      >> $LOGFIL echo "'date +'%Y.%m.%d %H:%M:%S'' $SCRIPT completed successfully."

   fi

 

## END_LOOP

 

if [ "$STATUS" = "SUCCESS" ]

then
   $RB_INS -s success                                  # Record status for monitoring
else
   $RB_INS -s error                             # Record status for monitoring

   case $DOMAIL in

   true)

      >  $ERRFIL echo "Logfile: $LOGFIL"        # Select errors and send mail
      >> $ERRFIL echo ""

      egrep "$FNDERR" $LOGFIL | egrep -v "$SKPERR" >> $ERRFIL

 

      $MAILER -s "*** $SERVER $SCRIPT: ERROR DETECTED" $MAILTO < $ERRFIL

      >> $LOGFIL echo ">>> Mail sent to $MAILTO"
   esac
fi

 

>> $LOGFIL echo "'date +'%Y.%m.%d %H:%M:%S'' Final Status: $STATUS"

>> $SVRLOG echo "'date '+%m%d.%H%M'' $SCRIPT $STATUS"  # Different time info

 

Filename:  STARTSERVER

Purpose:           Starts server PROD_ASE

 

#/bin/sh
#------------------------------------------------------------------------
# Start dataserver: PROD_ASE
# -------------------------------------------------------------------------------

. /sybase/SYBASE.sh                             # Set Sybase environment


SERVER=PROD_ASE                                 # Name of the ASE
MASTER=/dev/rdsk/sybase/PROD_ASE.master         # master device

CFGDIR=/sybase/$SERVER/cfg                      # Configuration directory
LOGDIR=/sybase/$SERVER/log                      # Log directory
CFGFIL=$CFGDIR/$SERVER.cfg                      # Configuration file
LOGFIL=$LOGDIR/errorlog                         # Errorlog

TRACES=""                                       # Traceflags
TRACES="$TRACES -T1204"                         # Print deadlock info in log

# TRACES="$TRACES -T4013"         # Show login records in log
# (now config setting)

# -------------------------------------------------------------------------------
# Check is server is already running (prevent logfile rename)
# -------------------------------------------------------------------------------
if [ '/usr/bin/ps -ef | grep dataserver | grep $SERVER | wc -l' -gt 0 ]
then

   echo "WHOA ... $SERVER is already running !!!"
   exit 1

else

   # ------------------------------------------------------------
   # Check Async IO setting
   # ------------------------------------------------------------
   asyncERR='grep -c "allow sql server async i/o = 0" $CFGFIL'

   if [ $asyncERR -gt 0 ]
   then
       echo "------------------------------------------------------------"
       echo " ERROR: Async IO not configured !!!"
       echo "------------------------------------------------------------"
       exit 1
   fi

   [ -f $LOGFIL ] && { mv $LOGFIL $LOGFIL.'date +%y%m%d.%H%M' ; }    # Rename log

   # ------------------------------------------------------------
   # Start ASE, specifying special directories and options
   # ------------------------------------------------------------

   $SYBASE/$SYBASE_ASE/bin/dataserver -s$SERVER \

                                      -e$LOGFIL \

                                      -d$MASTER \

                                      -c$CFGFIL \

                                      -i$SYBASE \

                                      -M$CFGDIR \

                                        $TRACES > /dev/null &
fi

 

Filename:  admindump

Purpose:           Save contents of important system tables in BCP (-c = text) format.

 

#!/bin/sh

# --------------------------------------------------------------------------------------

# admindump          Dump various system tables in character format

# --------------------------------------------------------------------------------------

if [ ! -d $BCPDIR ]

then

   >> $LOGFIL echo "ERROR bcp directory $BCPDIR does not exist!"

   exit 1

else

   cd $BCPDIR                           # Switch to output directory

   PARAMS="-c -U$SERVERUSER -S$SERVER"  # Set parameters

 

   for SYSTAB in syslogins        \

                 sysdatabases     \

                 sysservers       \

                 sysremotelogins  \

                 syssrvroles      \

                 syscharsets      \

                 sysconfigures    \

                 sysloginroles

   do

      OUTFIL="$SERVER.$SYSTAB.bcp.'date +'%m%d''"       # Output filename

 

      >> $LOGFIL echo "BCP out master..$SYSTAB ... 'date'"

      $RUNBCP master..$SYSTAB out $OUTFIL $PARAMS < $PWDFILE >> $LOGFIL

   done

 

Filename:  cnt_sessions

Purpose:           Counts and shows the top 30 nr of sessions per ASE account

 

#!/bin/sh
# ------------------------------------------------------------------------------
# Filename: cnt_sessions
#
# Counts the nr of sessions and shows config values
#
# Parameters: 1) servername, name of the server to connect to
#
# Expects: stored proc sp_echotime should exist.
# ------------------------------------------------------------------------------

SCRIPT='basename $0|sed 's/.sh//'' # This script

SERVER='echo $1 | tr '[a-z]' '[A-Z]''    # Server name

DISPLY=$2                         # Any string to prevent display (during cron execution)

 

[ "$SERVER"  = "" ] && { echo "Usage: $SCRIPT servername [ nodisplay ]"; exit 1; }

 

LOGFIL=./$SCRIPT.log.$SERVER.'date +%y%m%d.%H%M'

RUNSQL="isql -Udba -S$SERVER -w200"

 

# ------------------------------------------------------------------------------
# Generate report
# ------------------------------------------------------------------------------

$RUNSQL <<-ENDSQL | egrep -v 'Password:|return status = 0' > $LOGFIL

'cat /dba/input/.dba_pwd'

SET     NOCOUNT ON
DECLARE @msg  varchar(55)

SELECT  @msg  = 'Sessions in server: ' + upper(srvname)

FROM    master..sysservers

WHERE   srvid = 0

EXEC    sp_echotime @msg

go

PRINT ' ---------------------------- ----------- ----------- ------------ -----------'

EXEC    sp_configure 'user connections'

SELECT  convert(char(11), getdate(), 102) + convert(char(8), getdate(), 108)

, 'Total nr of sessions: ' + convert(varchar, count(*))

FROM   master..sysprocesses

go

PRINT  ''

SET    ROWCOUNT 30

SELECT TOP_30   = suser_name(suid)

,      Sessions = count(suid)

FROM   master..sysprocesses

GROUP  BY suid

ORDER  BY count(suid) DESC

go

ENDSQL

more $LOGFIL

 

Filename:  dba.pl

Purpose:           Standard perl module, used by all other DBA perl scripts


# ----------------------------------------------------------------------------------
# Name: dba.pl
# ----------------------------------------------------------------------------------
# Description/Purpose:     This perl module is the standard module for all dba perl jobs.
# It includes standard variable assignment as well as standard functions.
#
# Functions:
#       SetStandardVariables    - Sets up standard dba variables
#       ErrorOccurred           - Processes terminating errors
#       LogMessage              - Logs messages to standard log file
#       CentralLog              - Places a message in the "central log"
#       MailMessage             - Mails messages
#       SigTrapped              - Processes terminating signals
#       StartLog                - Puts a nicely formatted begin message in the log
#       EndLog                  - Puts a nicely formatted end message in the log
#       ExecSQL                 - Runs a SQL Statment using isql
#       ExecSql                 - Runs a SQL Statment using SybPerl DBlib
#       BaseAction              - Simple handler for ExecSql output
#       ObtainStatus            - Text to numeric converter for log/output files.
#       date                    - Returns numeric formatted date/time strings
#       DefineOS                - Sets up OS dependent variables
#       SetupAseOcsVersion      - Handles different release versions of OCS.
#
# Modification Log
# Login    Date         Action
# -------- ------------- -----------------------------------------------------------
# xxxxxx   yyy.mm.dd     Details ...
# ----------------------------------------------------------------------------------

sub SetStandardVariables
{

        # This function sets up standard variables for dba jobs.  All variables
        # that end with "Dir" are based on the $MainDir variable that should be
        # passed in through an initialization file. The OcsBin directory is also
        # based on a passed in variable.

        &DefineOS;
        &SetupAseOcsVersion;

        $JobName = $0;
        $JobName =~ s,.*[\\/](.*),$1, ;
        $JobName =~ s/\.pl//;

        chomp($Prefix    = &date("md"));
        chomp($Suffix    = &date("HMS"));
        chomp($Suffix2   = &date("HM"));
        chomp($TimeStamp = &date("mdHM"));

        # Set File Location Variables

        $JobDir  = "${MainDir}/jobs";
        $BinDir  = "${MainDir}/bin";
        $DiagDir = "${MainDir}/diagnostics";
        $SqlDir  = "${MainDir}/sql";
        $SqrDir  = "${MainDir}/sqr";
        $InDir   = "${MainDir}/input";
        $OutDir  = "${MainDir}/output";
        $WorkDir = "${MainDir}/work";
        $LogDir  = "${MainDir}/log";
        $ReptDir = "${MainDir}/reports";

        $WorkFile1 = "${WorkDir}/${Prefix}${JobName}${Suffix}.wk1";
        $WorkFile2 = "${WorkDir}/${Prefix}${JobName}${Suffix}.wk2";
        $WorkFile3 = "${WorkDir}/${Prefix}${JobName}${Suffix}.wk3";
        $MailFile  = "${WorkDir}/${Prefix}${JobName}${Suffix}.mail";

        $LogFile    = "${LogDir}/${SqlServer}.${JobName}.log.${Prefix}.${Suffix2}";
        $CentralLog = "${LogDir}/${SqlServer}.LOG";
}
sub ErrorOccured
{
        # This function simply removes any temporary files and exits
        # with a signal 99.  This is called upon an unexpected exit.

        if (-r "$WorkDir/*$JobName*")

        {
                unlink "$WorkDir/*JobName*";
        }

        exit (99);
}

sub LogMessage {

        # This function places an entry into the Log File
        # that reads as the supplied argument Message.

        if (!defined($_[0]))

        {
           $_[0] = "Log function called, no message supplied!";

        }

        open (LOGFILE, ">> $LogFile");

        print LOGFILE "$_[0]\n";

        close (LOGFILE);

}

sub CentralLog

{
        # To be compatible with older scripts, this allow the basic function
        # to enter a final status line to a central log for a given SQL Server

        my $FinalStatus = $_[0];


        if ($FinalStatus eq "")

        {
           $FinalStatus = "CentralLog function called, no message supplied!";
        };

 

        open (CENTRALLOG, ">> $CentralLog");

        print CENTRALLOG "$Prefix $Suffix: $JobName: $FinalStatus\n";

        close (CENTRALLOG);

 

}

sub MailMessage

{
        # This file will send mail to the recipient with the given subject.
        # If the body is supplied, it will also be sent.  If a sender is supplied,
        # the message will be marked with that sender in the "From" field.

        my $Recipient = $_[0];
        my $Subject   = $_[1];
        my $Body      = $_[2];
        my $Sender    = $_[3];

        $Recipient =~ s/\n+//;
        $Subject   =~ s/\n+//;
        $Sender    =~ s/\n+//;

        if (!defined $MailFile)
        {
                if ($OSFlag ne "Y")
                {
                   &DefineOS;
                }
                $MailFile = "${Temp}/dba_mail.$$";
        }

        if (-r $Body)

        {
                open  (MAILFILE, "> $MailFile");
                open  (BODY,     "$Body");
                while (<BODY>)
                {
                   print MAILFILE "$_";
                }
                close (BODY);
                close (MAILFILE);

        } else {

                open  (MAILFILE, "> $MailFile");
                print  MAILFILE "$Body";
                close (MAILFILE);

        }

        if ($OS eq "MSWin32")
        {
        $Mail = qq! $Mail $MailFile -t "$Recipient" -s "$Subject" -I "$Sender" -f "$Sender" !;

 

                open (MAIL, "| $Mail");

                while (<MAIL>) { print $_; };

                close (MAIL);

        } else {
                open (MAILFILE, "$MailFile");
                open (MAIL, "| $Mail $Recipient");
                print MAIL "To: $Recipient\n";
                print MAIL "From: $Sender\n";

                print MAIL "Subject: $Subject\n\n";

                while (<MAILFILE>)
                {
                        print MAIL $_;
                }
                print MAIL "\n.\n";
                close (MAIL);
                close (MAILFILE);
        }

        $mesg = "Mail sent to $Recipient\n";

        if (defined(&fLogMessage))

        {        &fLogMessage($mesg);
        } else {   LogMessage($mesg);
               }

        unlink ("$MailFile");

}

sub SigTrapped

{

        # This works in conjuction with any standard script which sets
        # up an errorhandling routine to deal with abnormal signals.
        # These are signals such as kill, hup, etc. The routine makes
        # an entry into the Log File as to which signal was received
        # and then calls the erroroccurred cleanup subfunction which
        # then exits the program.

 

        my ($sig) = @_;

        &LogMessage("Error: Signal: $sig received: exiting program");

        &ErrorOccured;
}

sub StartLog
{
        # This subfunction begins the Log File with a nicely formatted
        # set of information about the particular script.  The Info
        # String passed indicates what information to initially log
        # and is passed simply as a string of uppercase characters

        if (!defined($_[0]))

        {
                $_[0] = "JWIOLS"
        }

        uc($_[0]);

        @LogOptions = split(//, $_[0]);

        $Mesg  = "Begin Processing: $JobName\n" .  "Date: " . &date();
        $Mesg .= "Directories:\n";

        foreach $LogOption (@LogOptions)
        {
                if    ($LogOPtion eq "B")   { $Mesg .= "        Bin: $BinDir\n";
                } elsif ($LogOption eq "D") { $Mesg .= "Diagnostics: $DiagDir\n";
                } elsif ($LogOption eq "I") { $Mesg .= "      Input: $InDir\n";
                } elsif ($LogOption eq "J") { $Mesg .= "        Job: $JobDir\n";
                } elsif ($LogOption eq "L") { $Mesg .= "        Log: $LogDir\n";
                } elsif ($LogOption eq "O") { $Mesg .= "     Output: $OutDir\n";
                } elsif ($LogOption eq "Q") { $Mesg .= "        SQL: $SqlDir\n";
                } elsif ($LogOption eq "S") { $Mesg .= " Sybase Bin: $OcsBin\n";
                } elsif ($LogOption eq "W") { $Mesg .= "       Work: $WorkDir\n";
                }
        }
        $Mesg .= "-------------------------------------------\n";

        &LogMessage($Mesg);
}

sub EndLog
{
        # This procedure Places a nicely formatted finishing set of lines
        # to the Log File at the end of processing, includes a timestamp
        # and the jobname.

        $Mesg = "-------------------------------------------\n";
        $Mesg .= "End Processing: $JobName\n" . &date();

        &LogMessage($Mesg);
}

 

sub ExecSQL
{
        # Executes an SQL Statement against the given
        # server and places the output in the Log File.

        my $sql_code = $_[0];
        my $server   = $_[1];
        my $user     = $_[2];
        my $password = $_[3];
        my $TempFile = $_[4];
        my $OutFile;

        if ($OSFlag ne "Y")
        {
                &DefineOS;
        }

        if (defined($TempFile))
        {
                $OutFile = $TempFile;
        } else {
                $OutFile = $LogFile;
        }

        if ($sql_code eq "")
        {
                &LogMessage("Error: SQL Statement not defined.");
                return;
        }

        $Isql = "${OcsBin}/isql -S${server} -U${user}";

        if ($OS eq "MSWin32")
        {
                $Isql = $Isql . " -P${password}";
        }
        $Isql = $Isql . " >> $OutFile";


        $ENV{SYBASE} = "$Sybase";

        open (ISQL, "| $Isql");
        if ($OS ne "MSWin32")
        {
                print ISQL "${password}\n";
        }
        print ISQL ${sql_code};
        close (ISQL);
}

sub ExecSql
{
        # Executes an SQL Statement against the given server using sybperl.
        # Output is returned on a row by row basis for action by a passed function name.

        my $sql_code = $_[0];
        my $Server   = $_[1];
        my $User     = $_[2];
        my $Database = $_[3];
        my $Password = $_[4];
        my $Handler  = $_[5];
        my $Counter  = 1;
        my $DBHandle;
        my $RetCode = "END";

        if (!defined $Handler)
        {
                $Handler = "BaseAction";
        }

        $ENV{SYBASE} = "$Sybase";

        use Sybase::DBlib;

        if ($LogAll == 1)
        {
                print "Activating: $Server, $User\n $sql_code\n";
        }
        $DBHandle = new Sybase::DBlib $User, $Password, $Server;
        $DBHandle->dbuse($Database) or $RetCode = "Could not use $Database\n";
        $DBHandle->dbcmd($sql_code) or $RetCode = "Could not send $sql_code\n";
        $DBHandle->dbsqlexec        or $RetCode = "Could not exec $sql_code\n";
        $DBHandle->dbresults        or $RetCode = "Could not obtain results\n";

        while (@CurrentResult = $DBHandle->dbnextrow)
        {
                &{$Handler}($Counter, @CurrentResult);
                $Counter += 1;
        }
        return $RetCode;
}

 

sub BaseAction

{

        my @Results;

        my $Counter;

        ($Counter, @Results) = @_;

 

        print "Row $Counter: ";

        foreach $Result (@Results)

        {

                print "$Result\t";

        };

 

        print "\n";

}

 

sub EmptyAction

{

        # NOOP

}

 

sub ObtainStatus
{
        # This is used for searching back against the Log File of
        # the executing script and looking for known problem output.
        # If the problem output is found, the status of the job is
        # marked with the problem result.  You can set up as many
        # problem results and search strings as you like. If more
        # than one of the problem search criteria are met, the one
        # specified first will take precedence.  An ingore string
        # can also be specified.

        my @Result;
        my @Search;
        my $Status;
        my $StatusMax;
        my $Max;

        my $GoodResult         = shift(@_);
        my $Ignore             = shift(@_);

        if ($Ignore eq "")
        {
                $Ignore = "NOIGNORE";
        }

        while ((@_ + 0) > 0)
        {
                if ((@_ + 0) < 2)
                {
                        print "Invalid number of arguments specified to ObtainStatus!\n";

                        return "OBTAIN STATUS ERROR";

                } else {

                        push (@Result, shift(@_));
                        push (@Search, shift(@_));
                }
        }

        push (@Result, $GoodResult);

 

        $Max = $StatusMax = $#Result;

        $Length = $#Result;

        open  ( DETAILS, "$LogFile");
        while (<DETAILS>)

        {

                if (/$Ignore/)

                {

                } else {

                        for ($i = 0; $i < $Length; $i++)

                        {
                                if (/$Search[$i]/i)

                                { $Max = $i;
                                }

                        }

                        if ($Max < $StatusMax)

                        {  $StatusMax = $Max

                        }
                }
        }

        close (DETAILS);

 

        $Status = $Result[$StatusMax];

        return $Status;

}

 

sub EnterRunbook

{
        # This functions takes standard arguments for the rb_insert
        # program and builds them into a call to rb_insert.

        my $RbIniFile   = $_[0];
        my $RbDetails   = $_[1];
        my $Status      = $_[2];
        my $Activity    = $_[3];
        my $ForceKey    = $_[4];
        my $ForceServer = $_[5];|
        my $GrnLevel1   = $_[6];
        my $GrnLevel2   = $_[7];

 

        $RbCmd   = "${JobDir}/rb_insert ";

        $RbArgs  = "-i '${RbIniFile}'   ";

        $RbArgs .= "-D '${RbDetails}'   ";

        $RbArgs .= "-s '${Status}'      ";

        $RbArgs .= "-a '${Activity}'    ";

        if ($ForceKey ne "")

        {
                $RbArgs .= "-k '${ForceKey}' ";
        }

        if ($ForceServer ne "")

        {

                $RbArgs .= "-S '${ForceServer}' ";

        }

        if ($GrnLevel1 ne "")

        {

                $RbArgs .= "-d '${GrnLevel1}' ";

        }

        if ($GrnLevel2 ne "")

        {

                $RbArgs .= "-j '${GrnLevel2}' ";

        }

 

        open (RBINS, "${RbCmd} ${RbArgs} |");

        while (<RBINS>)

        {

                if (defined(&fLogMessage))

                {

                        &fLogMessage($_);

                } else {

                        &LogMessage($_);

                }

        }

        close (RBINS);

}

 

sub date

{
        # This procedure is for returning numeric formatted strings
        # which indicate the date and/or time at the point the procedure
        # was executed.  These are used for prefixes and suffixes and the
        # like and are not designed to be in traditional date formats.

        my ($options) = @_;
        my ($month, $day, $hour, $minute, $second, $year);
        my ($Date) = "";

 

        ($second, $minute, $hour, $day, $month, $year, $x, $y, $z) = localtime(time);

 

        $month    += 1;
        $month    = sprintf("%02d",$month);   # 2 digit Month
        $day      = sprintf("%02d",$day);     # 2 digit day of month
        $hour     = sprintf("%02d",$hour);    # 2 digit 24 hour
        $minute   = sprintf("%02d",$minute);  # 2 digit minutes
        $second   = sprintf("%02d",$second);  # 2 digit seconds
        $year     = (1900 + $year);           # 4 digit year

        if ($options eq "")

           { $options = "mdyHMS"; }

 

        @opts = split (//, $options);

        foreach $Option (@opts)
        {

                if    ($Option eq "H") { $Date = $Date . "$hour";   }
                elsif ($Option eq "M") { $Date = $Date . "$minute"; }
                elsif ($Option eq "S") { $Date = $Date . "$second"; }
                elsif ($Option eq "m") { $Date = $Date . "$month";  }
                elsif ($Option eq "d") { $Date = $Date . "$day";    }
                elsif ($Option eq "y") { $Date = $Date . "$year";   }
        }
        $Date = "$Date\n";
}

 

sub DefineOS
{
        # This procedure sets OS dependent variables for commands which
        # require specialized use.

        $OS     = $^O;
        $OSFlag = "Y";

 

        if ($OS eq "MSWin32")

        {

                $WinNTRoot      = "$ENV{SystemRoot}";

                $Mail           = "$WinNTRoot\\system32\\blat";

                $Temp           = "$ENV{TEMP}";

        } elsif ($OS eq "aix") {

                $Mail   = "/usr/lib/sendmail";

                $Temp   = "/tmp";

        } elsif ($OS eq "solaris") {

                $Mail   = "/usr/lib/sendmail";

                $Temp   = "/tmp";

        } elsif ($OS eq "sunos"  ) {

                $Mail   = "/usr/lib/sendmail";

                $Temp   = "/tmp";

        } elsif ($OS eq "linux"  ) {

                $Mail   = "/usr/sbin/sendmail";

                $Temp   = "/tmp";

        } elsif ($OS eq "hpux"   ) {

                $Mail   = "/usr/sbin/sendmail";

                $Temp   = "/tmp";
        }
}

 

sub SetupAseOcsVersion

{
        # This procedure sets up the directory structure and required
        # environment variables based on the ASE/OCS version.

        if  (substr(${SybVer}, 0, 2) eq "11")

        {

                $OcsBin = "${Sybase}/bin";

        } elsif (substr(${SybVer}, 0, 2) eq "12") {

                $ENV{SYBASE_ASE} = $SybaseAse = "ASE-12_" . substr(${SybVer}, 3, 1);

                $ENV{SYBASE_OCS} = $SybaseOcs = "OCS-12_" . substr(${SybVer}, 3, 1);

                $OcsBin = "${Sybase}/${SybaseOcs}/bin";

        } elsif (substr(${SybVer}, 0, 2) eq "15") {

                $ENV{SYBASE_ASE} = $SybaseAse = "ASE-15_" . substr(${SybVer}, 3, 1);

                $ENV{SYBASE_OCS} = $SybaseOcs = "OCS-15_" . substr(${SybVer}, 3, 1);

                $OcsBin = "${Sybase}/${SybaseOcs}/bin";

        }

}

 

sub SetBatonHolder
{
        $BatonHolder = $_[1];
}

 

sub GetBatonHolder
{

        my $Type        = $_[0];
        my $Database    = $INI{BTdb};
        my $Server      = $INI{BTsvr};
        my $User        = $INI{BTusr};
        my $Passwd      = $INI{BTpwd};
        my $SqlCode;

        if (lc($Type) eq "pager")
        {
                $Type = 'emailpager';
        } else {

                $Type = 'login';

        }

 

        $SqlCode  = "SELECT   ${Type} ";
        $SqlCode .= "FROM     contacts ";
        $SqlCode .= "WHERE    baton in ('T', 'O') ";
        $SqlCode .= "ORDER BY baton";

        &ExecSql($SqlCode, $Server, $User, $Database, $Passwd, 'SetBatonHolder');

        return($BatonHolder);
}

 

sub SendPage

{

        my $Recipient   = $_[0];
        my $Subject     = $_[1];
        my $Body        = $_[2];
        my $Sender      = $_[3];


        $Recipient      =~ s/\n+//;
        $Subject        =~ s/\n+//;
        $Sender         =~ s/\n+//;


        if (lc($Recipient) eq "baton")
        {
                $Recipient = &GetBatonHolder('PAGER');
        }
        &MailMessage($Recipient, $Subject, $Body, $Sender);
}

 

# End dba.pl

Filename:  db_spy

Purpose:           Save current processing information.

 

#!/bin/sh
# --------------------------------------------------------------------------------------
# db_spy      Collect ASE information about currently running processes
# --------------------------------------------------------------------------------------

$RUNSQL <<-EOF | egrep -v "return status" >> $LOGFIL

        $USRPWD

        SET NOCOUNT ON

        go

        print " -------------------------"

        print " Current processes"

        print " -------------------------"

        EXEC  sp_w         -- own DBA version of sp_who

        go

        print " -------------------------"

        print " Current blocked processes"

        print " -------------------------"

        EXEC  sp_block            -- Shows blocking info

        go

        print " -------------------------"

        print " Current locks"

        print " -------------------------"

        EXEC  sp_lockname  -- Own DBA version of sp_lock

        go

        print " -------------------------"

        print " Heavy hitters"

        print " -------------------------"

        EXEC  sp_hogs             -- Shows cpu and IO info from sysprocesses

        go

        print " -------------------------"

        print " Monitor info"

        print " -------------------------"

        EXEC  sp_monitor   -- Standard proc

        go

        EOF

 

Filename:  hostname.fs_spaceused.ini

Purpose:           Input file for fs_spaceused script.

 

      host= your_hostname
sql_server= PROD_ASE
  main_dir= /dba
    set_fs= default   80
    set_fs= /dbsdump1 85
    set_fs= /dbsdump2 85
    set_fs= /logdump1 90
   mail_to= dba

 

Filename:  fs_spaceused

Purpose:           Checks filesystem usage and reports on it if above a given (see

 

#!/dba/perl5/bin/perl
# --------------------------------------------------------------------------------------
# Purpose: This program extracts file system usage and alerts if
#          any given file system is beyond a configurable threshold.
#
# Modification Log
# login  | Date        | Action
#--------|-------------|-------------------------------------------------
# xxxx     yyyy.mm.dd    Details ...
#
# Obtain necessary modules
# --------------------------------------------------------------------------------------
require '/dba/jobs/dba.pl';
require 'getopts.pl';

# Define Signal Trapping #

 $SIG{INT}  = \&SigTrapped;
 $SIG{BUS}  = \&SigTrapped;
 $SIG{SEGV} = \&SigTrapped;
 $SIG{SYS}  = \&SigTrapped;
 $SIG{TSTP} = \&SigTrapped;
 $SIG{CONT} = \&SigTrapped;

#----------BEGIN MAIN PROGRAM -------------------------#

 &GetIniData;

 &SetStandardVariables;


 $LogFile = "${LogDir}/${Host}.${JobName}.log.${Prefix}.${Suffix2}";

 $RBInsert = "$JobDir/rb_insert -D ${LogFile} -a $JobName ";

 

 &StartLog("J");

 &LogIniData;

 &SetDF;

 &GetFSInfo;

 &EndLog;

 exit (0);


#----------END   MAIN PROGRAM -------------------------#

sub SetDF
{
    if ($OS eq "solaris" ) { $DF = "df -kl";      }
 elsif ($OS eq "sunos"   ) { $DF = "df -t 4.2";  }
 elsif ($OS eq "hpux"    ) { $DF = "bdf -l"; }
 elsif ($OS eq "aiux"    ) { $DF = "df -P"; }
 elsif ($OS eq "linux"   ) { $DF = "df -kl"; }
}

 

sub GetFSInfo {

 

 $BigAlert    = "No";

 $MountedOn   = "Directory";

 $PercentUsed = "Percent Used";

 $Threshold   = "Threshold";

 $Alert       = "Alert";

 &FormLogMessage;

 

 open (INP, "$DF |");

 $Discard = <INP>;

 

 while (<INP>) {

  chop;

  s/ +/=/g;

  ($FileSystem, $TotalKB, $UsedKB, $AvailableKB, $PercentUsed, $MountedOn)

    = split (/=/);

 

  if (($MountedOn =~ /\/usr\/u\//) || ($MountedOn =~ /\/cdrom\//)) { next; };

 

  if ($TotalKB  eq "") {

  $Reread = <INP>;

   chop($Reread);

   $Reread =~ s/ +/=/g;

   ($Discard, $TotalKB, $UsedKB, $AvailableKB, $PercentUsed, $MountedOn)

     = split (/=/, $Reread);

  };

 

  if (defined($Track_FS{$MountedOn})) { $Threshold = $Track_FS{$MountedOn}; }

  else                                { $Threshold = $Track_FS{default};    };

 

  $Alert = " ";

 

     if ($Threshold == 101        ) { $Threshold = "Skip"; }

  elsif ($Threshold < $PercentUsed) {

   $BigAlert = "Yes";

   $Alert = "Y";

   $Subject = "***${JobName}:${Host}: ${MountedOn} Directory beyond threshold!";

   $Body    = "The ${MountedOn} directory is ${PercentUsed} full!.";

   $Body    = $Body . "It should not be more than ${Threshold}% full.\n";

   &MailMessage($MailTo, $Subject, $Body);

   foreach $SqlServer (@SqlServers) {

    $RBJob = $RBInsert . "-i ${InDir}/${SqlServer}_rb_insert.ini "

                       . "-s alert -j ${MountedOn}";

    open (RBINS, "| $RBJob");

    close (RBINS);

   };

  };

 

  &FormLogMessage;

 };

 close(INP);

 

 LogMessage("\n");

 

 if ($BigAlert eq "Yes") {

    $FinalStatus = "alert";

    LogMessage("Mail sent to $MailTo.");

 } else {

    $FinalStatus = "ok";

 

   foreach $SqlServer (@SqlServers) {

    $RBJob = $RBInsert . "-i ${InDir}/${SqlServer}_rb_insert.ini " .

                         "-s $FinalStatus";

    open (RBINS, "| $RBJob");

    close (RBINS);

   };

 };

 LogMessage("Final Status: $FinalStatus");

};


sub GetIniData
{
   &Getopts('i:');

   die "Usage: $0 -i full path of ini file" if !defined($opt_i);

 

   $IniFile = $opt_i;

   if (! -r $IniFile) {

      print "\nBad ini file specified !!!\n";

      exit(0);

   };

 

   open   (INI, $IniFile);
   while (<INI>)
   {
     chop;

     s/=  /=/;

     if    (/main_dir/)   { ($Discard,$MainDir)     = split(/=/); }

     elsif (/sql_server/) { ($Discard,$SqlServer)   = split(/=/);

                                 push(@SqlServers, $SqlServer);   }

     elsif (/host/)       { ($Discard,$Host)        = split(/=/); }

     elsif (/mail_to/)    { ($Discard,$MailTo)      = split(/=/); }

     elsif (/set_fs/)     { ($Discard,$track)       = split(/=/);

                           ($FS, $Threshold)       = split(/\s/, $track, 2);

                               $Threshold =~ s/\s+//g;

                                    if ($Threshold == 0) { $Threshold = 101; };

                                     $Track_FS{$FS}       = $Threshold; };

   };

};

 

sub LogIniData
{

  $mesg = "";

  foreach $SqlServer (@SqlServers) {

     $mesg = $mesg . "       SQL Server: $SqlServer\n";

  };

 $mesg = $mesg . "             Host: $Host\n";
 $mesg = $mesg . "   Main Directory: $MainDir\n";


 &LogMessage($mesg);
};

 

sub FormLogMessage

{
   open (LOGFILE, ">> $LogFile");
   write LOGFILE;
   close (LOGFILE);

};

 

format LOGFILE =

@<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>>>>>  @>>>>>>>> @||||

$MountedOn, $PercentUsed, $Threshold, $Alert

.

Filename:  logscan.ini

Purpose:           Input file for logscan perl script

 

      host= your_hostname
sql_server= PROD_ASE
  main_dir= /dba
 scan_file= /dba/PROD_ASE/log/errorlog
      find= error|stack|infect|warning|sddone|msg|nopen|no free extents|cache
     panic= Error: 6??|Stack|stack trace|sleeping waiting|critically low
    ignore= Error: 21|Error: 1608|process exited|extended error information|Logon
   mail_to= dba

 

Filename:  logscan

Purpose:           Scan errorlog and report non-standard messages to DBA


#!/dba/perl5/bin/perl
# --------------------------------------------------------------------------------------------# Filename: logscan  (PERL script, so different initialization and setup !!)
#
# Scans the logfile supplied by the -i parameter file from the point of last scan
# and looks for lines containing pre-specified entries.
# --------------------------------------------------------------------------------------------# Obtain necessary modules
# --------------------------------------------------------------------------------------------require '/dba/jobs/dba.pl';           # Standard DBA perl functions
require 'getopts.pl';                 # Option parsing

# --------------------------------------------------------------------------------------------# Define Signal Trapping
# --------------------------------------------------------------------------------------------

$SIG{INT}  = \&SigTrapped;
$SIG{BUS}  = \&SigTrapped;
$SIG{SEGV} = \&SigTrapped;
$SIG{SYS}  = \&SigTrapped;
$SIG{TSTP} = \&SigTrapped;
$SIG{CONT} = \&SigTrapped;

# --------------------------------------------------------------------------------------------# Begin main program
# --------------------------------------------------------------------------------------------

&GetIniData;                            # Get initial data
&SetStandardVariables;                  # Build directories and OS dependent strings


$LogFile = "$LogDir/$SqlServer.$JobName.log.$Prefix";


&StartLog;                              # Note start to log.
&LogIniData;                            # Include pertinent script info in log.
&StampScanTo;                           # Locate point to scan to.
&LocateLastScan;                        # Locate last point scanned.
&Scan;                                  # Search for errors
&LogResults;                            # Place results in log.
&EndLog;                                # Inform log of completion.

exit (0);


# -------------------------------------------------------------------------------------------
# End main program, define subroutines
# -------------------------------------------------------------------------------------------

 

sub StampScanTo

{

# This procedure places a stamp at the current end of the file being scanned so that
# if the file is appended to during the scan, additions will be picked up in the next scan.
# This also limits the current scan's focus.

   open (SCANFILE, ">> $ScanFile");
   seek (SCANFILE, 0, 2);
   $NewPoint = tell(SCANFILE);
   print  SCANFILE "**LogScan Review**\n";
   close (SCANFILE);

};

 

sub LocateLastScan

{

# This procedure searches for the stamp from the last scan to place the starting limit on
# the current scan. If the file has never been reviewed before, a 'new file' flag is set.

 

   $Search = quotemeta("**LogScan Review**");

   $LastPoint = 0;

   $CurPoint  = 0;

 

   open  (SCANFILE, "$ScanFile");

   while ($CurPoint < $NewPoint) {

      $CurLine = <SCANFILE>; $_ = $CurLine;

      if (/$Search/) { $LastPoint = tell(SCANFILE); };

         $CurPoint = tell(SCANFILE);

   };

   close (SCANFILE);

   if ($LastPoint == 0) { $NewFlag = "NEW"; };

};

 

sub Scan

{

# This procedure scans from one point in the target file to a second point in the file.
# The two delimiting points are set by the subroutines "StampScanTo" and "LocateLastScan".
# The scan looks for a regular expression supplied by the input file.
# Additionally, lines can be ignored by suppylying an ignorable regular expression.


   $PanicPoint = "No";

 

   open (SCANFILE, "$ScanFile");

   seek (SCANFILE, $LastPoint, 0);

   while (tell(SCANFILE) < $NewPoint) {

      $_ = <SCANFILE>;

      if (/$Find/i) {

         $TotalLines += 1;

         if (/$Ignore/) { $TotalIgnored += 1; }

         else           { $Found = $Found . $_;

                        if (/$Panic/) { $PanicPoint = "Yes"; };

         };

      };

   };

   close (SCANFILE);

};

 

sub LogResults
{

# This procedure prints the results of the scan to the log file.

 

   if ($NewFlag eq "NEW") { $Found = "***NEW FILE***\n" . $Found; };

   if ($Found eq "") {

      $Found = "No Errors Found\n";

      $RBInsert .= " -s none -k ${SqlServer}.logscan";

   } else {

      if ($PanicPoint eq "Yes") { $Error = "panic"; } else { $Error = "error"; };

      $RBInsert .= " -s $Error";

      $mailsubj = "*** ${SqlServer} ${JobName}: $Error found in scan of ${ScanFile}.";

   };

 

   $mesg  = "Status of most recent search of $ScanFile:\n";

   $mesg .= "Total Lines Located: $TotalLines\n";

   $mesg .= "Found Lines Ignored: $TotalIgnored\n";

   if ($PanicPoint eq "Yes") {

      $mesg .= "PANIC ERROR OCCURED!!!\n";

   };

   $mesg .= "\n". ${Found} . "\n\n";

 

   &LogMessage($mesg);

 

   if ($Found ne "No Errors Found\n") {

      &MailMessage("$MailTo", "$mailsubj", "$mesg");

   };

   open  (RBINS, "| $RBInsert");

   close (RBINS);

};

 

sub GetIniData

{

# This is a standard procedure for getting specific information pertinent to this job
# out of an input file. The specific input options for this job are:
#
#        host= "Host machine on which jobs runs.
#  sql_server= "Server against which this job should report
#    main_dir= "Main Directory of job"
#   scan_file= "File to execute scan against"
#        find= "Regular expression to search for"
#      ignore= "Regular expression to ignore"
#     mail_to= "list of mail recipients or file name with list"

   &Getopts('i:');

   die "USAGE: $0 -i full path of ini file" if !defined($opt_i);

 

   $IniFile = $opt_i;

   if (! -r $IniFile) {

      print "Logscan: Invalid ini file specified: $IniFile !!!\n";

      exit(0);

   };

 

  open  ( INI, $IniFile);
  while (<INI>) {

      chop;

      s/= +/=/;

 

         if (/main_dir/)   { ($Discard,$MainDir)   = split(/=/);  }

      elsif (/sql_server/) { ($Discard,$SqlServer) = split(/=/);  }

      elsif (/host/)       { ($Discard,$Host)      = split(/=/);  }

      elsif (/scan_file/)  { ($Discard,$ScanFile)  = split(/=/);  }

      elsif (/find/)       { ($Discard,$Find)      = split(/=/);  }

      elsif (/panic/)      { ($Discard,$Panic)     = split(/=/);  }

      elsif (/ignore/)     { ($Discard,$Ignore)    = split(/=/);  }

      elsif (/mail_to/)    { ($Discard,$MailTo)    = split(/=/);  }

      };

   };

 

   $TotalLines   = 0;

   $TotalIgnored = 0;

   $Found        = "";

   $NewFlag      = "";

   if (!defined($Panic)) { $Panic = "No Panic Defined"; };

};

 

sub LogIniData {

# This procedure publishes job specific information to the log file

   $mesg  = "";

   $mesg .= "             Host: $Host\n";

   $mesg .= "       SQL Server: $SqlServer\n";

   $mesg .= "   Main Directory: $MainDir\n";

   $mesg .= "    Scanning File: $ScanFile\n";

   $mesg .= "  Seeking Entries: $Find\n";

   $mesg .= " Ignoring Entries: $Ignore\n";
   $mesg .= "     Panicing For: $Panic\n";

   &LogMessage($mesg);

};

Filename:  object_addition

Purpose:           Checks if (and reports on) any new objects created since previous run.

 

#!/bin/sh
# --------------------------------------------------------------------------------------
# object_addition          Show objects created since previous run
# --------------------------------------------------------------------------------------

for DBNAME in 'cat $LSTFIL'

do

   >> $LOGFIL echo ""
   >> $LOGFIL echo "====================== $DBNAME ==============================="

   $RUNSQL <<-ENDSQL | egrep -v "Password:" > $TMPFIL   # No header, only info gathered !

        $USRPWD
        USE $DBNAME
        SET NOCOUNT ON
        go
        SELECT crdate = convert(char(11), crdate, 102) + convert(char(5), crdate, 108)
        ,      type
        ,      name   = substring(name, 1,50)
        FROM   sysobjects
        WHERE  crdate > ( SELECT date
                          FROM   dbadb..maint_info
                          WHERE  activity = '$SCRIPT'
                          AND    item     = 'lastrun')
        ORDER BY type
        go
        ENDSQL

   >> $LOGFIL cat $TMPFIL  # Append info to script logfile

   set 'wc -l $TMPFIL'            # Check content, get nr of lines in temporary file
   if [ $1 -gt 0 ]
   then
      STATUS=new_object_detected
      $RB_INS -d $DBNAME -s newobject           # Record this info in Runbook
   fi
done

$RUNSQL <<-ENDSQL > /dev/null 2>&1      # Update dba info, no error checking
        $USRPWD
        UPDATE dbadb..maint_info
        SET    date     = getdate()
        WHERE  activity = '$SCRIPT'
        AND    item     = 'lastrun'
        go
        ENDSQL

 

Filename:  run_sysmon

Purpose:           Runs sp_sysmon for the given nr of times and duration

 

#!/bin/sh

# ------------------------------------------------------------------------------
# Runs sp_sysmon X times against the given server for a given time period
# ------------------------------------------------------------------------------

SCRIPT='basename $0'

SERVER='echo $1 | tr "[a-z]" "[A-Z]"'           # Server name

RUNMAX="$2"                              # nr of time to run

PERIOD="$3"                              # Duration to run in hh:mm:ss format

 

[ $# -lt 3 ] && { echo "------------------------------------------------------"
                  echo "Usage: $SCRIPT  server  times  period                 "
                  echo "                                                      "
                  echo "Where: server = name of the dataserver to connect to  "
                  echo "       times  = nr of times to run sp_sysmon          "
                  echo "       period = 1-10     for a 10.x or 11.0 dataserver"
                  echo "    or period = hh:mm:ss for a dataserver >= 11.5     "
                  echo "------------------------------------------------------"
                  exit 1 ; }

. /sybase/SYBASE.sh                             # Set SYBASE environment

SYBUSR='dba'                             # Hardcoded generic account

SYBPWD='cat /dba/input/.dba.pwd'         # Get password

FILNAM="/dba/sysmon/sysmon.out.$SERVER.${RUNMAX}x$PERIOD"

RUNSQL="$SYBASE/$SYBASE_OCS/bin/isql -U$SYBUSR -S$SERVER"

 

RUNCNT=1

while [ $RUNCNT -le $RUNMAX ]

do

   OUTFIL=$FILNAM.$RUNCNT.'date +"%y%m%d.%H%M"'

   if [ $RUNMAX -ge 10 -a $RUNCNT -lt 10 ]

   then

      OUTFIL=$FILNAM.0$RUNCNT.'date +"%y%m%d.%H%M"'

   fi

 

   $RUNSQL <<- ENDSQL  | egrep -v "Password|return status = 0" > $OUTFIL

        $SYBPWD

        exec sp_echotime "'basename $OUTFIL'"

        print 'Server:  %1!', @@servername

        print 'Version: %1!', @@version

 

        exec sp_sysmon   "$PERIOD", @dumpcounters='Y'

 

        exec sp_echotime "'basename $OUTFIL'"

        go

        ENDSQL

 

   compress $OUTFIL

   RUNCNT='expr $RUNCNT + 1'

done

Filename:  sp_block.sql

Purpose:           Stored procedure to show blocking information

 

USE sybsystemprocs

go

IF object_id('sp_block') > 0  DROP PROC sp_block

go

CREATE PROCEDURE sp_block               -- NON STANDARD SYBASE STORED PROCEDURE
AS

-- -----------------------------------------------------------------------------
-- sp_block
--
-- Show blocking info: blockers, which processes and how long
-- -----------------------------------------------------------------------------

SET NOCOUNT ON

 

-- ------------------------------------------------------- Show blockers -------

print  ' Blockers:'

print  ' ========='

 

select Spid          =  str(p.spid, 04)

     , Blocker_login = convert(char(15),  suser_name(p.suid))

     , DBname        = convert(char(15),     db_name(l.dbid))

     , Object        = convert(char(30), object_name(l.id, l.dbid))

     , Page          =  str(l.page, 09)

--   , Class         = l.class

--   , Class         = convert(char(20), l.class)

     , Cursor_Non    = patindex('Non Cursor%', l.class)

     , Cursor_Id     = patindex('Cursor Id %', l.class)

     , Locktype      = convert(char(15), v.name)

from   master..sysprocesses p

   ,   master..syslocks     l

   ,   master..spt_values   v

where  l.type = v.number

and    v.type = "L"

and    l.type &256 = 256

and    p.spid = l.spid

and    p.spid in (select blocked from master..sysprocesses where blocked > 0)

order  by p.spid

 

-- ------------------------------------------------------- Show blocked logins -

print  ''

print  ' Blocked logins:'

print  ' ==============='

select Spid          = str(spid, 4)
     , Blocked_login = substring(suser_name(suid), 1,15)

     , Blocked_by    = blocked

     , Time_blkd     = convert (varchar(10), dateadd(ss, time_blocked, '00:00:00'), 8)

from   master..sysprocesses

where  blocked <> 0

order  by 2,1,3

 

-- ------------------------------------------------------- Show blocked by time ---

print  ''

print  ' Blocked by time:'

print  ' ================'

select Spid          = str(spid, 4)

     , Blocked_login = substring(suser_name(suid), 1,15)

     , Blocked_by    = blocked

     , Time_blkd     = convert (varchar(10), dateadd(ss, time_blocked, '00:00:00'), 8)

from   master..sysprocesses s

where  blocked <> 0

order  by time_blocked

go

 

grant exec on sp_block to public

go

Filename:  sp_echotime.sql

Purpose:           Stored procedure to show the given parameter values with current date & time


USE sybsystemprocs

SET NOCOUNT ON

go

IF OBJECT_ID('sp_echotime') > 0  DROP PROC sp_echotime

go

CREATE  PROC sp_echotime ( @txt1 varchar(55)

                         , @txt2 varchar(55) = '' )

AS

-- -----------------------------------------------------------------------------

-- Displays given text with current (server) date and time in 24 hr format.

--

-- Uses 2 parameters to enable use of a fixed text and a (char) parameter

-- from calling script without need for concatination in the script itself.

-- -----------------------------------------------------------------------------

SET     NOCOUNT ON

DECLARE @text char(55)          -- Holds complete text string

,       @line char(80)          -- Holds header/footer line

,       @date char(19)          -- Holds 24 hr date, time

 

SELECT  @text = @txt1 + @txt2

,       @line = space(1) + replicate( '=', 79 )

,       @date = convert(char(11), getdate(), 102)

              + convert(char(08), getdate(), 108)

 

PRINT ''

PRINT   @line

PRINT ' ### %1! %2!', @text , @date

PRINT   @line

PRINT ''

go

GRANT EXEC ON sp_echotime TO public

go

Filename:  sp_devusage.sql

Purpose:           Stored procedure to show device size/used/free space and usage per database

 

USE sybsystemprocs

go

IF OBJECT_ID('sp_devusage') > 0  DROP PROC  sp_devusage

go

CREATE PROC sp_devusage ( @devname char(30) = NULL )

AS

-- -----------------------------------------------------------------------------
-- This is sp_devusage for ASE version 15.x, using sysdevices.vdevno
-- -----------------------------------------------------------------------------

BEGIN

   SET NOCOUNT ON

 

   DECLARE @mbfactor float

         , @maxname  char(30)

         , @devnmbr  numeric(5,0)

         , @devsize  numeric(8,0)       -- Mind devices can have x.5 MB's allocated !!!

         , @devused  numeric(8,0)

         , @devfree  numeric(8,0)

 

   CREATE TABLE #devices ( devname char(30)

                         , devnmbr numeric(5,0)

                         , devsize numeric(8,0)

                         , devused numeric(8,0)

                         , devfree numeric(8,0)

                         )

   IF @@error <> 0

   BEGIN

      PRINT "ERROR creating temp table #devices. Cannot proceed."

      RETURN 1

   END

 

   SELECT @mbfactor = low/4 FROM master..spt_values WHERE type = 'E' AND number = 1

 

   -- PRINT "@mbfactor = %1!", @mbfactor

 

   IF ( @devname IS NULL )

   BEGIN

      SELECT @devname = min(name)                       -- First device name

      FROM   master..sysdevices

      WHERE  cntrltype = 0

      AND    name NOT LIKE 'SYS%'                       -- Exclude SYSDEV devices

                                                        -- (dynamic archive mounts)

 

      SELECT @maxname = max(name)                       -- Last  device name

      FROM   master..sysdevices

      WHERE  cntrltype = 0

   END

 

  ELSE

      SELECT @maxname = @devname                        -- Only 1 devicename

 

   WHILE (@devname <= @maxname )

   BEGIN

      SELECT @devsize  = (high-low+1)/@mbfactor

      ,      @devnmbr  = vdevno                         -- ASE 15.x and above

      FROM   master..sysdevices

      WHERE  name      = @devname

 

      SELECT @devused  = ISNULL(sum(SU.size), 0.0)/@mbfactor

      FROM   master..sysusages  SU

      ,      master..sysdevices SD

      WHERE  SU.vdevno = SD.vdevno

      AND    SD.status & 2 = 2
      AND    SD.name   = @devname

 

      SELECT @devfree  = @devsize - @devused

 

      INSERT #devices

      VALUES ( @devname, @devnmbr, @devsize, @devused, @devfree )

 

      SELECT @devname  = min(name)                      -- Get NEXT device name

      FROM   master..sysdevices

      WHERE  name      > @devname

      AND    cntrltype = 0

   END

 

   -- --------------------------------------------------------------------------
   -- Show Free Space
   -- --------------------------------------------------------------------------

   SELECT 'Device name' = devname

        , 'Size_MB'     = str(devsize, 8,0)

        , 'Used_MB'     = str(devused, 8,0)

        , 'Free_MB'     = str(devfree, 8,0)

   FROM   #devices

   WHERE  devfree <> 0                  -- Only show devices with free space

   ORDER  BY 1

 

   PRINT ""

 

   -- --------------------------------------------------------------------------
   -- Using cursor to be able to show separator lines between devices
   -- --------------------------------------------------------------------------

 

   PRINT " Device_Name                    DB_name              Segmap Used_MB"

   PRINT " ------------------------------ -------------------- ------ --------"

 

   DECLARE @dbname char(20)

         , @segmap char(06)

         , @summry char(08)

 

   DECLARE devcursor CURSOR FOR SELECT devname

                                ,      devnmbr

                                FROM   #devices

                                ORDER  BY 1

 

   OPEN  devcursor

   FETCH devcursor INTO @devname, @devnmbr

 

   WHILE @@sqlstatus < 2

   BEGIN

      IF EXISTS ( SELECT 1 FROM master..sysusages WHERE vdevno = @devnmbr )

      BEGIN

         DECLARE db_cursor CURSOR FOR SELECT db_name(SU.dbid)

                                      ,      STR(SU.segmap, 6,0)

                                      ,      STR(SUM(SU.size)/@mbfactor, 8,0)

 

                                      FROM   master..sysdevices SD

                                      ,      master..sysusages  SU

 

                                      WHERE  SD.name   = @devname

                                      AND    SD.vdevno = @devnmbr

                                      AND    SD.vdevno = SU.vdevno

                                      GROUP  BY SD.name, SU.dbid, SU.segmap

                                      ORDER  BY 1,2,3

 

         OPEN  db_cursor

         FETCH db_cursor INTO @dbname, @segmap, @summry

 

         WHILE @@sqlstatus < 2

         BEGIN
            PRINT " %1! %2! %3! %4!", @devname, @dbname, @segmap, @summry

            FETCH db_cursor INTO @dbname, @segmap, @summry

         END

         CLOSE             db_cursor

         DEALLOCATE CURSOR db_cursor

      END

      ELSE

      BEGIN

         PRINT " %1! HAS NO DATABASE FRAGMENTS DEFINED.", @devname

      END

 

      PRINT " ------------------------------ -------------------- ------ --------"

      FETCH devcursor INTO @devname, @devnmbr

   END

   CLOSE  devcursor

END

RETURN 0

go

GRANT EXEC ON sp_devusage TO public

go

Filename:  sp_hogs.sql

Purpose:           Stored procedure to show processes consuming a lot of cpu ticks, io's and/or memory

 

USE sybsystemprocs
go

IF OBJECT_ID('sp_hogs') > 0 DROP PROC sp_hogs
go

CREATE PROC sp_hogs (@loginame varchar(30) = NULL)

AS

-- -----------------------------------------------------------------------------
-- sp_hogs
--
-- Display top 5 of worst individual's process information.

-- If no username supplied, returns info for all currently logged in processes.
-- -----------------------------------------------------------------------------

SET NOCOUNT ON

DECLARE @low      int, @high      int
,       @spidlow  int, @spidhigh  int

SELECT @low = 0, @high = 32767, @spidlow = 0, @spidhigh = 32767

IF @loginame IS NOT NULL
BEGIN

   SELECT @low = suser_id(@loginame), @high = suser_id(@loginame)

   IF @low IS NULL
   BEGIN

      IF @loginame LIKE "[0-9]%"
      BEGIN

         SELECT @spidlow  = convert(int, @loginame)

         ,      @spidhigh = convert(int, @loginame)

         ,      @low      = 0, @high = 32767

      END
      ELSE
      BEGIN

         PRINT "No login exists with the supplied name."

         RETURN 1

      END
   END
END

SET ROWCOUNT 5

SELECT '     CPU' =       STR( cpu,                           8)

,      '      io' =       STR( physical_io,                   8)

,          ' mem' =       STR( memusage,                      4)

,        '  spid' =            spid

,        Login    = substring( suser_name(suid),           1,20)

,        DBname   = substring( db_name(dbid),              1,14)

,        Hostname = substring( ISNULL( hostname, ipaddr),  1,15)

,        H_pid    = substring( ISNULL( hostprocess,  ""),  1,05)

,        Program  = substring( ISNULL( program_name, ""),  1,14)

--       Client   = substring( ISNULL( clientname,   ""),  1,10)

,        Command  = substring( cmd,                        1,16)

FROM   master.dbo.sysprocessesWHERE  suid >= @low

AND    suid <= @high

AND    spid >= @spidlow

AND    spid <= @spidhigh

AND    spid <> @@spid

AND    suser_name(suid) <> NULL

ORDER  BY CONVERT(int, cpu)         DESC

        , CONVERT(int, physical_io) DESC

        , CONVERT(int, memusage)    DESC

 

PRINT ''

SELECT '     cpu' =       STR( cpu,                           8)

,      '      IO' =       STR( physical_io,                   8)

,          ' mem' =       STR( memusage,                      4)

,        '  spid' =            spid

,        Login    = substring( suser_name(suid),           1,20)

,        DBname   = substring( db_name(dbid),              1,14)

,        Hostname = substring( ISNULL( hostname, ipaddr),  1,15)

,        H_pid    = substring( ISNULL( hostprocess,  ""),  1,05)

,        Program  = substring( ISNULL( program_name, ""),  1,14)

--       Client   = substring( ISNULL( clientname,   ""),  1,10)

,        Command  = substring( cmd,                        1,16)

FROM   master.dbo.sysprocesses

WHERE  suid >= @low

AND    suid <= @high

AND    spid >= @spidlow

AND    spid <= @spidhigh

AND    spid <> @@spid

AND    suser_name(suid) <> NULL

ORDER  BY CONVERT(int, physical_io) DESC

        , CONVERT(int, cpu)         DESC

        , CONVERT(int, memusage)    DESC

 

PRINT ''

SELECT '     cpu' =       STR( cpu,                           8)

,      '      io' =       STR( physical_io,                   8)

,          ' MEM' =       STR( memusage,                      4)

,        '  spid' =            spid

,        Login    = substring( suser_name(suid),           1,20)

,        DBname   = substring( db_name(dbid),              1,14)

,        Hostname = substring( ISNULL( hostname, ipaddr),  1,15)

,        H_pid    = substring( ISNULL( hostprocess,  ""),  1,05)

,        Program  = substring( ISNULL( program_name, ""),  1,14)

--       Client   = substring( ISNULL( clientname,   ""),  1,10)

,        Command  = substring( cmd,                        1,16)

FROM   master.dbo.sysprocesses

WHERE  suid >= @low

AND    suid <= @high

AND    spid >= @spidlow

AND    spid <= @spidhigh

AND    spid <> @@spid

AND    suser_name(suid) <> NULL

ORDER  BY CONVERT(int, memusage)    DESC

        , CONVERT(int, cpu)         DESC

        , CONVERT(int, physical_io) DESC

go

GRANT EXEC ON sp_hogs TO public

go

 

Filename:  sp_lockname.sql

Purpose:           Stored procedure to show lock information in readable format

 

USE sybsystemprocs
go

IF object_id('sp_lockname') > 0  DROP PROC sp_lockname
go

CREATE PROCEDURE sp_lockname ( @par1 varchar(30) = NULL ) -- par1 is spid or login_name

AS

--------------------------------------------------------------------------------

-- Shows locks in SQL Server with tablenames instead of table_id's.

--

-- Code taken from sp_lock with table_id's converted to table_names.

-- Also output layout is always fixed width.

--------------------------------------------------------------------------------

if @@trancount = 0

begin

   set transaction isolation level 1

   set chained off

end

 

declare @spid  int

      , @login varchar(30)

 

if ( patindex('%[a-z]%', lower(@par1)) ) > 0   -- parameter contains characters

begin

   select @login = @par1

end

else

begin

   select @spid = convert(int, @par1)

end

 

 

if @login IS NOT NULL                  -- Show the locks for given login.

begin

   select login      = convert(char(15), suser_name(suid))

        , spid       = str(l.spid,  04)

        , page       = str(page,    08)

        , locktype   = convert(char(15), name)

        , table_name = convert(char(20), object_name(l.id, l.dbid))

        , dbname     = convert(char(10), db_name(l.dbid))

        , cmd        = convert(char(15), cmd)

        , program    = convert(char(15), program_name)

     from master..syslocks l, master..spt_values v, master..sysprocesses p

    where l.type = v.number

      and v.type = "L"

      and p.spid = l.spid

      and p.spid <> @@spid

      and suser_name(p.suid) = @login

    order by l.spid, dbname, table_name, locktype, page

end

else

   if @spid is not NULL               -- Show the locks for given spid

   begin

      select login      = convert(char(15), suser_name(suid))

           , spid       = str(l.spid,  04)

           , page       = str(page,    08)

           , locktype   = convert(char(15), name)

           , table_name = convert(char(20), object_name(l.id, l.dbid))

           , dbname     = convert(char(10), db_name(l.dbid))

           , cmd        = convert(char(15), cmd)

           , program    = convert(char(15), program_name)

        from master..syslocks l, master..spt_values v, master..sysprocesses p

       where l.type = v.number

         and v.type = "L"

         and p.spid = l.spid

         and p.spid = @spid

         and p.spid <> @@spid

       order by l.spid, dbname, table_name, locktype, page

   end

 

   else                              -- No parameters, so show all the locks.

   begin

      select login      = convert(char(15), suser_name(suid))

           , spid       = str(l.spid,  04)

           , page       = str(page,    08)

           , locktype   = convert(char(15), name)

           , table_name = convert(char(20), object_name(l.id, l.dbid))

           , dbname     = convert(char(10), db_name(l.dbid))

           , cmd        = convert(char(15), cmd)

           , program    = convert(char(15), program_name)

        from master..syslocks l, master..spt_values v, master..sysprocesses p

       where l.type = v.number

         and v.type = "L"

         and p.spid = l.spid

         and p.spid <> @@spid

       order by l.spid, dbname, table_name, locktype, page
  end

 

return (0)

go

grant exec on sp_lockname to public

go

 

Filename:  sp_w.sql

Purpose:           Stored procedure to show process information (improved version of sp_who)

 

USE sybsystemprocs
go
IF OBJECT_ID('sp_w') > 0  DROP PROC sp_w
go
CREATE PROC sp_w ( @loginame varchar(30) = NULL )
AS
-- ---------------------------------------------------------------------------------------
-- Improved version of sp_who for ASE 12 & 15, with client and ipaddr info in sysprocesses
-- ---------------------------------------------------------------------------------------

DECLARE @low      int
,       @high     int
,       @spidlow  int
,       @spidhigh int

 

IF @@trancount = 0
BEGIN

   SET CHAINED OFF
END

SET TRANSACTION ISOLATION LEVEL 1
SET FLUSHMESSAGE ON
SET NOCOUNT      ON

SELECT @low      = 0
,      @high     = 32767
,      @spidlow  = 0
,      @spidhigh = 32767

IF        @loginame  IS NOT NULL
AND upper(@loginame)     <> 'ALL'
AND upper(@loginame)     <> 'X'
BEGIN

   SELECT @low  = suser_id(@loginame)
   ,      @high = suser_id(@loginame)

   IF @low IS NULL
   BEGIN
      IF @loginame LIKE "[0-9]%"        -- spid supplied
      BEGIN

         SELECT @low      = 0

         ,      @high     = 32767

         ,      @spidlow  = convert(int, @loginame)

         ,      @spidhigh = convert(int, @loginame)

      END
      ELSE
      BEGIN

         /* 17231, "No login with the specified name exists." */
         RAISERROR 17231
         RETURN
      END
   END
END

SELECT @@servername, convert(char(11), getdate(), 102) + convert(char(8), getdate(), 108)

SET NOCOUNT OFF

PRINT  ''
PRINT  ''
PRINT  ' ACTIVE processes by login, dbname, fid, spid:'
PRINT  ''


SELECT SPID     =       str( spid,                4)

,      FID      =       str( fid,                 4)

,      BLK      =       str( blocked,             4)

,      E        =       str( enginenum,           1)

,      Status   =            status

,      Login    = substring( suser_name(suid), 1,20)

,      DBname   = substring( db_name(dbid),    1,14)

,      Hostname = substring( ISNULL( hostname, ipaddr), 1,15)

,      H_pid    = substring( hostprocess,      1,05)

,      Program  = substring( program_name,     1,14)

,      Client   = substring( clientname,       1,10)

,      Command  = substring( substring( '> THIS PROCESS <', 1 - abs(sign(@@spid - spid)), 16)

                           + substring( cmd               ,     abs(sign(@@spid - spid)), 16)

                           , 1,16)

FROM   master..sysprocesses

WHERE  suid    >= @low     AND suid <= @high

AND    spid    >= @spidlow AND spid <= @spidhigh

AND    cmd     <> 'AWAITING COMMAND'

AND    suser_name(suid) <> NULL

ORDER  BY Login, DBname, FID, SPID

 

IF @loginame IS NOT NULL

BEGIN

   PRINT  ''

   PRINT  ' IDLE processes by login, dbname, fid, spid:'

   PRINT  ''

 

   SELECT SPID     =       str( spid,                4)

   ,      FID      =       str( fid,                 4)

   ,      BLK      =       str( blocked,             4)

   ,      E        =       str( enginenum,           1)

   ,      Status   =            status

   ,      Login    = substring( suser_name(suid), 1,20)

   ,      DBname   = substring( db_name(dbid),    1,14)

   ,      Hostname = substring( ISNULL( hostname, ipaddr), 1,15)

   ,      H_pid    = substring( hostprocess,      1,05)

   ,      Program  = substring( program_name,     1,14)

   ,      Client   = substring( clientname,       1,10)

   ,      Command  = substring( cmd,              1,16)

   FROM   master..sysprocesses

   WHERE  suid    >= @low     AND suid <= @high

   AND    spid    >= @spidlow AND spid <= @spidhigh

   AND    cmd      = 'AWAITING COMMAND'

   ORDER  BY Login, DBname, FID, SPID

END

RETURN 0

go

GRANT EXEC ON sp_w TO public

go


 

DOCUMENT ATTRIBUTES
Last Revised: May 18, 2009
Product: ASE/CIS, Adaptive Server Enterprise
Technical Topics: Database Admin
  
Business or Technical: Technical
Content Id: 1063658
Infotype: Technote
 
 
 

 
© Copyright 2010, Sybase Inc. - v 6.7 Home / Contact Us / Sitemap / Help / Feedback / Jobs / Legal / Privacy / Code of Ethics Follow Sybase