You are on page 1of 361

1

Edition

PROFESSIONAL DBA SERIES


Christopher Kempster

SQLServer 2000
fortheOracle DBA
SQL Server for the Oracle DBA

Dedicated to Veronica, a wonderful wife and a dearly loved friend;


and my great kids Carl and Cassidy.

Thanks to Raf Cammarano for editing and providing ongoing


encouragement to complete this so called “small” e-book.

Copyright  2003 Christopher Kempster


Perth, Western Australia

Copying, selling, duplication or reproduction of this work is expressly forbidden without the copyright holder’s written consent.
All scripts and examples are used at your own risk.

Spotlight on SQL Server is a registered trademark of Quest Software, Inc.


Diagnostic Manager is a registered trademark of NetIQ Corporation.
Microsoft Word 2000 is a registered trademark of the Microsoft Corporation.
SQL Server and SQL Server 2000 is a registered trademark of the Microsoft Corporation.
Oracle is a registrated trademark of the Oracle Corporation.
SQL Server Magazine Copyright 2002, Penton Media, all rights reserved.
SQL-Server-Performance.com website is copywritten by Brad M.McGehee.
Table of Contents
Moving MSDB and MODEL ................ 55
SQL SERVER ARCHITECTURE 101........ 1 Moving TEMPDB .............................. 57
OVERVIEW OF DATABASE INSTANCES ....1 GUI AND COMMAND LINE TOOLS ...... 58
Control Files and Data Dictionary ........4
Datafiles ..........................................5 WHAT IS INSTALLED? ............................. 58
Tablespaces .....................................6 ENTERPRISE MANAGER (OVERVIEW) ............ 59
Redo and Archived Logs .....................7 Registering Servers ......................... 59
Rollback Segments ............................7 Interface Overview .......................... 61
Init.ora ............................................8 Meta Data Repository ...................... 62
Environment Variables .......................8 Meta Data Repository Snap-In ....... 63
MEMORY STRUCTURES .........................9 Task Pad View ................................ 64
SGA (SQL Server Address Space)...... 11 Inserting NULL’s into Table Columns.. 65
Buffer Cache .................................. 12 DBVERIFY ......................................... 65
Redo Log Buffer (Log Cache) ............ 14 SVRMGRL ......................................... 65
Library Cache (Procedure Cache) ...... 15 SQL LOADER ....................................... 66
SQL SERVER CONNECTIONS ..................... 17 JAVA AND SQL SERVER ........................... 66
EXTENDED STORED PROCEDURES ............... 18 SQL TRACE ......................................... 67
CHECKPOINT ........................................ 18 QUERY ANALYSER (SQL*PLUS) ................. 68
BACKGROUND PROCESSES........................ 20 DATABASE CONFIG ASSISTANT / ORACLE ADMIN
STORAGE ENGINE .................................. 22 ASSISTANT ETC .................................... 68
Tablespaces ................................... 22 NET8 ASSISTANCE / SQLNET ................... 68
Blocks / PctUsed & PctFree / Extents / UTLBSTAT, UTLESTAT, STATSPACK ...... 69
Segments ...................................... 24 SRVCTL ............................................ 69
Free Space Management .................. 26 LOG MINER ......................................... 69
Fragmentation ................................ 30 ISQL ................................................ 69
Reporting on Fragmentation .......... 30 ISQL vs OSQL command line ............ 70
Resolving Fragmentation ............... 31
High Water Mark (HWM) .................. 33 BACKUP AND RECOVERY ................... 71
Segments ...................................... 35 BACKUP.............................................. 71
RELATIONAL ENGINE .............................. 35 Recovery Interval............................ 72
INSTALLATION ................................. 37 Recovery Models ............................. 73
Backup Devices............................... 74
EDITIONS AND VERSIONS ........................ 37 RMAN ............................................ 75
LICENSING SCHEMES .............................. 38 Database Maintenance Plans ............ 75
Alter licensing mode after install?...... 41 Data Dictionary Views (Media Sets,
BINARIES & INSTANCE INSTALLATION .......... 42 Backup Sets) .................................. 77
Service Account .............................. 43 Hot / Online (Full) Backups .............. 79
Encrypted File System (EFS) ............ 44 Differential Backups ........................ 81
Encrypted Database File IO (avg - Archived Log (Transaction Log) Backups
1min 10sec to create and populate) 45 .................................................... 82
RAID Set-up with SQL Server, Install Tablespace (Filegroup) Backups ........ 83
Issues, OFA.................................... 46 Moving DB &Transportable Tablespaces
Items to consider before installation .................................................... 84
(summary)..................................... 49 Some issues with MODEL and MSDB
Example Installation – Standard, databases ................................... 88
Developer or Enterprise Ed............... 50 Fixed dbid for system databases .... 88
MOVING YOUR SYSTEM DATABASES AFTER Scripting Databases......................... 89
INSTALLATION ...................................... 55 Backup control file to trace............... 91
Moving MASTER and Error Logs ........ 55 Verifying Backups ........................... 91
RECOVERY........................................... 92 TRACE FLAGS ..................................... 147
Killing User Connections and Stopping INDEXING ......................................... 150
Further Connects ............................ 92 Index Types .............................. 150
Using the GUI for Recovery .............. 93 Like Clause ................................ 151
Options - Leave database in non- Functions and Indexes ................ 152
operational state but able to restore Composite Indexes ..................... 152
additional logs ............................. 94 Indexed Views (Materialised Views)
Options – Using the Force restore ................................................ 152
over existing database option ........ 94 Covering Indexes ....................... 154
Restoring a databases backup history Index Skewing ........................... 155
from backup files ............................ 95 Index Statistics and Fragmentation
Restore cannot fit on disk................. 96 ................................................ 156
Restore uses “logical” names ............ 96 Heaps, Clustered Indexes and
RESTORATION BY EXAMPLE ....................... 97 Fragmentation ........................... 156
Restore Master Database ................. 97 Rebuilding Indexes ..................... 158
Restore MSDB and Model Databases.. 99 Performance Counters................. 158
Suspect Database ........................... 99 Index Management via Enterprise
Database is in “Loading” Mode ? ..... 100 Manager.................................... 159
Restore with file move ................... 100 Summary .................................. 159
Restore a specific File Group........... 101 DATABASE FILE IO STATS ...................... 160
Adding or Removing Data Files (affect WAIT STATISTICS................................ 160
on recovery)................................. 101 STATSPAK....................................... 161
Emergency Mode .......................... 102 GENERAL PERFORMANCE TIPS ................. 161
Restore Full Backup....................... 103 Server Configuration ..................... 161
Partial (stop at time) PITR Restore on a What can affect performance (not an
User Database .............................. 104 exhaustive list) ............................. 162
Corrupt Indexes (DBMS_REPAIR) .... 104 Collecting SQL Server Statistics ...... 163
Reinstall NORTHWIND and PUBS ..... 105 General DB Parameters, Settings and
Other Recovery Scenarios .............. 105 other DBA items ........................... 163
Scenario 1 - Lost TEMPDB Database Physical Database Design............... 164
................................................ 105 SQL and Developer Tips ................. 166
Scenario 2 - Rebuildm.exe......... 105 Backup and Recovery .................... 168
Scenario 4 - Disks lost, must restore CPU is a Bottleneck?...................... 168
all system and user databases from I/O is a Bottleneck?....................... 168
backup to new drive/file locations. 109 TASK MANAGER .................................. 169
COM+ ............................................ 169
TRANSACTIONS AND LOCKING ....... 110 Isolation level of COM+ components 171
ROLLBACK SEGMENTS & REDO LOGS ORACLE - Proxying your COM+ components ... 172
SUMMARY OF UNDO MANAGEMENT / ROLLBACK STORED PROCEDURES ........................... 172
SEGMENTS.......................................... 110 Using SET NOCOUNT ..................... 172
Oracle – Redo Logs ....................... 112 SUMMARY - TOP PERFORMANCE PROBLEMS .. 173
Oracle – Locking ........................... 113 HIGH AVAILABILITY ....................... 175
SQL Server - Undo & Redo Management
Architecture ................................. 114 CLUSTERING ...................................... 176
In Summary .............................. 117 Oracle RAC and Application Clustering
LOCKING & ISOLATION LEVELS ................ 118 .................................................. 176
TRANSACTIONS ................................... 121 SQL Server Clustering ................... 178
MONITORING LOCKING ISSUES ................ 122 Ongoing Cluster Administration .... 183
CONTROLLING LOCKS ........................... 124 NLBS (Web Farm Cluster) .............. 183
Detecting and dealing with Deadlocks CLB (Component Clustering) .......... 185
.................................................. 126 Microsoft Clustering - The Big Picture
Example Deadlock Trace ............. 128 .................................................. 185
FEDERATED DATABASES ........................ 187
PERFORMANCE TUNING .................. 130 LOG SHIPPING .................................... 189
TRACING (PROFILER) ............................ 130 Manual Log Shipping - Basic Example
Saving & Scripting Traces .............. 133 .................................................. 191
Index Tuning Wizard ..................... 134 ONLINE OBJECT REDEFINITION ................ 195
EXPLAIN PLAN .................................... 137 GLOBALISATION SERVICES (NLS) .. 196
BLACK BOX TRACING? .......................... 139
LATCH STATISTICS .............................. 140 ORACLE ARCHITECTURE ......................... 197
PAGE SPLITS...................................... 140 SQL SERVER ARCHITECTURE .................. 198
PERFORMANCE MONITOR (PERFMON.EXE).... 142
Collation – Installation (Server Level) Check object ownership ................. 253
.................................................. 202 User Lock Timeouts ....................... 253
Collation – Database ..................... 203 Transfer Logins between Servers .... 253
Collation – Table Column ............... 204 Change a Users Password .............. 254
Collation – Expressions and Variables Rename a Login ............................ 254
.................................................. 205 KILLING SESSIONS .............................. 254
INTERNATIONALLY AWARE APPLICATIONS .... 206 Orphaned “Sessions” ..................... 256
TEMPDB.......................................... 256
OLAP............................................... 207 INSTANCE UPTIME.............................. 257
TERMINOLOGY .................................... 207 RE-CREATING & AUTO-STARTING SERVICES 257
ADMINISTRATION ................................ 208 RAW PARTITIONS ................................ 258
Installation................................... 208 SQL*MAIL ........................................ 258
Administering from your client PC ... 210 AUTO-GROWTH AND SPACE MANAGEMENT
Migrating the repository ................. 211 TRACKING ......................................... 258
Storage Models and Connectivity..... 213 Automatic data file growth ............. 258
OLAP Databases......................... 213 Space Tracking ............................. 258
Cubes and Cube Storage Models .. 214 STATISTICS AND HISTOGRAMS ................ 259
OLAP Connectivity ...................... 214 Building and Maintaining Histograms 260
Security .................................... 214 Import and Export Statistics ........... 261
Example – Cell Level Security ...... 215 Re-collecting Statistics & Monitoring
ADO MD & DSO ................................ 217 Auto-Statistics Collection ............... 261
BACKUP............................................ 219 Updating Statistics ..................... 261
Monitoring Statistics ................... 261
SCRIPTS & SCHEDULED JOBS ......... 220 Controlling Stats Collection at the
Object Level ................................. 262
T-SQL ROUTINES ............................... 221
Analysing Indexes & Histograms
XP_CMDSHELL Example ................. 221
(collections) ................................. 262
DTS ............................................... 221
SYNONYMS ........................................ 264
ISQL / OSQL.................................... 222
SHRINKING DATABASE FILES .................. 264
VB SCRIPT ........................................ 222
SQL DMO ........................................ 267
VB / COM EXAMPLE ............................ 223
VB Example.................................. 267
MANAGING DATABASES.................. 226 VB Script Example (.vbs) ............... 267

DATABASE CHECKING ROUTINES .............. 226 SQL & T-SQL ................................... 268
LOG FILES (UDUMP, BDUMP) ............... 227
PL/SQL (T-SQL) ............................... 268
LINKED SERVERS (DATABASE LINKS) ........ 229
Comments and Statement End ....... 268
Example - Databases in the same
Understanding GO......................... 269
Instance ...................................... 231
Block Structure ............................. 270
Example - Connecting to an SQL Server
Declarations / Local Variables /
Instance ...................................... 231
Constants .................................... 270
Example - Connecting to an Oracle
Assigning values to variables & Create
Instance ...................................... 232
Table as....................................... 271
OPENQUERY, OPENROWSET,
Exception Handling (error handling) 272
OPENDATASOURCE ....................... 235
RAISEERROR and Error Messages ... 273
Remote Servers ............................ 236
Non-SQL Output ........................... 274
DTS PACKAGES .................................. 237
Cursors........................................ 275
DIAGRAMS (DATA MODEL DIAGRAMS) ....... 243
STATIC Cursors.......................... 277
Transferring Diagrams ................... 244
UTL_FILE (File IO)......................... 277
ROW CHAINING & MIGRATION ................. 245
Procedures/Functions/Packages ...... 278
TABLESPACE (FILE-GROUP) MANAGEMENT ... 245
User Defined Functions (UDF) ...... 278
PINNING TABLES ................................. 247
User defined Stored Procedures ... 279
TRIGGERS ......................................... 247
Versioning Stored Procedures ...... 280
CONSTRAINTS .................................... 248
Security & Ownership Issues........ 280
LONG RUNNING TRANSACTIONS ............... 248
Calling External Applications (command
SQL TIMEOUTS .................................. 249
shell)........................................... 281
RENAME DATABASE .............................. 249
DBMS_SQL................................... 282
USER MANAGEMENT ............................. 250
DBMS_RANDOM............................ 282
Login vs User................................ 250
DBMS_OUTPUT ............................. 283
Orphaned Logins ........................... 251
DBMS_MAIL, UTL_SMTP................. 283
Change DB Owner ......................... 252
DBMS_AQ .................................... 283
User Quotas & Account Expiry ........ 252
PSP, PL/SQL Web Toolkit................ 283
OPS$ Logins (OS Authentication) .... 252
DBMS_METADATA ......................... 283
Change Object Owner .................... 253
DBMS_JOB ................................... 284 OLE Automation ......................... 336
DBMS_LOB................................... 287 Registry Access .......................... 336
BFILE .......................................... 287 Other routines ........................... 336
Tables ......................................... 287 DATA TRANSFORMATION SERVICES ........... 337
User Defined (Inline) Functions....... 288 SYSTEM, OBJECT PRIVILEGES AND ROLES ... 337
Indexes ....................................... 289 Fixed Server Roles (Instance) ...... 339
SEQUENCES ....................................... 289 Fixed Server Roles (Database) ..... 339
What about UNIQUE IDENTIFIER? ... 292 User Defined Roles ..................... 340
BUILT IN FUNCTIONS ............................ 293 Object Privileges ........................ 340
Numeric Functions ........................ 293 AUDITING ......................................... 341
String Functions............................ 294 Application Auditing....................... 341
Date Functions.............................. 295 Profiler (trace) .............................. 344
SQL EXAMPLES WITH ORACLE COMPARISONS Instance level auditing................... 344
..................................................... 297 C2 Level Auditing .......................... 345
PARTITIONED TABLES ........................... 301 ENCRYPTION / OBFUSCATION OPTIONS ...... 345
PARALLEL QUERY ................................. 301 Networking Options ....................... 345
PARALLEL IO ..................................... 302 Encrypted File System ................... 345
SQL HINTS ....................................... 302 WITH ENCRYPTION option.............. 346
Example Hint ............................. 305 T-SQL .......................................... 347
DATA TYPES COMPARED ........................ 306
DYNAMIC SQL.................................... 309 INDEX............................................. 348
T-SQL (PL/SQL) OVERVIEW ................... 311
REFERENCES ................................... 352
NETWORKING SQL SERVER............. 313
LISTENER AND ODS ............................. 313
Multi-Protocol ............................... 315
Registry Entries ............................ 315
Client Network Utility..................... 316
ODS ............................................ 317
Tracing TCP/IP port issues.............. 317
List of Running Instances ............... 317
SSL OF SQL SERVER CONNECTIONS ......... 317
SQLOLEDB ...................................... 319
NETWORK MONITORING ........................ 320
SQLDiag ...................................... 322
MTS / ORACLE SHARED SERVER .............. 322
SECURITY ....................................... 323
SECURED INSTALLATION ........................ 323
LOGINS AND USERS ............................. 325
Authentication Modes .................... 325
BUILTIN/Administrator Login .......... 326
Using the SA login......................... 327
Duplexing a Login to Multiple Users . 327
Finding NULL Passwords................. 328
DBO Access .................................. 328
User Quota and Resource Restrictions
.................................................. 328
Password File................................ 328
Development Server Privileges ....... 328
Application Security – Connection
Strings & Authentication ................ 329
Authentication Example............... 330
Obtaining the DB Connection string
and Connecting to the Database... 331
Views and Stored Procedures.......... 333
Virtual Private Databases ............... 335
Label Security............................... 335
LOCKING DOWN EXTENDED AND SYSTEM
PROCEDURES ..................................... 335
Securing xp_cmdshell (OS Shell) .... 335
Securing xp_cmdshell (OS Shell) .... 336
1
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL Server Architecture 101

T
hroughout this chapter we will introduce you to the SQL Server Instance, the database and
core memory structures. The overview is reasonably thorough and where possible we will
drill through to the DBMS architecture, with some early examples of SQL and database
checking and consistency commands (DBCC).

In this and subsequent chapters, we will explore SQL Server 2000 and revisit some of the core
Oracle concepts to re-enforce the SQL Server equivalent technology (or lack of in some cases).
Please remember that we assume good working knowledge of the Oracle DBMS and the daily tasks
and challenges of the DBA; therefore, I don’t “beat around the bush” when explaining core
concepts or discuss at length syntax and semantics.

Please note that this ebook is not designed to be read from front to back but rather as a reference
guide to getting quick answers and where to look next.

OVERVIEW OF DATABASE INSTANCES


Before we drill into SQL Server, it is important that we step back for one moment and take a high-
level look at the Oracle Instance vs. the SQL Server Instance. First of all, the word “instance” and
“database” tend to be somewhat blurred in the SQL Server realm.

When describing Oracle, database is used to describe the physical files and instance as the memory
structures and processes to interact with the database (3). In SQL Server 2k an instance describes
a complete, near independent installation of SQL Server that includes:
exit.

1. Binaries and associated options (mandatory and optionally installed)

2. Windows Services and associated registry entries

3. System databases, their physical database files, log files and other example databases
associated with the instance.

In general, think of a SQL Server instance as a new installation of SQL Server. To support multiple
installations of SQL Server on the same server SQL Server 2k introduced named instances. This is
a great feature that effectively allows you to have, say, a SQL Server 2k instance running Service

1
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Pack 2 installed and other running Service Pack 1 on the same server. In context to Oracle, its like
having v8.1.5 and v8.1.6 running on the same server.

When we run multiple named instances, we call them “near” independent installations because
there are common files used by all. Some of which (at a high level) include:

ƒ COM (DLL’s)

ƒ Replication

ƒ Full text search

ƒ Directory service integration

ƒ Import OLEDB provider

ƒ Proxy message data source provider

ƒ Virtual device interface for backups

ƒ Distribution agent for replication (exe)

ƒ Log reader agent for replication (exe)

ƒ Tools

ƒ Enterprise Manager

ƒ Command line and GUI query analyser tools

ƒ BCP, Bulk Insert etc

ƒ DTS Run command line

ƒ Rebuild Master DB utility

ƒ Wizards

ƒ Books online (BOL)

ƒ SQL Templates

Each instance maintains what is left over, namely their data files and complete set of executable
files. Installation of named instances is covered in more depth later in the book.

It is important to remember that the MDAC (Microsoft Data Access Components, see
http://www.microsoft.com/data/whatcom.htm) version is not instance dependent, it is a server
wide API for all data access (ADO, OLE-DB, ODBC). Therefore, care must be taken between service
packs and even other SQL Server installations as they may inadvertently “break” existing products.

2
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Here is a summary of what we discussed.

Instance Binaries

Common files for all SQL Server 2k instances


(default and other named instances).

Default instance binaries. Named instances


will be something like MSSQL$MyInstance

Instance Service

Instance Databases (views within Enterprise Manager)

Default databases for all instances.


Master, Model, MSDB, Tempdb are system
databases, the Northwind and Pubs
databases are sample databases.

The above can also be shown as:

Instance & Address Space (oracle.exe) Instance & Address Space (sqlservr.exe)

Oracle DB SQL Server Instance

SYSTEM MASTER
Tablespace Database

Undo MSDB
Tablespace Database

Redo Logs Model


Database

TEMP Seg TEMPDB


tablespace Database

User User Database


tablespaces.. and trans logs

3
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

NOTE – When a new user database is created within an instance, its structure is modelled
from the MODEL system database. The DBA may customise selected properties of MODEL to
reflect these within any new database created.

Some named instance issues to be aware of:

1. 16 per server

2. One instantiation of an instance may only run in a multi-server failover cluster.

3. Don’t necessarily need to install the default (non-named) instance, can start with a named
instance right from the start.

4. Instance can have different service pack levels and languages and sort orders

5. One Enterprise Manager (EM) manages all SS2k instances, with also includes the server,
client network utilities and network data providers.

6. Each instance has its own sqlserver NT service and associated binaries and registry entries

7. Named instance services are titled MSSQL$InstanceName

If you were wondering, I use the product Process Explorer available at sysinternals.com to drill
down into NT processes running on the server and associated file IO activity. This and other
internals tools are excellent when exploring the inner workings of the NT/Windows operating
system and associated application processes.

NOTE – When a SQL Server DBA talks about “SQL”, some are actually referring to the
product “SQL Server” rather than the SQL language.

Control Files and Data Dictionary

The control file is critical to an Oracle instance, it stores a variety of information such as:

ƒ Database name

ƒ Timestamp of DB creation

ƒ Names and locations of database files and redo logs

ƒ Tablespace information

ƒ Archive Log history

ƒ Checkpoint information

ƒ and more..

4
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Within a SQL Server instance this information is a divided over a range of databases. The control
file is basically the master database. Without it the instance will not be able to start as it consists of
all the information about other system and user databases. The master database can also be
viewed the system tablespace to some degree, but it distributes its data dictionary objects with
other system and user databases (such as MSDB).

The data dictionary within SQL Server is a series of system tables with the sys prefix owned by the
internal user dbo (which, like the sys account, can never be removed). These reside in all user and
system databases within the primary file-group of the database. Because the dictionary is divided
over the databases, it is important that backups include all system databases (master, model,
msdb) at a minimum, just as you would backup the system tablespace, control files, rollback
segments within an Oracle instance.

In terms of users databases and dictionary objects, each user database includes a standard set of
sys tables using to track space allocation, objects created (views, tables, constraints etc) and basic
SCN (called LSN) and database file properties.

To work with the data dictionary, SQL Server provides the DBA with:

ƒ stored procedure calls (prefixed with sp_ in the master and msdb databases)

ƒ information schema views, special pre-summarised views to simplify direct querying of the
data dictionary sys tables.

ƒ DBCC routines (database consistency checking), special database checking, validation repair
routines called from query analyser or other command line utility

ƒ Extended stored procedure calls for externally developed routines for DB management

ƒ SQL-DMO, SQL programming interface and associated API

Search for “master database, information stored in system tables”, for an excellent overview of all
sys dictionary tables within the system and user databases within the BOL (SQL Server help books
online).

As there is only one master database, there is no concept of multiplexed control files.

Datafiles

An Oracle tablespace can have one of more data files. Within SQL Server, a file-group can have
one or more datafiles. Objects can span multiple data files in its file-group as they can do within
Oracle tablespace data files. If there is more than one data file per file-group, then SQL Server will
stripe (store) data evenly across each of the datafiles (based on the % free space within each data
file).

A database file (data file) also consists of a logical-filename, this includes all database files (data
and log files). The logical filename is referred to during alter database commands and recover to
make life easier when referring to database files rather than their physical name or when referring

5
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

to the files file-group is not appropriate. The logical name of a database file must be unique for the
database but other databases can use the same name if need be.

As with Oracle tablespace datafiles, SQL Server supports dynamic datafile growth by percentage or
by megabytes to a maximum or unlimited size.

An example is shown below:

ALTER DATABASE use [mydb]


DATAFILE ‘myfile.ora’ ALTER DATABASE [mydb] MODIFY
AUTOEXTEND ON FILE (NAME = N'mylogicalfilename’,
NEXT 20M FILENAME = ‘myfile.mdf',
MAXSIZE 2000M; MAXSIZE = 2000,
FILEGROWTH = 20)

ALTER DATABASE use [mydb]


DATAFILE ‘myfile.ora’ RESIZE 200M; ALTER DATABASE [mydb]
MODIFY FILE
(NAME = N'mylogicalfilename',
SIZE = 200)

Tablespaces

Are known in SQL Server as File-Groups, these are logically named structures that hold zero or
more physical database files (zero because you can actually create a group then add files later). All
databases have a default PRIMARY group that cannot be removed or renamed although the files
within it can be manipulated. The primary group will consist of one data file containing the
databases data dictionary objects (sys tables). Adding more file-groups is synonymous to adding
more tablespaces to an existing database in which tables and indexes can be stored within. At the
database level you can specify the default file group that will be used when a users object is created
without specifying the destination group. A database user cannot have a default file-group as a
property of being a database user.

It is important to remember that a databases transaction log data file for a database cannot be
allocated to file-group, only non-log files can.

The SYSTEM tablespace is the same as the MASTER database with a SQL Server instance. As with
Oracle, it must be online for the instance (and other user and system databases within the
instance) to successfully start. This database contains a variety of critical information about other
databases, logins, extended stored procedures etc.

An UNDO tablespace in 9i has replaced rollback segments in previous versions of Oracle. The
content or meaning of has not changed within Oracle, but architecturally the undo tablespace is
very different to “rollback segment” management when using automatic undo management.
Rollback and Redo is discussed in detail in the Transactions and Locking Chapter. The equivalent
SQL Server structure closest to the undo tablespace is the databases transaction log; one
transaction log database file exists at a minimum for all system and user databases.

6
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The TEMPORARY tablespace is equivalent to the tempdb system database that is automatically
recreated on instance start-up. The DBA cannot alter the user/login properties to specify the
temporary tablespace as with Oracle, it is automatically the tempdb and cannot be removed or
altered.

The read-only tablespaces are supported in SQL Server as read only file-groups. All user-defined
file-groups can be made read-only; the primary file group cannot be made read only. To make the
primary file-group read-only you, must make the entire database read only.

The DBA cannot Offline/Online a file-group like you can an Oracle tablespace.

There is no concept similar to dictionary or locally managed tablespaces within SQL Server. Each
database maintains its own storage properties via the sys tables in the primary filegroup of the
database, apart from that, all extent and block (pages) are uniform in size and can not be altered.

There is no equivalent to the transportable tablespace in SQL Server.

Redo and Archived Logs


As an Oracle database has two or more redo logs, so each database within a SQL Server instance
has a transaction log file that is further divided into smaller logical log files.

The transaction log file, depending on the databases recovery model, will continue to grow in size
until the database issues a backup transaction log statement for the database, or truncates the log
(point in time recovery will not be possible though).

The backing up of the log is the same as an archived redo log file. When we backup the log we can
send it direct to tape, a file share on another server (UNC path), to disk or via a named pipe; even
so, SQL Server does not provide any magic duplexing commands with the backup statement, so
the DBA needs to copy the backed up file to cover all bases.

A transaction log exists for each database within the instance and will hold:

ƒ modifications associated with incomplete transactions (pending a commit or rollback,


they are rolled back on database recovery)

ƒ modifications not yet flushed to disk (to be rolled forward on database recovery)

NOTE – Where possible, do NOT create more than one transaction log data file per database.
The log is sequential and there is little benefit from duplexing files over multiple spindles.
Multiple files can be a pain to administer and deal with in terms of re-attaching databases (see
Backup and Recovery) and managing log files sizes/shrinking.

Rollback Segments
There are no rollback segments in a SQL Server database. This concept is described in detail later
in this book. Because of this, writers can block readers and SQL Server’s locking mechanism is
much more complex that Oracle’s with a higher probability of locking problems with long running,

7
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

non-committed transactions. These issues can be resolved to some degree with using different
isolation levels on connection to the instance or per transactions, or using locking hints to enhance
database concurrency.

The transaction log acts as a data store for incomplete database transactions pending a commit or
rollback. Because of this it can be a type of rollback segment but from an Oracle definition, it is
very much limited in function.

Init.ora
There is no equivalent file in SQL Server, the closest we have is the internal settings within the
master system database via the sp_configure stored procedure command or set via Enterprise
Manager, the registry settings or the service startup parameters (sqlservr.exe).

Environment Variables
There is none, the registry controls all aspects of the SQL Server instance at this level.

8
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

MEMORY STRUCTURES
It is difficult to compare the two databases at a memory level. In some respects, both use the
same, proven, fundamental data structures and techniques for managing their memory structures.
The key difference here is that Oracle provides fine grain control over virtually all aspects of the
memory (and storage) engine, whereas SQL Server provides very little control. This is not
necessarily a bad thing in a majority of cases.

NOTE – Oracle has many complex memory structures that are configurable by the DBA, some
of which are not shown in this diagram on purpose. Read the summaries later for each
memory area for more information in context to Oracle.

System Global Area (SGA) Instance Address Space

Buffer Pool (Cache)


Block Buffers
Thread Stack Space

Dirty Buffer Write Queue (LRU) System Data Structures

Redo Log Buffer


Buffer Cache

Shared Pool
Library Cache
Procedure Cache

Dictionary Cache
Log Caches

Large Shared Pool


Connection Context

JAVA Shared Pool

SQL Server Net-LIB DLL’s

ODS Services Code

SQL Server Code

Distributed Query OLE-DB providers

Server Processes Memory Pool OLE Automation Objects


S000..S999
(PGA) Reserved Pool Extended Stored Procs

9
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The following provides a further drill down into the SQL Server architecture in terms of its threads
of execution and associated subsidiary engines. The key point here is that SQL Server runs with a
similar architecture to that of its underlying operating system, via a pool of threads that
asynchronously perform a variety of tasks on behalf of the DBMS and its related engine
components (storage, relational etc). Remembering this, we can see where DBWR, LGWR and
other Oracle processes are represented in the SQL Server framework. Each arrow/line typically
represents one or more of these worker threads (or fibres when DBA selects the option).

NOTE – The thread architecture for Win95 and 98 clients is not represented below.

SQL Server Instance {thread pool – priority 7 or 13 threads}


sqlservr.exe

Procedure Cache
Plan caching and reuse
Buffer Cache
Log Cache’s
Divided amongst Parse SQL
the worker Relational Optimise Plans
threads to async. Engine Exec Logical ops
scan, read and asynchronous Process DDL / other
write, a reading asynchronous logwriter Result formatting
thread wont affect worker threads threads
a subsequent
Manage files
scheduled write
Storage Build and read physical
Engine pages
checkpoint process Data buffer and IO
(buffers not added to Logging and recovery
free list) Utility functions
Free buffer list

scan & add


to free list 1 or more
schedule
threads per
writers
check free net-lib &
separate login
thread
allocated via
lazywriter {flush} {flush} UMS
thread

Net-Lib
Data Files T.Log Files
Providers

DBCC SQLPERF (UMSSTATS)


Gets statistics of SQL Servers thread
scheduler (UMS) running in native thread
or fibre mode, one scheduler per CPU.
The num runable is like the Processor
Queue Length performance counter. Num
workers equates to the number of worker
threads in the pool.

10
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

DBCC SQLPERF (THREADS)


Maps a system thread to a SQL Server
spid.

There is one UMS (user mode schedular) for each CPU. On a user connecting, a worker thread and
UMS schedular is allocated for the lifetime of the connection. Idle threads are allocated from the
pool of waiting threads, if all are busy the work requests are queued and allocated in a round-robin
scheme to threads. Use the command DBCC PSS to get UMS and thread details for a SPID:
DBCC PSS (0, 1) -- Where 1 is the spid

ExecutionContext Summary @0x1938A3A0


------------------------------------
ec_pss->pspid = 1 ecid = 0 ec_stat = 0x0
ec_stat2 = 0x0 ec_atomic = 0x0 pcurdb = 0
ec_lasterror = 0 ec_preverror = 0 ec_cpucur = 0
ec_cmderrs = 0 ec_timeslice = 100 ec_dbtable = 0x00000000
ec_reswait = 0xa0df60 ec_dbindex = -1
ec_umsContext->m_pSched->m_id (SchedulerId) = 0x1
ec_umsContext->m_workercntxt->m_id (threadId) = 0x47c

SGA (SQL Server Address Space)


The maximum address space for SQL Server is 2Gb, this can be extended via the /3GB switch in
the operating systems boot.ini file. Each instance of course has its own address space and
associated memory pool. Under Windows, you will only see the single, sqlservr.exe process
running under which a range of worker threads and other memory structures run. It is difficult to
get a good view of the underlying threads, but consider:

ƒ DBCC SQLPERF(UMSSTATS)

ƒ DBCC SQLPERF(THREADS)

ƒ Process Monitor and File Monitor found at www.sysinternals.com

The virtual address space that is made up of a global memory pool and a reserved working space
for the loading of extended stored procedures (in master database and start with xp_, they are
external DLL’s), OLE-DB data providers and automation objects instantiated via sp_OACreate. This
memory allocation is controlled via the –g parameter on instance startup and defaults to 128Mb.

The only real control the DBA has over memory is the –g parameter on instance start-up, the min
and max server memory option and the set working size option (both set via sp_configure when
the instance has started). These options are best managed via EM as shown in the dialog box
below:

11
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Dynamic memory control mode for


SQL Server, min and max memory.

Working set parameter, only set if the use a fixed


memory size parameter is being used. This locks in
memory as a working set for the win32 process.

Min memory per query. Minimum memory allocated per


SQL statement by the query processor to assist with
joins, sorts etc. Additional space can be acquired and
possibly allocated via the tempdb. Range of 512Kb to
2Gb.

Consider setting the maximum RAM by 10 to 20% less that the total server memory for dedicated
database servers.

NOTE – It is best practice to always control memory, setting a maximum that is appropriate
to the server configuration and the software running against it. See system table
master..syscurconfigs for current configuration options set.

Buffer Cache
SUMMARY

The buffer cache is a dynamic pool of buffers (8k pages) read from the physical data files and is
equivalent to the Oracle buffer cache. All subsequent reads/writes to physical data files occur via
the buffer cache. The cache itself consists of:

ƒ Linked list - to all free buffer pages

ƒ Each buffer page has a header that, among other things, contains a reference pointer that is
incremented when SQL statements reference the page. The increment may differ internally.

ƒ A value of zero on the reference counter marks the page as dirty. A write is then scheduled.

ƒ A global pool of worker threads via the user connection will manage writes and reads from
the cache.

The buffer will include data and index pages to complete all SQL from all databases hosted by the
instance.

The Oracle buffer cache goes many steps further than SQL Server in terms of configureability and
control, for example:

ƒ Default, Keep or Recycle pools (multiple buffer pools)

12
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ DBA controlled sizing

ƒ Multiple different block sized buffers

The SQL Server DBA has no control over the sizing or the reservation or division of the cache.

To locate pages not in the buffer cache hash bucket data structures are used. To view them, run
the following:

DBCC TRACEON(3604)
GO
DBCC BUFCOUNT
GO

SQL Server can also employ a read-ahead (RA, or parallel data scan) operation concurrently via
multiple threads for a single request. The optimiser will determine the requirement for the RA
operation and schedule the RA. This may be based on a count of pages missing in the database
buffer cache at the time and the sorted nature of the data itself in terms on proximity (especially
clustered indexes). The types of operations include table scans, index leaf-level scans, DBCC
statements and the updating of statistics.

The RA options have been removed in SQL Server 2k and the DBA can no longer control the RA
operation.

BUFFER CACHE MANAGEMENT

To drop all clean buffers from the pool, run the following database consistency checking command
via query analyser:

DBCC DROPCLEANBUFFERS

this requires the sysadmin instance permission.

The DBA can PIN objects into the cache as in Oracle via the DBCC PINTABLE command.

MONITORING PERFORMANCE

To monitor the hit ratio of the buffer cache, the best tool is Performance Monitor (perfmon.exe).
The counter is SQL Server : Buffer Manager, when there are multiple named instances the counter
will be something like MSSQL$<instance-name>: Buffer Manager. Other counters related to the
buffer manager include Free pages, Free List requests / sec and Free list empty/sec.

13
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Redo Log Buffer (Log Cache)

The redo log buffer in Oracle is a circular buffer of redo entries (which are any changes made
by any insert, delete, update, create, alter, drop statement) stored sequentially in the SGA
and controlled via the log buffer parameter. The background process lgwr writes the redo log
buffer entries to the current active online redo log file. It is important to understand that any
block change requires the creation of a redo log buffer record, lgwr will free space as need be
in the cache. A series of latches are used to manage this process:
a) redo copy
b) redo allocation
c) redo writing

The Oracle DBA subsequently needs to monitor the log buffer size and associated space
contention; then to a lesser degree latch contention.

In a SQL Server instance we have a single log cache memory structure for all databases within
the instance; there is a series of cache buffers for each database within the instance. For
every change made to a buffer cache page a log cache entry is made recording the change,
this must be written to the databases transaction log before the dirty buffer cache record is
written (flushed) to disk. This process is essential to ensure effective rollback during database
or user transaction recovery. Due to this write-ahead strategy of log-cache Æ transaction log
Æ buffer cache flush the transaction log is at times called the write-ahead log.

The SQL Server managed log-writer threads manage the flushing of data from the cache to disk.

NOTE - Non-logged operations are primarily controlled via the recovery model used for each
database within the instance.

MANAGEMENT OF

To view the contents of the transaction log (similar to that of log miner tools), drill into the
command:

DBCC LOG(3, TYPE=-1)

where 3 is the database ID

The key record operations include:

LOP_MODIFY_ROWS
LOP_INSERT_ROWS
LOP_DELETE_ROWS

14
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Library Cache (Procedure Cache)


The procedure cache under SQL Server v7 was part of the global pool of memory that was known
as the buffer cache. For the Oracle DBA this is confusing and somewhat strange, but with SQL
Server 2k the memory structure has been split away from the buffer cache and dynamically grows
and shrinks, as the DBMS deems necessary.

The procedure cache has many similar elements to that of the library and dictionary cache
combined within Oracle. The query processor (part of the relational engine that parses, compiles,
optimises and manages the submitted statement) will develop the necessary plan and return it for
execution; the plan and associated data structures are submitted to the procedure cache to
complete the call.

The different types of cache object include:

ƒ Compiled plan

ƒ Executable plan

ƒ Parse Tree

ƒ Cursor Parse Tree

ƒ Extended Stored Procedure

This can be further broken down to:

ƒ Adhoc SQL Plans

ƒ Prepared SQL Plans

ƒ Stored procedure

ƒ Replication procedure plans

ƒ Trigger

ƒ Views

ƒ Default

ƒ User table

ƒ System table

ƒ Check constraint

ƒ Rules

15
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

A worker thread is allocated to manage concurrent procedure cache operations. Where possible,
only one copy of a plan is stored at any one time. This enforces serialisation (not at all times) of
the compilation process and is managed via compilation locks. The Microsoft support document ID
Q263889 provides a good explanation of such locks and compile blocking, primarily dealing with
stored procedures.

NOTE – See the section on “Dynamic SQL” for more information about caching plans.

MONITORING

To get some general buffer cache statistics, use the following command.

DBCC PROCCACHE

The DBA may also consider the undocumented commands:

DBCC MEMORYSTATUS
and DBCC MEMUSAGE

MANAGEMENT OF

To flush the procedure cache globally for all databases in the instance, run the DBCC command:

DBCC FREEPROCCACHE

To flush the procedure cache for a specific database in the instance (where 3 is the database ID
from sysdatabases in the master database):

DBCC FLUSHPROCINDB(3)

Do a before and after check in the master database dictionary table – syscacheobjects, to verify the
affect of the routine. Be careful with these commands especially on your long running production
server. You will effectively force the once “warm” SQL Server procedure cache to be cleared and all
this will undoubtedly result in a degradation of performance for some time whilst plans are re-
cached.

You can force the recompilation of stored procedures the next time its run via the sp_recompile
system stored procedure. The create procedure command also includes the option RECOMPILE to
prevent the caching of the execution plan.

MONITORING PERFORMANCE

Utilise the NT performance monitor and the counter “SQL Server : Cache Manager Object” and the
items “Procedure Cache [Hit Ratio (cache hits vs. lookups), Pages (#8k pages in use), Object
Counts (#cache objects)” . The counter data is also available in master..sysperfinfo.

16
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The 20 largest procedures in the cache can be monitored via the command below and can be used
to predict future space requirements:

DBCC MEMUSAGE

To view the contents of the procedure cache, query the table master..syscacheobjects table in the
master database. Here we find a breakdown of cache objects by type (eg. Executable Plan,
Extended Proc, Parse Tree, Compiled Plan for example). Some of the core columns are:
pagesused, usecounts, refcounts and of course sql (being cached).

Third party tools, like Diagnostic Manager from NetIQ, provide cache hit statistics with a hit ratio
breakdown per cache object type over time.

SQL Server Connections


Each database connection is managed via a worker thread no matter the underlying DB-Library
provider. In SQL Server, each connection is through a database instance login, which defines
instance wide privileges, language and other basic properties for the associated process (SPID)
managed via a worker thread. The connection itself is controlled via the UMS (user mode
schedular) as described in the Memory Structures section.

The properties of each SPID can be monitored via the sp_who and sp_who2 stored procedures or
by querying the master..sysprocesses table.

The DBA determines which of the databases within the instance the login can access, these are
called database users; as the login to user mapping exists separately for each instance database
with their own database level privileges (i.e. 1 login to many database users within the instance).

The sysprocesses table has a variety of information that the DBA may be interested in, namely the
ECID (execution context ID in which threads are running under for the SPID, KPID (current NT
thread managing the SPID), CMD (command being executed) and much more. Such information
may be present in the server error logs on occasions.

In terms of memory usage, SQL Server documentation is reasonable scarce in detailing the
sequence of events (although you could probably guesstimate it) and associated memory
structures. Generally, each connection will take a minimum of 12Kb + (3 x TDS Network Packet
Size), the TDS packet being 4Kb by default (see master..sysconfigures where config = 505 for
runtime value). The packet size can be set via the network packet size database option or via EM
via Tools Æ Options Æ Advanced.

The number simultaneous connections accepted can be controlled via the maximum concurrent
user connections property. Select properties for the instance and select the connections tab. The
DBA can check the value via select @@MAX_CONNECTIONS.

With SQL Server 2k, we can programmatically add up to 128 bytes of binary data to the current
session (connection). The context data remains accessible to all SQL for the session/connection.
The context_info column can be queried in the master..sysprocesses table to retrieve the data for
the SPID. To set the binary data in T-SQL code, here is an example:

17
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

DECLARE @contextdata varbinary(128)


SET @contextdata = CAST( 0x10 AS varbinary(128) )
SET CONTEXT_INFO @contextdata

select context_info
from master..sysprocesses
where spid = @@SPID

-- Value set is..


0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000

Extended Stored Procedures


Extended stored procedures are DLL’s written via the ODS (open data services) API (typically via
C++). The associated stored procedure in the master database is a wrapper to the underlying DLL
that is loaded and run in the same address space of SQL Server (the calling process).

The wrapper T-SQL stored procedure is like any other stored procedure in terms of calling it. The
object is referred to in the master..sysobjects table and they can be managed via:

ƒ sp_helpextendedproc

ƒ sp_dropextendedproc

ƒ sp_addextendedproc

ƒ sp_addextendedproperty

ƒ select * from ::fn_listextendedproperty

See Microsoft Support Doc# Q190987 for a great summary of extended procedures albeit with a
lack of example code.

Checkpoint
Within the Oracle DBMS, a checkpoint is a database event that synchronises altered data blocks in
the buffer cache with the physical data files. The DBWR process on certain conditions, such as
every 3 seconds, on a redo log switch or how full the buffer cache is with committed dirty buffers,
manages the write event. The CKPT process will update the control file and data files to indicate
the last completed checkpoint with the SCN (system change number). In older versions of Oracle
the LWGR would perform job of the CKPT process unless the DBA overrides the option with the
checkpoint_process start-up parameter.

The Oracle DBA has a lot of control of the checkpoint process; it’s timing and monitoring
performance. Even so, many of these parameters are rarely understood and at times can severely
impact performance.

18
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

It is not too surprising that fundamentally, a SQL Server checkpoint (in theory) is the same as
Oracle in that both are events that synchronise altered database blocks and log files in the buffer
and log caches with the physical data files. In saying that, remember the key differences in redo
logs and server processes between the architectures.

The checkpoint operation itself results in a flush of dirty data and log pages, the databases within
each instance checkpoint separately, maintaining their own last SCN (LSN in SQL Server) for
recovery. The checkpoint will:

ƒ write to the transaction log file (redo and rollback segment in Oracle) marking the start of
the checkpoint

ƒ Write LSN to the database boot page, begin recording information about the checkpoint in a
chain of log entries.

ƒ Records the minimum LSN (MinLSN), being the LSN of the first log record to complete a
database recovery

ƒ Record all outstanding and active transactions

ƒ Remove all virtual log records in the transaction log before the MinLSN (simply recovery
model, backup log command will have the same affect, also called archived redo logs)

ƒ Writes dirty data buffers to disk

ƒ Writes log entries marking end of checkpoint

Automatic checkpoints occur:

ƒ based on the recovery interval parameter and the number of associated log entries to fulfil
the parameters setting.

ƒ Database transaction log becomes >=70% full

ƒ Result of a manual CHECKPOINT

ƒ Selected DBCC commands are run

ƒ Backup command issued

ƒ Instance shutdown, offline database, read-only the database.

ƒ NT service stopped

The DBA can control the recovery interval (in seconds) parameter for each database within the
instance. The DBA can also force a checkpoint for a specific database via:

use mydb
CHECKPOINT

19
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

This command is available to the syadmin, db_owner and db_backupoperator privileged server and
database roles.

Background Processes

An Oracle instance is implemented as a single process, namely oracle.exe, under which the
background processes, namely pmon, dbwN, lgwr, ckpt, smon, reco run as threads. The oracle.exe
process corresponds to an NT service that is typically named OracleServiceSID.

NOTE – Get the Oracle thread details by querying v$process, v$session, v$bgprocess over
the addr and paddr columns.

The threads themselves can vary depending on the installation, i.e. if clustering or replication
services are used. Some of the common ones include:

Thread Description SQL Server


(background process) Equivalent
Pmon Process monitor individual worker threads
(UMS managed)

DbwN Database Writer individual worker threads

Lgwr Log Writer Lazywriter thread and individual


worker threads
Ckpt Checkpoint individual worker threads.
Smon System Monitor individual worker threads.
Reco Recovery individual worker threads.

In the SQL Server world, a SQL Server instance also runs under a single process sqlservr.exe with a
number of worker threads. These threads manage (not a definitive list):

ƒ each database connection

ƒ pooled if need be under heavy load

ƒ scanning the buffer cache, reading pages into cache, writing dirty buffers, populating free
buffer list

ƒ scheduled asynchronously

ƒ flushing log cache entries to disk

ƒ parsing, compiling and executing plans

Selecting rows from master..sysprocesses, you will see a variety of system processes running
against the instance, some of which are managers of the individual worker threads. Some
examples are:

20
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

LAZY WRITER

LOG WRITER1

LOCK MONITOR – thread level lock monitoring exists in SQL Server 2k

SIGNAL HANDLER

TASK MANAGER

CHECKPOINT SLEEP

These threads utilise a common memory area (stack) within the SQL Server instance address
space.

The worker thread is controlled by the configuration parameter max worker threads. The default
is 255.

Each thread is assigned a schedular (see DBCC SQLPERF (UMSSTATS) ). The wait state of worker
threads assigned to a UMS schedular is logged in the SQL Server error log and you get a thread
starvation error message if all UMS threads are in a wait state. Remember that there is one UMS
schedular for each CPU, the value of max worker threads parameter is evenly divided among the
UMS schedular(s). Each connection (SPID) is allocated to a thread linked to a UMS that never
changes throughout the life of the connection. The idle worker threads are allocated to incoming
tasks as need be, queuing requests appropriately whilst worker threads are made available. See
Q262973 for a good overview.

REMEMBER – Each individual database within the instance does not have a separate global
pool of worker threads.

21
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Storage Engine
This section covers a variety of areas related to the Storage Engine, namely:

ƒ tablespaces (file-groups)

ƒ Redo logs, archived logs and rollback segments

ƒ Blocks, extents, pctused and pctfree

ƒ Segments

ƒ Space management

Tablespaces
Each database within SQL Server has a minimum requirement of:

one primary filegroup – and its associate data file

one transaction log file (logs are not associated with file groups)

A filegroup is the logical name for a tablespace. One file-group can consist of zero or more physical
database files. The transaction log file (redo log) is dedicated to the database and does not have
the concept of filegroups and therefore logical names, it is simply a redo/rollback log with a logical
and physical file name that is used for transaction management. The general extension naming
conventions for database files are:

.mdf master data file

.ndf next data file (for any other files created for the database)

.ldf transaction log file

The logical name is a unique name that will identify the file within the file-group. I like to use it to
identify the general contents of the file within the file-group to simplify recovery, for example
MYDB_DATA or MYDB_AUDIT.

It is important to remember that a file-group (tablespace) with two or more database files causes
SQL Server to stripe writes over the files based on the percentage of free space available within
each. Depending on your application this may provide a performance enhancement as SQL Server
creates a new IO thread for each file. This is not the case though with transaction log files which
are sequential. Best practice states that where possible have one and only one database file per
file-group.

22
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Here is an example create database statement:

CREATE DATABASE [MyDB]


ON PRIMARY ( Part of the SYSTEM
NAME = N'MyDB_System', tablespace for the user
FILENAME = N'e:\dbdata\MyDB\MyDB_System_Data.MDF', database.
SIZE = 1,
FILEGROWTH = 10%),
FILEGROUP DATA01 (
User defined
NAME = N'MyDB_Data01', tablespace for our
FILENAME = N' e:\dbdata\MyDB\MyDB_Data01.NDF' , table objects
SIZE = 1,
FILEGROWTH = 10%),
FILEGROUP INDEX01 (
NAME = N'MyDB_Index01',
FILENAME = N' e:\dbdata\MyDB\MyDB_Index01.NDF' , User defined
tablespace for our
SIZE = 1, index objects
FILEGROWTH = 10%),
LOG ON (
NAME = N'MyDB_TransLog01', Redo / Rollback
FILENAME = N' f:\dblog\MyDB\MyDB_TransLog.LDF', Segment tablespace
SIZE = 1,
FILEGROWTH = 10%)

NOTE – our temporary tablespace is the tempdb database and is shared by all databases.

Database creation is discussed in detail later in this book. Take careful note of the syntax, if you
use Enterprise Manager it will use the alter database statement to add any files other than the
primary file-group and the transaction log, rather than doing it all in one statement.

The DBA can specify the file-group in which database objects are created. By default they will be
created in the primary filegroup. Only tables, materialised views (indexed views) and indexes can
be stored to a specific file-group via the ON clause, eg:

CREATE TABLE mytable


(mycol1 integer) ON DATA01

It is important to understand that file groups are logical structures, they can be created
independently with no datafiles in them (see alter database command) and physical files can be
added or removed later. A file-group cannot be removed until all of its data files are removed.
Also, removing a single file, even if it’s the only file in the filegroup, does not mean the file-group is
dropped (this is not the case via EM). Use the alter database <mydb> remove filegroup
<logicalname> command. The primary file-group (default) cannot be removed.

SQL Server will automatically remove the physical data files when a database file is dropped. So
long as there is no user objects in the data file or in the case where the file is a transaction log file,
there are no transactions, the DBA can remove the file. See the stored procedure commands
sp_dbremove (deletes a database), sp_detach_db (removes database from instance but retains
files, preferred method), alter database <mydb> remove file <logical-name>.

23
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

A file-group can be made the default group for user objects. Best practice typically states that the
DBA creates additional file-groups (data, index) and does not use the default PRIMARY filegroup
that holds all the sys tables (mini data dictionary) for the database. Use the command alter
database <mydb> modify filegroup <logicalname> default.

We can specify the default operating system location of filegroup files as we can do with Oracle and
the db_create_file_dest parameter in 9i. The parameters in SQL Server are very basic and covers
data and log files for new user databases at an instance level. These entries are actually stored in
the registry for the instance and can be altered via Enterprise Manager (right click properties for the
instance and choose the Database Settings tab) or via the extended stored procedure (xp_routine
reside in the master database only) command:

exec xp_instance_regwrite
'HKEY_LOCAL_MACHINE',N'Software\Microsoft\MSSQLServer\MSSQLServer',N'DefaultData',REG_SZ,N'
E:\SQLServerData\'

SQL Server will not name the files for you or let you overwrite existing data files on a create
database statement. When restoring though, you can force an overwrite of existing files if need be.

For a new database (includes 1 data file for the primary file group and 1 transaction log), SQL
Server will call them:

<db-name>_Data eg. mydb_Data, file extension is .MDF to default data dir

<db-name>_Log eg. mydb_Log, file extension is .LDF to default log dir

I tend to call these:

<instance-name>_<db-name>_SYSTEM

<instance-name>_<db-name>_LOG01

If it’s the default instance then leave <instance-name> blank. I use 01 to 99 to ID the file-number
in the group. Good naming standards can assist the DBA in emergency recovery scenarios.

There is no reason why you cannot use the OFM (Oracle File Management) and associated OFA
(Oracle Flexible Architecture) naming conventions for files with SQL Server (it wont pre-empt you
anyhow so its good to stick with the conventions).

NOTE – SQL Server has no concept of Partitioning as in Oracle or transportable tablespaces.


There is not such thing as dictionary managed or locally managed tablespaces (file-groups) as
such, the space allocation pages are stored in the headers and throughout the physical
database files themselves.

Blocks / PctUsed & PctFree / Extents / Segments


In Oracle, we have the logical allocation of space based on blocks Æ extents Æ segments, with
blocks being the finest level of granularity for storage. Oracle allows the DBA to specify different

24
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

block sizes for each tablespace (up to 5 standard sizes in 9i) to cater for different storage
characteristics of objects. Earlier versions of Oracle allow the block size to be set once on the
databases creation, even so, it is completely user defined. The set block (page) size for SQL
Server is 8k, you cannot alter this, so we have no DB_BLOCK_SIZE parameters of at the database
or file-group level.

FACT – SQL Server does not support multiple block sizes or variable extents.

Oracle 9i - Block SQL Server 2k - Page

Header
Header (96k)
84 to
107k Table Directory
Pointer to
Row Directory text data
Row data
where
appropriate

Row data
fillfactor
(pctused)

Row offset
pointers to
There are eight different page types in SQL Server : physical data
rows

ƒ data

ƒ index

ƒ text/image

ƒ global and secondary allocation map – what extents (64k contiguous) are allocation

ƒ page free space – information about page free space

ƒ index allocation map – extent information about index allocation

ƒ bulk change map – lists extents modified from bulk operations since last log backup

ƒ differential change map - extents modified since last backup database command

NOTE - Row offset table entries start at end of page, 1 entry per row, in table entries are in
reverse sequence of rows in the page.

25
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

In order to view page structural information:

dbcc traceon( 3604)

dbcc page( <dbid>, <page#>, [print opt], [cache], [logical])

dbcc traceoff( 3604)

NOTE - DBCC Page is an undocumented command.

The fillfactor option is used in place of pctused in Oracle. You cannot use this option in create table
command though, it is only used when indexes (clustered or non-clustered) are created. When
DBA’s of SQLServer talk about defragmentation, it is usually in context with indexes and rebuilding
them to resolve storage issue and page splitting. The default fill factor is zero, this is similar to
100% but with space for one record left at the higher level of the index nodes.

As a clustered index defines the storage of the table, the option fillfactor has a key influence over
the leaf (actual data) pages and the most affect with subsequent inserts or updates against the
segment.

On top of fillfactor, the DBA can also specify pad_index. This option can only be used in
conjunction with fillfactor and specifies the space to leave available at all non-leaf nodes (called
intermediate pages) of the index. The pad_index value is internally set by SQL Server and is based
on the value specified by fillfactor.

Since SQL Server has fixed page sizes the extent size is also fixed at 64k (8x8k pages) as is
contiguous in its storage. This is the smallest IO call SQL Server will make. The idea of the DBA
pre-allocating extents to objects or change extent size is non-existent in SQL Server.

The DBMS has the concept of uniform and mixed extents, this affects the allocation of space to
segments. A uniform extent is one whose pages are allocated to a single segment. A mixed
extent means its 8 pages may be shared by a variety of segment pages. SQL Server will allocate
space to segments (tables/index etc) at a page level, if, during space allocation, the DBMS
determines that an entire segments mixed page allocation can fill an extent, then SQL Server will
allocate (reserve) uniform extents for the object rather than individual pages. See free space
management next for more information.

Free Space Management


Each Oracle segment includes a free list that is implicitly allocated at the segments creation time.
This is made up of a common pool (master) free list of blocks containing free space for the extents
allocated to the segment and each subsequent extent allocated to the segment as the segments
size increases. On top of this and to reduce master free list contention, a process free list is
explicitly created when the DBA specifies the FREELISTS parameter on a create/alter table/index
statement. This parameter effectively allows the DBA to partition the free list to improve
applications with a large number of concurrent transactions.

It is worth mentioning that in Oracles’ locally managed tablespace, the tablespace manages its own
extents via a bitmap structure for each datafile to track free or used blocks. As the uniform extents

26
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

are allocated and deallocated the bitmap entries for the associated blocks are also altered. On top
of this, there is no requirement for coalescing free extents to consolidate fragmented free space as
all extents are uniform in size (unlike dictionary managed tablespaces).In SQL Server, “free space
management” in terms of a ‘free-list’ entries consists of two page types:

ƒ GAM – global allocation map page

ƒ Tracks extent allocation

ƒ 1 x GAM = 64k extents (4Gb data)

ƒ One bit for each extent

ƒ 1 = free, 0 = allocated

ƒ SGAM – shared global allocation map page

ƒ Tracks those extents that have mixed pages and have at least one unused page

ƒ 1 x SGAM = 64k extents (4Gb data)

ƒ 1 = extent is mixed and has free pages

ƒ 0 = not used as mixed, or, is a mixed extent whose pages are all in use.

These pages, typically found after the file-header pages are used by SQL Server for extent
management for each data file (not including transaction log files). To complete free space
management we also have PFS pages.

A PFS (page free space) page records individual page allocations within the data file. The page
itself is a bitmap structure similar to the GAM and SGAM but only covers 8000 pages at a time. The
value of the bit denotes the percentage full within the pages for an extent, for example:

Empty
1 - 50%
51 - 80%
81 - 95%
96 - 100%

The PFS bitmap is constructed as extents are allocated.

NOTE – read IO occurs in 64Kb chunks (extent size).

Finally, we need to discuss IAM’s (Index Allocation Maps). These are critical as they map the
extents in a database file used by the heaps (non-indexes tables), indexes (including clustered
indexed tables) and blob objects (ntext, image, text pages). Each object has at least one IAM so
long as:

ƒ the object has data allocated

27
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ the object did have data, but it was “deleted” rather than truncated.

The IAM’s are linear linked lists and are scattered throughout the data file as the objects within it
acquire space. If the file-group has more than one data file then remember that storage will be
allocated evenly over the data files based on the total % free space in the data files, therefore IAM
linked lists will span the physical data files within the logical file-group.

NOTE – IAM, PFS and other pages will be bought into the buffer cache along with other
standard page types holding row and index data.

The IAM and PFS pages are used to locate pages with enough free space to hold incoming rows.
The IAM’s are used to locate the extents for the object, whilst the PFS is used to locate page free
space. Necessary reallocation of extents (mixed to uniform) and subsequent acquisition of new
extents is via the GAM and SGAM pages.

file-group data-file (1 or more files per file-group)

File PFS GAM SGAM BCM DCM IAM IAM


Hdr

All 8k pages,
64k extents (not sysindexes entry for all
shown in diagram) objects to first IAM

BCM (bulk changed map)


DCM (differential changed map)

We can view the allocation of space via sp_spaceused or dbcc showcontig. With this the DBA
can see how a tables space allocation moves from mixed extents to the reservation of uniform
extents to the object. The following example was adapted from the work of Kalen Delaney
and her classic articles from SQLMag.com:

create table largerow (a int identity,b char(8000) )

As we insert rows (row#), and execute the sp_spaceused procedure we get the following results:

exec sp_spaceused largerow, @updateusage = true

28
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Row Reversed Data Index Unused Notes


count (Kb) (Kb) (Kb) (Kb)
0 0 0 0 0
1 16 8 8 0 Plus one page for IAM
2 24 16 8 0
3 32 24 8 0
4 40 32 8 0
5 48 40 8 0
6 56 48 8 0
7 64 56 8 0
8 72 64 8 0
9 136 72 8 56 Uniform extent allocated
10 136 80 8 48
17 200 136 8 56 All are uniform extents

NOTE – when you create a table with no indexes, an entry is placed in sysobjects and then
sysindexes for the table, the sysindexes entry record consists of an IAM binary entry pointing
to the first IAM for the object. With no data the entry is 0x000000000, as data is entered the
first IAM is allocated. If you “delete from” the table, the IAM entry remains and sp_spaceused
reports the same space utilisation!, but a truncate will clear the IAM entry altogether and
associated other GSAM, GAM pages therefore returning those pages/extents quickly back to
the storage engine.

29
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Fragmentation
Fragmentation occurs at a variety of levels with DBMS’s and seems to be one of those ongoing
struggles for the DBA to resolve. In Oracle, fragmentation of segments is a classic problem,
occurring primarily where many segments with different growth characteristics share a tablespace.
This as been addressed with locally managed tablespaces and fixed extent sizes for segments. In
SQL Server as we have seen in previous examples, the allocation of space occurs in the form of a
mixed extent then reserving uniform extents (64k - 8 contiguous pages). All this said, we still
have the following issues in both databases:

ƒ physical file fragmentation (OS fragmentation)

ƒ shutdown instance and defragment at the OS level.

ƒ distributed extent fragmentation (honeycombing)

ƒ page (block) fragmentation

ƒ page row fragmentation (a non issue)

In SQL Server, the only way to resolve honeycombing object extents is via:

ƒ BCP out data (or copy to another database), script foreign keys, drop foreign keys, truncate
tables, reimport data, enable keys

ƒ Backup and Restore

ƒ For clustered indexed tables only – DBCC REINDEX or DBCC INDEXDEFRAG or drop and re-
create the clustered index (can be problematic if a primary key constraint).

The DBA can view the fragmentation of its indexes via DBCC SHOWCONTIG, which divides the
fragmentation into:

logical scan fragmentation

extent scan fragmentation

Be warned that for SHOWCONTIG to display accurate figures you may need to re-run DBCC
UPDATEUSAGE and then possibly try shrinking the database. For some strange reason statistics
used by SHOWCONTIG can become “out of date”, causing no end of confusion for the DBA.

For heaps (non-clustered indexes), space is not automatically added at the end of the structure, the
PFS will be searched for free space for the record and inserted appropriately. Therefore, a table
with a sequenced primary key that is also experiencing heavy deletions can have is rows dispersed
throughout its pre-allocated extents.

Reporting on Fragmentation

Use the command DBCC SHOWCONTIG to report on a table or indexes fragmentation. When
writing scripts to track fragmentation over time, consider this command:

30
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

INSERT INTO msdb..dba_fraghistory (<column list here>)


DBCC SHOWCONTIG (21575115, 2) WITH TABLERESULTS, NO_INFOMSGS

Loop for all user objects (sysobjects) in the current database and run the above into our
custom created fragmentation history table msdb..dba_fraghistory. An example of an indexes
fragmentation summary is shown below:

dbcc showcontig ('enrolment')

DBCC SHOWCONTIG scanning 'enrolment' table...


Table: 'enrolment' (1903397900); index ID: 0, database ID: 5
TABLE level scan performed.
- Pages Scanned................................: 909
- Extents Scanned..............................: 166
- Extent Switches..............................: 165
- Avg. Pages per Extent........................: 5.5
- Scan Density [Best Count:Actual Count].......: 68.67% [114:166]
- Extent Scan Fragmentation ...................: 39.16%
- Avg. Bytes Free per Page.....................: 441.3
- Avg. Page Density (full).....................: 94.55%
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Clustered indexes represented by index ID: 0 or 1. The values above mean:

Pages scanned = total pages used (in clustered index, this of course represents the actual data pages as well
as the index intermediary nodes)

Extents scanned = total number of 64Kb extents, 8 pages per extent

Extent switches = movements between 1 extent to another over its extent chain.
(pages scanned / 8 should-be less than extent-switches).

Avg pages / extent = technically, represents unused pages per extent, 8 is the optimal value (no unused)

Scan density = fragmentation % (best count is the ideal value vs the actual extent switch count)

Extent scan fragmentation = % of out of order extents in the leaf nodes


avg bytes free per page = can be skewed with unused space in extents, is the avg free space left over per
page, lower value the better. Dependent on row size.

avg page density = how full the average page is, again, is dependent on row size, fill-factor, and
inserts/deletes/updates.

Be warned with the values presented above. A small table, for example products in the Northwind
database, reported 77 rows, two extents (1 switch), and a scan density (fragmentation) of 50%,
with a terrible avg pages / extent of 1. The mixed extent issue is the reason and should not overly
worry you.

Resolving Fragmentation

Clustered index tables will benefit the most from SQL Server’s defragmentation routines as they are
all based around indexes (a defrag on a clustered index will of course compact data and index
pages), unlike heaps (tables without clustered indexes, compacts indexes only). The following is
recommended and can be further explored in the books online.

ƒ DBCC DBREINDEX

31
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ DBCC INDEXDEFRAG

ƒ DBCC SHRINKDATABASE

ƒ Consider dropping and re-creating your clustered indexes if the above seems to be skewed
(after re-checking the fragmentation report). Always concentrate on the largest and busiest
tables first.

32
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

High Water Mark (HWM)


When space is allocated to a table or index, and you remove it all via a “delete from” statement
(unlike a truncate), SQL Server will retain a set amount of space.

The actual amount should be re-confirmed with your particular SQL Server installation in case there
is variance with DBMS versions, OS and/or IO sub-system configuration. The example below
shows the reservation of space.

Row Reversed Data Index Unused Notes


count (Kb) (Kb) (Kb) (Kb)
79858 638984 638984 8 112
<<all rows removed from the table via delete>>
0 38920 38880 8 32 Approx 38Mb of space left allocated to
table after delete DML

159716 1277896 1277728 8 160


<<all rows removed from the table via delete>>
0 38920 38880 8 32 Re-check space left over after delete with
double the number of rows. In this case
no matter the number of rows the same
space is reserved.(this can vary and the
DBA should verify themselves on their
particular instance).

IMPORTANT – This example was with a heap (non-clustered index) table. See the
examples below for space utilisation after a delete with a clustered indexed table.

In terms of a HWM and the optimiser full-table scanning to the end of the tables memory allocation,
we see the following occur for empty tables:

Example 1 – Heap with no indexing

-- table with 1 row per page


create table largerow (a int identity,b char(8000))

-- populate with 1000 rows


declare @aa int
set @aa = 1
while @aa <= 1000
begin
insert into largerow values('a')
set @aa = @aa + 1
end

Row Reversed Data Index Unused Notes


count (Kb) (Kb) (Kb) (Kb)
1000 8008 8000 8 0 Inserted 1000 rows.
-- select *
Table 'largerow3'. Scan count 1, logical reads 1000, physical reads 7, read-ahead reads 264.
0 6152 6112 8 32 Deleted all rows
-- select *
Table 'largerow3'. Scan count 1, logical reads 764, physical reads 28, read-ahead reads 700.

33
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

0 0 0 0 0 Truncate the table


-- truncate
Table 'largerow3'. Scan count 1, logical reads 0, physical reads 0, read-ahead reads 0.

Example 2 – Clustered Indexed Table

-- table with 1 row per page


create table largerow (a int identity,b char(8000))
create clustered index largerow_ix on largerow3 (a)

-- populate with 1000 rows


declare @aa int
set @aa = 1
while @aa <= 1000
begin
insert into largerow values('a')
set @aa = @aa + 1
end

Row Reversed Data Index Unused Notes


count (Kb) (Kb) (Kb) (Kb)
1000 8072 8000 40 32 Inserted 1000 rows.
-- select *
Table 'largerow3'. Scan count 1, logical reads 1002, physical reads 0, read-ahead reads 592.
0 88 8 24 56 Deleted all rows
-- select *
Table 'largerow3'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0.
0 0 0 0 0 Truncate the table
-- truncate
Table 'largerow3'. Scan count 1, logical reads 0, physical reads 0, read-ahead reads 0.

Example 3 – Non Clustered B*Tree Indexed Table

-- table with 1 row per page


create table largerow (a int identity,b char(8000))
create index largerow_ix on largerow3 (a)

-- populate with 1000 rows


declare @aa int
set @aa = 1
while @aa <= 1000
begin
insert into largerow values('a')
set @aa = @aa + 1
end

Row Reversed Data Index Unused Notes


count (Kb) (Kb) (Kb) (Kb)
1000 8048 8000 48 0 Inserted 1000 rows.
-- select * (index not used by optimizer)
Table 'largerow3'. Scan count 1, logical reads 1000, physical reads 0, read-ahead reads 648.
-- forced index lookup via hint, select.. with (index (largerow_ix))
Table 'largerow3'. Scan count 1, logical reads 1004, physical reads 0, read-ahead reads 627.
0 88 8 24 56 Deleted all rows
-- select *
Table 'largerow3'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0.
0 0 0 0 0 Truncate the table

34
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

-- truncate
Table 'largerow3'. Scan count 1, logical reads 0, physical reads 0, read-ahead reads 0.

Segments

In early versions of SQL Server (namely 6.x), we had the concept of segments and their pre-
allocation to house set objects (index, tables) typically to separate disks to increase IO speed. This
concept is no longer valid in SQL Server 7 and 2000.

A SQL Server page can be of segment types:

ƒ data – all data type entries, text/image/ntext data can be stored inline with the data row via
the text in row option is used on table creation.

ƒ index – index entries

ƒ text/image – storage of data type text, image, other blob data out of line with the rest of
the data row. The data row page has a 16-byte text pointer to this entry.

ƒ GAM / SGAM

ƒ Free space

ƒ BCM

ƒ DCM

Most of these segments have already been discussed. The key fact to remember here is that
segment space is not pre-allocated by the DBA, SQL Server manages the space allocation in all
cases. The DBA can only control fillfactor (default zero or 100%) and padindex (default 1 space for
a single row) options for indexes.

Relational Engine
The relational and storage engines are completely separate within SQL Server and communicate via
the OLE-DB API. Its not too difficult to work out what the relational engine does, but I must say
that compared to Oracle, the documentation is very scarce and overly broad:

ƒ parse

ƒ locate existing cached plans

ƒ build query tree (depending on b))

ƒ optimise (cost based optimisation)

35
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ execute

ƒ communicate with storage engine to retrieve data

ƒ process DDL and other statements

ƒ return result to client

The SQL (T-SQL is also regarded as SQL) statements cover all forms and instantiations submitted
to the engine, namely:

ƒ single (adhoc) statements, including views

ƒ batch statements

ƒ stored procedures and user defined functions

The optimiser relies on histograms (statistics) collected by the instance automatically (auto create
statistics setting for each database in the instance), indexes and manually created statistic
collections. These are used to establish a variety of figures related to the cost of the plan and
choosing the one with the lowest estimated cost. To speed plan estimation a variety of complex
algorithms are used, which, in some cases will result in only partial optimisation. The source data
structure for the optimiser is the successfully parsed sequence (query) tree.

On execution of the optimised query plan, a series of requests are sent to the storage engine in
which rowsets are returned. The data is processed by the relational engine that formats and
returns the results to the client via a UMS managed worker thread.

The relational engine may build temporary data structures (work-tables) in the tempdb system
database to complete the SQL statement.

All execution plans are stored in the procedure cache. Each plan has two parts:

ƒ query plan, read-only cached plan, up to two can exist for a batch, one for serial and one for
parallel operations

ƒ execution context, bind variables and other parameter values for the SQL

Like Oracle, the use of parameters (bind variables) increases the possibility of plan reuse.

Unless altered by the DBA, the parallelisation of the statement will be determined during the
optimisation phase.

36
2
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Installation

T
hroughout this chapter will we discuss the installation of a SQL Server instance. Like most
DBMS’s, the DBA can do a quick and dirty install, or be thorough in terms of security and
really lock down the instance and access to it. We will discuss some of the issues to
consider in both methods and where appropriate, drill into the finer points of the installation
process.

Editions and Versions


Before you install (or buy) SQL Server 2k, here is a short overview of the “editions” of SQL Server,
this is very important as the costs and feature differences may bite you later on. The “editions”
consist of:

ƒ Standard Edition

ƒ Enterprise Edition

ƒ Developer Edition (CD two of Standard and Enterprise)

ƒ Personal Edition

ƒ SQL Server CE (small footprint for Windows CE OS)

ƒ SQL Server MSDE (Microsoft Data Engine, no EM GUI with max 5 concurrent users)

ƒ Evaluation Ed (typically 128 day evaluation)

Some of the key items Standard Ed does not include over Enterprise Ed:

ƒ Distributed partitioned views

ƒ Log shipping (can be manually scripted though)

ƒ Parallel index creation, Parallel scan, Parallel DBCC

ƒ Fail over Clustering

37
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ Indexed views

ƒ Multi-language capabilities

ƒ OLAP – linked cubes

ƒ OLAP – cube access over HTTP

ƒ OLAP – ROLAP storage

ƒ Direct SAN support

ƒ 32 CPU’s and 64Gb RAM

Licensing Schemes
When installing Standard or Enterprise Editions, the DBA is prompted for the SQL Server licensing
scheme to be used for the instance. The schemes are:

ƒ Per Processor (typically for web-based applications) – for each CPU, unlimited users.

ƒ Per Seat (known as a CAL or Client Access Licence) – this is a per “device connection”
licence, and not per user, if I as a user connect 10 times with mobiles/PDA/laptop etc all
simultaneously then all require a CAL.

NOTE - SQL Server does not use the pricing model of per power-unit as Oracle does (or used
did, this seems to change on a regular basis as RDBMS competition heats up).

IMPORTANT – No licence for your operating system? then all SQL Server licences are
automatically treated as “invalid” for the server.

IMPORTANT - Connection pooling is not an excuse for buying less CAL’s if using this
licensing scheme. If 20 user connections are pooled to 5 SQL Server sessions, you still need
20 CAL’s.

There are many important issues to be considered when dealing with licensing, some of these are:

ƒ Standard Edition

ƒ Must have a separate licence for each new instance

ƒ Enterprise Edition

ƒ Can create as many instances of the same server as you like under a single license.

ƒ Active / Active Cluster

38
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ All Active machines required separate licences

ƒ CAL or Per Processor schemes are fine.

ƒ Active / Passive Cluster

ƒ A single licence scheme can be used for both servers. Attempts to use the passive
SQL Server for connections will result in further licensing issues.

ƒ Log Shipping

ƒ See “Active / Passive Cluster”

ƒ Developer Edition

ƒ Licensed per developer

ƒ Personal Edition

ƒ So long as the OS is licensed, Personal Ed is free of further licensing issues.

ƒ SQL Server CE Edition

ƒ Requires CAL as part of the Developer Edition

ƒ If the CE SQL Server connects to another SQL Server (i.e. replication, linked server
etc), then that “remote” SQL Server requires a per-processor licence.

It is worthwhile spending the time to read these:

http://www.microsoft.com/sql/howtobuy/sqlserverlicensing.asp
http://www.microsoft.com/sql/howtobuy/sqlserverce.asp
http://www.microsoft.com/sql/howtobuy/msde.asp
http://www.microsoft.com/sql/howtobuy/personal.asp

Some approximated pricing is shown below (believe me, with the market as it is, don’t trust me on
this one):

Type Of Edition Quantity Est.Price$ (US)


Per Processor Enterprise Ed N/A $20,000
Per Processor Standard Ed N/A $5,000
Per Seat CAL Enterprise Ed 5 N/A
Per Seat CAL Enterprise Ed 10 N/A
Per Seat CAL Enterprise Ed 25 $11,000
Per Seat CAL Standard Ed 5 $1,500
Per Seat CAL Standard Ed 10 $2,200
Per Seat CAL Standard Ed 25 N/A

39
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

To locate information in regards to the existing licensing scheme, run the following within Query
Analyser:

select SERVERPROPERTY('LicenseType')
select SERVERPROPERTY('NumLicenses')

where 'NumLicenses' is not applicable for the per CPU scheme. If you are running the Developer
Edition, 'LicenseType' returns “disabled” and 'NumLicenses' is NULL.

The License Manager program (control-panel -> administrative tools) cannot display information
related to per-processor licensing for SQL Server (Q306247). To get around this issue the
installation will create a new administrative tool program to track such information as shown in the
screen shots below.

SQL Server 2k licence applet, this


is very different under v7.

Version 2000 Version 7

The Settings Æ Control panel Æ Licensing Æ shows only server licensing for SL Server 2000
installations (unlike v7), the applet above is used instead. Notice that you cannot switch to a per-
processor licence; you must re-install the instance to do this.

NOTE – Unless specified in your licence contract or SQL Server version on installation, the
installed instance will not automatically expire or end.

40
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Alter licensing mode after install?


Once the licensing mode is set on instance installation, that’s it, you cannot change it back. In
control panel we have the icon:

This will allow you administer your licences, but you will see one of the options is greyed out, such
as:

To get around this go to the following registry key entry:

Change the mode to 1 (default is zero) and you get both options:

Microsoft may not support you if this method is used.

41
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Binaries & Instance Installation


Upon the installation of the Oracle binaries, the DBA would either create the databases they require
via command line script svrmgr or sql*plus or use the Oracle GUI tools. Under NT, the Oracle DBA
would perhaps utilise:

oradim.exe Create instance of the NT service


svrmgrl / SQL*Plus To run our hand written DB script and run cat%.sql files to build
dictionary.
SQLNet Config Configure network connectivity and listener
or
Database Configuration Assistant (GUI)

Throughout the different versions of Oracle we have seen a shift to more GUI tools (driven by
Java) that cover most basics and allow the DBA to quickly get databases up and running and
add to the database any other tablespaces as need be. In SQL Server, the setup disk not only
covers the binary installation, but instance creation, maintenance tasks (registry rebuild,
system database fix etc) as well.

The SQL Server Setup CD will (not necessarily in order):

a) Run through installation options for default or named instance and install the instance
with instance and non-instance dependent binaries
a. Named Instance?
b. Location of binaries and the instance’s system database files
c. Setup the account in which the services will run
i. Use the same account to run the instance service and the instances SQL
Agent account?
ii. Run under the Local system account?
iii. Run under another domain user account?
iv. Auto-start service?
d. Instance Collation (language) and sort order
e. Install binaries based on selected options
f. Authentication mode for the instance
i. Mixed mode (windows and SQL Server authentication)
ii. Windows authentication
g. Setup NT services
h. Setup default networking properties

You may need to install the prerequisite options first, SQL Server setup will soon tell you about
this and also notify you when trying to install over an OS that doesn’t support the edition. You
have the flexibility to install options only (like, only the books online which is a very good idea)
and not to install or create a new SQL Server instance. These are all self explanatory with the
set-up.

Additional options include:

a) rebuilding the registry entries (will also reinstall MDAC from the CD)

42
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

b) installation of missed or skipped components


c) can fix broken installations where server name has changed
d) can restore default system database data and log files in case of an emergency
recovery
e) can assist with installing instances over a configured MSCS (MS Cluster) for failover
clustering.
f) Install analysis services (Microsoft OLAP and Data Mining)

Service Account
As with Oracle installation under NT, the NT account you are using on installation is called the
service account in which associated DBMS services and further installation and administrative tasks
will occur under. In many cases (the quick and dirty method), the DBA will use the administrator
account as it provides complete access to the server and its resources, reducing the possibility of
any flow on issues related to the system privileges.

If you need to install using a separate NT account that will not be a member of the administrators
group, the consider the following:

ƒ Create a new NT user

ƒ Grant login as service rights

ƒ Grant administrator group privileges to this user

ƒ Create DB data and log file directories for database files to be created in

ƒ Install SQL Server as this user

ƒ Once installed, shutdown the MSSQLServer service

ƒ Login as Administrator of the server and alter the users rights as follows

ƒ Full control of SQL Server binaries (install directory)

ƒ Full control of all directories to store database files (mdf,ndf,ldf)

ƒ For the above directories, remove the "everyone" group privilege

ƒ Full control of the registry keys.


HKEY_LOCAL_MACHINE\Software\Microsoft\MSSQLServer
HKEY_LOCAL_MACHINE \System\CurrentControlset\Services\MSSQLServer or
MSSQL$<INSTANCE> for named instances
HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\Perflib

ƒ and associated service registry keys for SQLAgent$InstanceName, MSSearch, and


MSDTC

ƒ Revoke administrative rights to the SQL Server user account

43
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ Login as the SQL Server user and attempt to re-start the database, debug as
required.

ƒ Access to xp_cmdshell for non-sysadmin users must be via a proxy account (select
properties of SQL Agent).

NOTE – When using replication, create a DOMAIN user account and not a local server
account.

This may not be definitive and will require some testing and checking of the SQL Server error logs
and the NT event logs to locate the reasons why specific operations are not happening with the
account being used. A classic problem is the SQL Agent service account, which does require
administrative privilege to run successfully.

Encrypted File System (EFS)


Those running Windows 2000 can take advantage of the EFS (encrypted file system) for database
and/or backup files. To use this option:

ƒ shutdown your database instance

ƒ login with the account the SQL Server instance is using

ƒ select properties of the folder(s) in which the database files reside

ƒ select advanced option and follow prompts to encrypt files/folders

ƒ re-start the instance service

ƒ verify successful start-up of instance and databases affected via the encryption.

Attempting to start the service as any user other than the user that encrypted the database data
files, results in the instance not starting, or a suspect database. Example error log entries:

udopen: Operating system error 5(error not found) during the creation/opening of physical device
E:\cktemp\efs\efs_Data.MDF.
FCB::Open failed: Could not open device E:\cktemp\efs\efs_Data.MDF for virtual device number (VDN) 1.
udopen: Operating system error 5(error not found) during the creation/opening of physical device
E:\cktemp\efs\efs_Log.LDF.
FCB::Open failed: Could not open device E:\cktemp\efs\efs_Log.LDF for virtual device number (VDN) 2.

In terms of speed, this is a tough one to measure, there are so many factors to consider it’s not
funny, for example:

ƒ hardware vendor

ƒ IO drives and OS version and patch level

ƒ Disk vendor, speed, cache

ƒ RAID levels, channels, disk interconnect

44
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ RAID controller type, cache, vendor

After some testing of the same 5000 row table on an EFS database verses a non-EFS database, we
find some interesting results. The following table was created and queried:

drop table efs


create table efs (col1 int, col2 varchar(200))

declare @aa int

set @aa = 1
while @aa <= 5000 begin
insert into efs (col1, col2) values (@aa, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
set @aa = @aa + 1
end

NOTE - the following statistics are averaged figures of five different attempts at the same
SQL. Personally, I do not like to write up such figures, and I pre-warn that careful testing
must be done at your specific site with more complex scenarios.

Encrypted Database File IO (avg - 1min 10sec to create and populate)

update efs set col2 = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'


where col1 = 3345
checkpoint

-- Averaged 10% slower


Table 'efs'. Scan count 1, logical reads 1720, physical reads 0, read-ahead reads 0.

SQL Server Execution Times:

CPU time = 40 ms, elapsed time = 40 ms.

-- Averaged 6% slower
update efs
set col2 = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'

Table 'efs'. Scan count 1, logical reads 5875, physical reads 0, read-ahead reads 0.

SQL Server Execution Times:


CPU time = 1472 ms, elapsed time = 11761 ms.

-- Averaged 42% slower (varied substantially based on query complexity)


dbcc dropcleanbuffers
select count(*) from efs

Table 'efs'. Scan count 1, logical reads 1720, physical reads 1, read-ahead reads 48.

SQL Server Execution Times:


CPU time = 50 ms, elapsed time = 89 ms.

45
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Non-Encrypted Database File IO (avg - 42sec to create and populate)

update efs set col2 = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'


where col1 = 3345
checkpoint

Table 'efs'. Scan count 1, logical reads 1721, physical reads 0, read-ahead reads 0.

SQL Server Execution Times:


CPU time = 30 ms, elapsed time = 36 ms.

update efs
set col2 = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
Table 'efs'. Scan count 1, logical reads 5875, physical reads 0, read-ahead reads 0.

SQL Server Execution Times:


CPU time = 1482 ms, elapsed time = 11109 ms.

dbcc dropcleanbuffers
select count(*) from efs

Table 'efs'. Scan count 1, logical reads 1720, physical reads 1, read-ahead reads 48.

SQL Server Execution Times:


CPU time = 40 ms, elapsed time = 205 ms.

Be very careful, the EFS is an advanced option and I having read a variety of news-group posts
regarding recovery of servers and associated tape backups from EFS files, the process is far from
simple. Be aware of the dependency on the OS installation, server and user that will all influence
the encryption.

RAID Set-up with SQL Server, Install Issues, OFA


The same principals apply between Oracle and SQL Server is terms on RAID, including the
hardware selection and channel configuration, on-board RAM and compliance with the Microsoft
Windows hardware compatibility list. For the installation directory and its binaries, system
database data files and users database data files, we need to consider:

ƒ reated an installation map?

ƒ Some of the issues include OS versions and service packs, service accounts to be
used, placement of files, disk sub-system configuration, how many databases will be
hosted and how will their file place affect other databases?, number of users and
connectivity properties, instance names, requirement to install previous SQL Server
versions, backup locations, default passwords, who will access to the DBMS, remote
administration issues, file shares and their security, virus checking software (and is it
auto-updating).

46
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ OLTP or DSS nature of the system, affect on network bandwidth, buffer cache and
procedure cache hit ratios

ƒ Will multiple instances will be sharing the same disk sub-system?

ƒ Will other IO intensive software will be installed?

ƒ Will other file-system like activity through the application such as batch document creation,
auditing log files, bulk extracts for reporting, OLAP cube builds, affect performance
significantly or pose issues with the disk subsystem?

ƒ Possibility of moving to a clustered environment?

ƒ Capacity of disk array in terms of free drive slots?

ƒ Backup sub-system and associated disk space (will disk backups share the drive with other
database files?)

ƒ Do we really understand the expected database growth patterns? and how do you plan to
track it?

ƒ Positioning of file-groups and have we thought of using multiple file-groups over disk RAID
arrays to increase IO performance and ease administration?

ƒ Adhoc queries or reporting databases (IO distribution or bias).

These issues are particularly important in large OLTP or DSS based applications sharing the same
disk sub-system with other applications or user databases.

The question of the RAID level is a tricky one as RAID-1, RAID-5 and RAID-10 arrays are typically
determined by the money available and the total databases to be supported. I have yet to come
across any mid-sized organisation where money wasn’t as issue and don’t be fooled, high-end
server hardware is expensive (we are not talking desktop PC’s here).

In terms of performance, RAID-5 should not be overlooked. Be aware that each write results in
two IO’s plus a single read IO. Even so, I have successfully run a variety of applications over such
an array (with hardware caching enabled though at a small risk of database corruption) with very
low read/write queue lengths. Like all things, the DBA should be aware of the issue and pre-test
where possible.

As a guide, we tend to see very little IO activity around the master, msdb and model system
databases. As such they and the binaries tend to be placed in the same location, typically a RAID-1
or RAID-10 array. The tempdb database, used for temporary sort, group-by and other operations
like the temp tablespace in Oracle, may need to be placed on its own array.

The issue with the tempdb is its size and trying to justify its own disks (the minimum is typically
18Gb or 36Gb). A server with large amounts of RAM and very short transactions manipulating
small amounts of data will rarely use the tempdb. As an example, my 2Gb production database
with over 900 online users, 4Gb of RAM, sees the maximum tempdb of 800Mb.

47
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The DBA needs to consider the total server RAM, index rebuilds, DBCC executions and their
timings, the need to large data set processing, and simply monitor tempdb usage, weighing up IO
performance via performance monitor.

User database files are broken down (at their basic configuration) into two data files:

ƒ Data File (primary file-group)

ƒ Transaction Log File (file-groups not applicable)

Ideally, the log files should be own their own array due to their serial writes.

In summary, as an instance includes numerous databases all with a minimum of two data files, a so
called perfect disk placement for all files is a dream for 99% of companies. From the points
discussed, I would recommend something like:

Drive RAID Contents


Letter Type
C: RAID-1 Windows OS and installed apps
D: CD-ROM
E: RAID-1 or All system database files
RAID-10
F: RAID-1 Filegroup “DATA” DB files
G: RAID-1 Filegroup “INDEX” DB files
H: RAID-1 Transaction log files
* opt for the RAID-10 for the optimal read/write performance.

As an example, my 800 user database server with heavy OLTP activity has the following drive
configuration with close to zero problems in terms of IO contention. The disks are SCSI160 15k
18Gb disks hooked to a HP 4M raid controller with 40Mb cache, read/write ahead caching is on for
the RAID-5 array.

Drive RAID Contents


Letter Type
C: RAID-1 Windows OS and installed apps
All system database files
D: CD-ROM
E: RAID-1 Transaction log files
F: RAID-1 Filegroup “AUDIT” DB files
Backup file dumps
G: RAID-5 Filegroup “DATA” DB files
(4 disks) Filegroup “INDEX” DB files

In Oracle, many DBA’s prescribe to some form of the OFA (Optimal Flexible Architecture) for file
placement over the array. This basically describes:

ƒ Establish a documented and orderly directory structure for installation binaries and database
files that is compatible with any disk resource

i.e. c:\SQLServer2kBin\<instance-name>\{binaries}
c:\SQLServer2kData\<instance-name>\<db-name>\{data files}
c:\SQLServer2kLog\<instance-name>\<db-name>\{log files}
c:\SQLServer2kErr\<instance-name>\{error log files}

48
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ Separate segments of different behaviour into different tablespaces (file-groups)

ƒ Consider creating, for users databases, a separate file-group or DATA, INDEXES,


AUDITING, and not using the PRIMARY group for user objects.

ƒ Consider separation based on disk resource contention

ƒ Consider file-group separation based on their historical data content

ƒ Separate database components across different disk resources for reliability and
performance

NOTE – Be aware of SQL Server data striping. If you have two or more database files for a
single file-group, SQL Server will automatically stipe data across these based on the
percentage of free space with each data file. Be aware of this is you are also planning disk
striping “by hand” during installation/restore.

Items to consider before installation (summary)

The following is a summary the DBA should be considering carefully before installation, some of
which were covered in previously on RAID arrays:

a) Clustered installation?
b) Disk sub-system set-up and ready for the installation?
c) Upgrading and existing version?
a. v7 to 2000
b. v6.5 to 2000
c. mixed environment? (v7 and 2k or other combination)
d) Check OS requirements and RAID issues
e) Location of binaries and default location for installed system databases (OFA)
f) Editions and Versions
g) MDAC version support for other applications (will installing SQL Server be an issue, as a
general rule it will not).
h) Will you need to run SQL Server v7
a. Install named instances of SQL Server 2k
b. v7 cannot support multiple instances, therefore will be used as the default
instance.
i) File and instance naming standards defined?
j) Collation and Sort Order determined for instance?
k) Security – Installing under System User or another domain user account?
l) Security – Integrated or Mixed Mode?
m) Do you want to move the tempdb system database?
n) Log shipping support required? Does your edition support it? The SQL Agent service
must run under a domain user account with rights to other domain servers.
o) Full Text Search and English Query required?
p) SA Password Management and the sysadmin privilege user
q) Instance memory configuration (how much will be allocated?)

49
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

r) Backup/Recovery plan considered, will be duplex files to another server?, retention


period and recovery models used? Have you tested them and can you meet defined
SLA’s?
s) Server and Database ownership in terms of ongoing support and maintenance

Example Installation – Standard, Developer or Enterprise Ed


Installing Oracle is a two-part process, one being the installation of the binaries in a specific
ORACLE_HOME, and then creating one or more databases via the command line or GUI tools. In
SQL Server these two steps are completed in a single running of the set-up.

NOTE – In general, the setup is self-explanatory and we will only cover some of the wizard
dialogs presented to you.

The setup process as described, is multi-functional, to install a new database instance, we select
the Server and Client Tools option. The client tools are generic for all instances, therefore, once
installed we need to filter out these additional options. This is discussed later.

The next question presented to the DBA is the instance name, the default option will create the
default unnamed instance (if one doesn’t already exist). Based on this early decision the following
will eventually be created:

Shared files for all instances

Default Instance

Other Named instances

and the following example services, the first being the instance and the active directory helper
service for all instances, and the second set being SQL Agent (batch job processing service) for
each instance.

50
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

When prompted, always select the custom option. It is good practice to select advanced options.

Binaries (keep all instances in the


same location).

Sets the instances default directory


for all instance databases. The
directory will be :
..\<instance-name>\Data

You cannot specify the ORACLE_HOME and there is no environment variable; the DBA can specify
the installation directory for the binaries for an instance the default being c:\Program
Files\Microsoft SQL Server\.

51
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The options for Management Tool (Enterprise Manager and other command line and GUI tools),
Client Connectivity, BOL (Books online), Development tools and Samples are shared components
for all instances; when installed for one instance, don’t re-select them for subsequent instances.
This is especially the case when patching a system with service packs or upgrading BOL, as you
don’t want to revert back to the default installation settings accidentally. Full-text query allows the
DBMS to utilise the Microsoft Search Engine to build catalogs on table columns that allows English
like queries to be performance at high speed.

The next step is selecting the NT account in which the instance services will run. It is important
that you read the Security Chapter on Installation Issues regarding security during installation.
Many DBA’s leave this as default, running the two services for the instance under the system user
account. Although fine for most installations, in a production environment this should be altered to
another NT domain user account with restricted OS privileges if required. If changing the account,
do not forget to check the auto-start service check box.

For the security conscious,


run the instance under a
new user account. How to
configure it is described in
the Security Chapter.

The above can be altered by editing the services within NT, and also within SQL Server Enterprise
Manager by selecting properties at the top level of the instance tree and for the SQL Server agent.
See below.

Select security tab when


selecting properties for
the instance once
connected.

52
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Select properties for the


SQL Server Agent option
with enterprise manager.

Once the service accounts have been specified, we tell SQL Server about the authentication method
it should use. See the Chapter on Security. The Windows Authentication mode is the same as
OPS$ (external Oracle authentication) only, and Mixed is both Database and Windows
Authentication. Mixed mode will require you to enter the sa account password to complete mixed
authentication, guard this login/password religiously, it is equivalent to the sys login with Oracle.
The service account in which SQL Server is installed will be the Windows Authentication user, and
you will be able to connect to the instance with no password (OS managed). The
BUILTIN/Administrators SQL Server login will provide this seamless authentication via the
equivalent OS group that can be removed to provide better security.

I recommend Mixed Mode where possible with a complex SA password that is rarely used. This
ensures that a DBA inadvertently locking themselves out when altering windows authentication
privileges or server configuration is not a completely lost cause.

The final BIG question asked of the DBA is the collation and sort order. This single question results
in numerous postings in newsgroups and forums, and rightly so. The language and sort order is
covered in the Chapter on NLS and Sort Orders. The installation screen is shown below.

53
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The default collation is


Latin1_General, and the sort
order is Accent sensitive.
Example collations are:
French
Greek
Romanian
Polish etc…

Previous version sort orders


can be selected if need be
for backward compatibility.

To complete the installation, the setup will finally prompt you for the default server network
(listener) properties and the supported network libraries that can be used. The standard libraries
include named pipes and TCP/IP (a port of 0 equates to port 1433 or SQL Server will pick a random
port on first ever connection and retain it). The named pipe will be \\. \pipe\MSSQL[$]<instance-
name>. The server will not be hidden from the network. See the Chapter on Networking SQL
Server. Leave the displayed options as default in a majority of cases.

Please read the Chapter on Networking regarding listener set-up and configuration.

After the network screen SQL Server will:

ƒ Install MDAC (check documentation on version being installed)

ƒ Install binaries and registry entries

ƒ Install and prepare services

ƒ Register active-x components

ƒ Update your system (whatever that means)

And this completes the installation.

You will need to apply additional services packs as need be to the installation (highly
recommended).

WARNING – Applying SQL Server patches or installing SQL Server will alter your MDAC
level. Take are in multi-server environments where this can cause differences in MDAC
between servers.

54
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Moving your system databases after installation


The first thing Oracle DBA’s will ask, is “so how do I move my system database files after a
standard installation?”. The setup prompts the DBA for a default data directory, in which the setup
will then dump ALL default installation data files from the CD to this directory. In most cases, this
is fine, as the DBA will have set aside a RAID set for all system files, the only system file that that
DBA may want to split away from the master, msdb, model database files is the tempdb database.

The default database files installed from the CD-ROM are:

MASTER master.mdf, mastlog.ldf


MSDB msdbdata.mdf, msdblog.ldf
TEMPDB tempdb.mdf, templog.ldf
MODEL model.mdf, modellog.ldf

Moving MASTER and Error Logs


The instance start-up parameters in the registry can be altered, effectively allowing you to move
the database files to another location.

Alter the registry entries, stop the instance service, including SQL Agent, move the master
database files to the new location and re-start the instance. The DBA can alter these within
Enterprise Manager by selecting properties of the instance and altering the start-up parameters.
This will call an extended stored procedure to alter the registry settings above.

Moving MSDB and MODEL


The DBA can mode the MSDB and MODEL databases via:

ƒ Full backup then restore to a new destination

ƒ Use the sp_attach and sp_deattach commands

55
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The backup and restore option is the most simplistic and is covered in the Backup and Recovery
chapter. The instance will require less downtime and is a safer option overall.

To move these database via the sp_attach and sp_deattach commands, we require a little more
work to be done.

1. Open the service control window for the instance, and add the start parameter -T3608

2. Start the instance

3. Run query analyser, login in with sysadmin privileges

4. Run the following command, writing down the name, fileid and filename displayed

use msdb
go
sp_helpfile
go

5. De-attach the database from the instance with the command

use master
go
sp_detach_db 'msdb'

56
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

go

6. Refresh enterprise manager, you will notice that MSDB has now disappeared.
7. Copy or Move the database files listed in 4 to their new destination
8. Run the following command to re-attach the MSDB database files

use master
go
sp_attach_db 'msdb','C:\msdbdata.mdf','c:\msdblog.ldf'
go

9. Go back to the service control window, shutdown service, clear the trace flag and re-start
the service.
10. Refresh Enterprise Manager or re-start.
11. Re-run step 4 to verify the new file location

Repeat the process above for the MODEL database.

WARNING - if doing both databases at the same time attach the MODEL database before
MSDB.

Moving TEMPDB
The TEMPDB database is the same as the temporary tablespace option within Oracle. This
database is used for sorting and temporary tables. It is common practice, where possible, to
move this database to its own RAID 1 or RAID 10 set. This needs to be carefully evaluated to
determine if the use of the database and the set of disks it is residing on is a bottleneck. To
move the database files for this system database:

1. Run query analyser, check existing location of the tempdb database files

use tempdb
go
sp_helpfile
go

2. Get the destination directory ready and document the results above, re-check the
location.

3. Issue the alter statement to logically move the files

alter database tempdb modify file (name=tempdev, filename=c:\dbdata\sys\tempdb.dbf)


alter database tempdb modify file (name=templog, filename=c:\dbdata\sys\templog.ldf)

Restart the instance for the files to be re-created at the new location.

Consider trace flag 3608 or 3609 (skips tempdb creation) if you have issues with the new
destination or with the model database (from which its created).

You can also resize the tempdb database via the SIZE option in the alter database statement.

57
3
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

GUI and Command Line Tools

T
hroughout this chapter we will focus on the GUI and command line utilities installed with
SQL Server. The tools are simple to use and all they require is time trying out their
numerous options. We will not explore each and every option, but provide a high level
summary of the tool and its use.

What is installed?
On installation, SQL Server 2k comes with a variety of tools sets. Some of the tools are:

Tool GUI? Category Summary


Enterprise Manager Y Management The core GUI for all database administration of 1
(EM) or more instances on remote or local servers.
Profiler Y Trace & SQL Tracing utility, captures numerous statistics of
Performance all DML/DDL running against the instance. Very
powerful tuning and debugging tool for the DBA.
Query Analyser Y SQL Similar to SQL*Plus, includes command line
isql.exe and GUI wsql.exe versions.
BCP N Import/ Bulk copy process command line, includes import
Export and export functionality. Equiv to sqlloader but is
not as powerful and is reasonably limited.
Textcopy N Import
DTSRUN N DTS Command line utility that can execute a data
transformation package create in a SQL Server
instance.
SQLDIAG N Diagnostic Command line tool that produces detailed
diagnostic type information for a SQL Server
instance. Highly recommended.
Performance Monitor Y Performance perfmon.exe is a built-in with the OS, Oracle also
(perfmon.exe includes perfmon counters on installation of the
counters) Oracle binaries. SQL Server adds a large range of
counters for each instance installed for detailed
performance monitoring of instance and database
internals.
SQLAGENT N (Y Scheduling Linked to the MSDB system database and exists
via for each database instance, is the job scheduler
EM) for the instance.

58
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Service Manager Y Management Manage SQL Server NT services


Server Network Utility Y Network Similar to SQL*Net listener, acts as the listener for
the database server and defines the providers that
may communicate to the database instance(s).
Client Network Utility Y Network Defines client connectivity properties to database
instances over 1 or more defined providers
(protocols)
Books Online Y Help Product Help and Documentation
Itwiz Y Performance Index Tuning Wizard.
Dtswiz Y DTS Data transformation service import/export wizard.
Does have command line options, use dtswiz /? to
get a list of them.
Distrib Replication
Logread Replication
Replmerg Replication
Snapshot Replication
Regxmls XML
Odbccmpt ODBC
Sqlftwiz Y Full Text Full text indexing wizard.
Sqlmaint N Maintenance Maintenance operations on one or more databases
such as updating stats, rebuilding indexes etc.
Vswitch N Switch Switch between v6, v6.5 and v8 (SS2k) SQL
Server installations.
Sqlagent N Job Starts SQL Agent service. Mainly used at the
Scheduling command line for diagnostics.
and
Processing
console N Tape Displays diagnostics information on tape backup
and restore operations.
Scm Y Services Service control manager

Enterprise Manager (overview)


The core DBA tool for managing SQL Server instances is Enterprise Manager. The GUI tool covers
virtually all of the key functions the DBA will perform in their day-to-day tasks, even so, as your
skills increase you may find yourself tracing the activity of Enterprise Manager via profiler and re-
writing your own scripts/stored-procedures to meet your specific requirements in which EM falls
short.

The EM tool itself is very easy to use and requires very little discussion; it is a simple a matter
of trying its features and learning from there. But all that said, we will highlight some issues
with the interface and how EM can make life of the DBA a lot easier.

Registering Servers

Registering database instances within EM is a fundamental task for managing multiple instances
from the single console. Right click properties on the Microsoft SQL Server group and select New
SQL Server Group:

59
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The name must of course be unique within its hierarchy; groups are sorted by name. Select the
new group, right click properties and choose new SQL Server registration:

Going through the wizard, it will show a screen of available servers. If yours is not listed ( which is
likely) then simply type in:

a) server IP address or hostname

b) or use the alias created for the instance via the Client Network Utility.

Option b) is the standard selection, especially when connecting to named instances, or instances on
non-standard ports and/or protocols. The alias method also allows you to register the same
instance multiple times.

60
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Interface Overview

Database folder – drill through to all databases


within the instance, if you cant see the system
databases then check the properties of the
registration as there is an option to hide them
from EM. The DBA can manage all properties
and settings of each database from here.

Create/edit DTS packages which are automatically


versioned for you. Packages and their content can
generate meta-data which the DBA can view/search
over, this allows us to track transformations typically
used in warehousing applications.

Management folder – Config and manage SQL


Agent jobs and their schedules, manage backup
devices, view current session activity and locking
issues, create and maintain maintenance plans and
view error logs. Can manage alerts, operators.

Replication folder – manage publications and the


subscriptions to these publications.

Security folder – Manage logins, server role


permissions, linked server and remote servers.

Support Services folder – managing other utilities


such as SQL Mail, full text search engine and the DTC.

Meta data services repository (stored in MSDB


database).

61
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Meta Data Repository


The Meta Data Services repository folder in EM seems eternally blank. To get it populated with
properties from an instances database and working for you in terms of meta data for your data
models via extended properties, then follow these screen shots below, remembering to refresh EM
after importing the meta-data.

62
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Meta Data Repository Snap-In

The meta data repository is not a small topic by any means. Its API and associated open interfaces
are designed to hook into case and designer tools, and follow this onto the implementation with
documenting the physical data model, tracking DTS data loads and providing some great
documentation on top of the standard E-R model. Unfortunately, we are not covering this topic in
detail but will look at the snap-in.

The meta data services snap in is the key to administering meta data services. To use the snap in
(which is not available in EM) you need to:

a) Run mmc.exe

b) File --> “Add/Remove Snapin”, dialog is shown, click on the “Add” button

c) Select the Meta Data Services snap-in and others as need be, close when finished

d) Ok

e) Save the console, setting yourself up with a custom admin management console

To register a instance and set administrative properties, you must have a database with the
repository tables. This database is the msdb system database.

a) Right click on Meta Data Services, select register database

b) Filling in the standard registration database property using the SQL Server OLE-DB provider
(which you cannot change).

c) The 3 user modes are:

a. End User – read only access to contents folder (as in EM)

b. Power User – read/write but cannot edit object properties

c. Administrator – read only to information models, read/write all other properties

d) Based on the user access, the DBA can remove, edit and refresh the repository and
properties, this is not possible in EM.

63
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

e) The DBA can also view the information models available for tracking and managing within
the repository.

Task Pad View

Some DBA’s talk about task pad in SQL Server, this is simply a type of view you can have within EM
when looking at an instance or individual database. An example is shown below.

64
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Inserting NULL’s into Table Columns

To insert a NULL into a database table column within EM, use CTRL-0 (zero) and tab to the next
column. Also take care having the table view open, EM is a classic for taking out escalated table
locks. A CTRL-N will close the EM window and you will have to re-start EM.

DBVERIFY
There is no database checking utility that operates whilst the SQL Server database instance is
down. Once up, the SQL Server DBA can use the DBCC (database consistency checking) routines,
namely DBCC CHECKDB, DBCC CHECKALLOC within query analyser or consider creating a database
maintenance plan and selecting the integrity checking options.

SVRMGRL
The closest SQL Server has to the server manager executable (svrmgr23 in 7.3, svrmgr30 in 8.0,
svrmgrl in 8.1 and replaced with extended functionality in SQL*Plus for 9i) is sqlservr.exe. This is
the core process running the instance and its associated databases and worker threads.

In most cases, the DBA will utilise the Service Control Manager (also see the NT services and open
the properties of the service to interact with startup parameters) and Enterprise Manager. The DBA
may also consider using Query Analyser (SQL*Plus).

65
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL Loader
There is no equivalent to SQL Loader command line. Running Enterprise Manager, the DBA can use
the DTS Import / Export wizard and its variety of options to script databases and move data, but it
is still limited, i.e. cannot script linked servers etc). The GUI is reasonably powerful, but the DBA
may feel inclined to use other 3rd party products for better coverage of all database elements. The
DBA should not script the system databases as a method of restoring.

The DBA should also consider the BCP command line tool and the bulk insert DML command. The
bulk copy process allows the DBA to dump data to text files using defined column and line
separators.

Here is an example of using bulk insert in a stored procedure to load a temporary table:

CREATE TABLE [#lodgement_enrolment]


([lodgeenrol_id] [int] NOT NULL ,
[lodgeenrol_match_trainprod_id] [int] NOT NULL ,
[lodgeenrol_match_tc_id] [varchar] (20) NULL ,
[[lodgeenrol_match_student_id] [int] NULL ,
[lodgeenrol_moduleassoc_id] [varchar] (20) Not NULL )

DECLARE @v_sql VARCHAR(1000)

set @v_sql = 'BULK INSERT #lodgement_enrolment FROM ''' + @filename + ''' WITH (FORMATFILE =
''c:\lodgement.fmt'')'

exec(@v_sql)

Example format file:


8.0
18
1 SQLINT 0 50 "\t" 2 lodgeenrol_cps_no SQL_Latin1_General_CP1_CI_AS
2 SQLCHAR 0 50 "\t" 4 lodgeenrol_intake_no SQL_Latin1_General_CP1_CI_AS
3 SQLCHAR 0 50 "\t" 5 lodgeenrol_module_code SQL_Latin1_General_CP1_CI_AS
4 SQLCHAR 0 50 "\t" 6 lodgeenrol_module_name SQL_Latin1_General_CP1_CI_AS
5 SQLCHAR 0 50 "\t" 7 lodgeenrol_module_hours SQL_Latin1_General_CP1_CI_AS

The bulk insert command requires the user to be a member of the bulk admin fixed server role.
The user must also be the owner of the object they are inserting the data into. The command is
very fast and is well worth exploring. If you still have issues running the command, try and making
the user a dbowner of the tempdb database.

Java and SQL Server


In Oracle, we can store enterprise beans within the SGA via JServer (load and execute java
applications with the DBMS ), we can also write Java stored procedures and utilise JSQL. There
are not equivalent utilities or DBMS options in SQL Server for such native support. This may
change with the release of SQL Server .Net (Yukon).

66
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL Trace
The ORACLE DBA can utilise SQL Trace to write out performance statistics for statements being
executed for a session or all connection database sessions. This may typically involve the setup of
the trace parameters in the init.ora (SQL_TRACE, TIMED_STATISTICS, USER_DUMP_DEST etc),
and invoked from SQL*Forms, SQL*Plus, PL/SQL sub-routine and other methods, using commands
such as:

alter session set sql_trace true


or
DMBS_SESSION.SET_SQL_TRACE(TRUE);

The files produced are formatted via TKPROF.

In SQL Server, the DBA can utilise:

a) SQL Profiler GUI for tracing and the subsequent reading of trace data files. The GUI
may skip trace records depending on the load running against the database. This was
apparently was by design.

b) Use the T-SQL stored procedures to run the trace, these are stored in the master
system database.
a. sp_trace_create
b. sp_trace_setevent
c. sp_trace_setfiler
d. sp_trace_setstatus

67
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Query analyser (SQL*Plus)


The Query Analyser is the GUI version of isql.exe, and is initiated with isqlw.exe from the
command line. It is the equivalent to SQL*Plus in Oracle, even so, it does not include SQL*Plus’s
extensive formatting extensions such as REPFOOTER, BREAK, BTITLE, ATTRIBUTE, SPOOL, TTITLE
and its ability to parameterise and prompt for input. Some of these options are available within the
GUI but are not specific SQL or T-SQL statements. The experienced Oracle developer or DBA may
find this lack of equivalent functionality very frustrating.

Database Config Assistant / Oracle Admin Assistant etc


Use the SQL Server Enterprise Manager (EM).

Net8 Assistance / SQLNet


The listener in SQL Server is called the Server Network Utility. When instances are installed via
the setup disk, default listener entries are also created for named pipes and the TCP/IP (default
port auto-selected on first every connection via the protocol unless specifically set) protocols. Here,
the DBA can control the DB-Libraries used for establishing connectivity to the SQL Server instances
installed on the server.

Compared to Oracle, the listener configuration in SQL Server is simple and is generally an error free
process. The options available are somewhat restrictive though in terms on failure alternatives and
encryption etc.

68
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

UTLBSTAT, UTLESTAT, STATSPACK


Oracle DBA’s extensively uses these PL/SQL routines and associated packages for performance
tuning and reporting. The SQL Server DBA will utilise:

ƒ Profiler for statement tracing

ƒ NT Performance Monitor and the numerous SQL Server counters

ƒ 3rd party products from Quest, NetIQ and others.

SRVCTL
There is no equivalent to srvctl (manage ORAC environment via the command line) in Oracle. This
may be closer to the Cluster Manager utility in Windows and to a lesser degree SQL Server
Enterprise Manager.

Log Miner
There is no equivalent to log miner utility in Oracle. Consider 3rd party tools.

ISQL
ISQL is invoked on the command line with isql.exe, the GUI version is called “query analyser” and
is discussed later in this chapter. The command line version help is called by isql.exe -? or
isql.exe /?, the screen shown for a SQL Server 2k installation is:

isql: unknown option ?


usage: isql [-U login id] [-P password]
[-S server] [-H hostname] [-E trusted connection]
[-d use database name] [-l login timeout] [-t query timeout]
[-h headers] [-s colseparator] [-w columnwidth]
[-a packetsize] [-e echo input] [-x max text size]
[-L list servers] [-c cmdend]
[-q "cmdline query"] [-Q "cmdline query" and exit]
[-n remove numbering] [-m errorlevel]
[-r msgs to stderr]
[-i inputfile] [-o outputfile]
[-p print statistics] [-b On error batch abort]
[-O use Old ISQL behavior disables the following]
<EOF> batch processing
Auto console width scaling
Wide messages
default errorlevel is -1 vs 1

69
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

[-? show syntax summary (this screen)]

ISQL vs OSQL command line


Feature ISQL OSQL
Invocation isql.exe or osql.exe
isqlw.exe (query analyser)
Connectivity DB-Library ODBC (SQL Server ODBC
driver via SQL-92 connect
options)
Unicode output files No Yes
supported
OS Environment variables isqluser=.. osqluser=..
isqlserver=.. osqlserver=..
NT Authentication Mixed or NT Mixed or NT
Max command characters per 1000 1000
line
Call OS commands? Yes, use !! when running isql Yes, use !! when running isql
interactively interactively
Can read in files Yes, in interactive mode with :r
command.

70
4
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Backup and Recovery

A
s with any modern DBMS, SQL Server supports complete or full backups, differential
backups and transaction log backups (equivalent to archived log backups)

The key difference between Oracle and SQL Server is not so much the commands and
recovery models affecting the type of backup, but the number of backups required to
completely recover a database instance verses an individual database. Of course,
architecturally, backup and recovery is very different under both DBMS.

We will explore backup and recovery in SQL Server with a variety of scenarios.

Backup
As mentioned in the architecture section, a SQL Server instance consists of a number of system
databases, these, just like the system tablespace in Oracle, is essential for recovery. For the
instance to start, the system databases must be available. It is critical that full backups are
performed on a regular basis for your master, msdb, model and distribution (if replication enabled),
then of course, the users databases are just as important. We will cover backup and recovery in
some detail.

To make this section a little easier to put in context with Oracle:

ƒ Hot Backup – all full backups in SQL Server are HOT backups

ƒ Full Backup (shutdown instance and backup database files) – although possible, it is not
recommended, the full backup is typically used in all cases

ƒ RMAN – no equivalent in SQL Server. Closest option is Database Maintenance Plans but
these are simply wizards that generate scheduled jobs to make life much easier.

ƒ Import/Export (full) – no equivalent utility that is even close to Oracle’s. The best SQL
Server has database scripting (manually run) and BCP (bulk copy data). Oracle is way
ahead in this area.

ƒ Differential Incremental Backups (RMAN) – same in SQL Server

71
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ Incremental or Archived Log Backups – transaction log backup in SQL Server

REMEMBER – Treat the master, msdb, model and distribution databases as your system
tablespace data files and control files all mixed into one. They are critical in Oracle recovery
and are subsequently critical in SQL Server database instance recovery. The tempdb is rebuilt
from the model database on instance startup.

Recovery Interval
The recovery interval is set at an instance level and affects the checkpoint timeout period for all
databases in the SQL Server instance. This of course has flow on effects for instance recovery in
terms of the number of possible transactions SQL Server must rollback (uncommitted transactions)
and roll forward (committed but not written to the physical database data files) during its recovery
cycle on instance startup.

The default value is zero (SQL Server managed) or any value greater than zero in minutes and
when altered its value takes affected immediately. In a majority of circumstances leave the setting
at the default.

The value can be set via Enterprise Manager, or via a SQL statement:

exec sp_configure N'recovery interval (min)', 2


reconfigure with override

Trying to pre-empt the actual goings-on with the DBMS architecture in terms of this value is difficult
to predict and the SQL Server documentation is some vague. Use performance monitor counters to
monitor checkpoints and alter the recovery interval to review the impact to the instance, this may

72
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

take some time to be reflected. It is important to remember that performance monitor wont
measure instance recovery time which, in some circumstances, can effect your SLA if you are not
careful.

Number of pages flushed by checkpoint or


other operations that require all dirty pages
to be flushed.

In this case we are monitoring the default


instance, other instances will have their
own counters.

Recovery Models
Setting a recovery model is like the Oracle DBA tuning on or off archived log mode for the database
instance. In SQL Server, each database has a recovery model which determines what statements
are logged or not and if point in time recovery is possible. The models are:

a) Simple – transaction log (redo log) entries are truncated on completion of a


checkpoint. Point in time recovery is not possible. Equivalent to non archived log
mode in Oracle.

b) Full – transaction log entries are retained and the log file will grow until the DBA back’s
up the transaction log and flushed the committed log data to disk (archived log mode in
Oracle).

c) Bulk Logged – as per full but selected commands are not fully logged (therefore not
recoverable), these include select into, bcp and bulk insert, create index and indexed
view creation, text and image operations (write and update text).

The default system database recovery models are:

MASTER Simple (only full / complete backups can be performance on master)


MSDB Simple
MODEL Simple
TEMPDB Simple (recovery properties cannot be set for this DB)

Do not alter recovery model properties for any system database. Again the DBA can alter the
recovery model properties for user databases via Enterprise Manager or a SQL statement:

73
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ALTER DATABASE [BUYSMART]


SET RECOVERY SIMPLE

The alteration will take immediate affect. The DBA should issue a full backup and if using full or
bulk-logged options, continue with planned transaction log backups as need be.

Backup Devices
A “backup device” in SQL Server 2k is simply a logical name (alias) for a physical file that may be a
disk location (physical or UNC) or tape device. The device is visible to all databases within the
instance.

The device is not necessarily required, but is there for convenience and does allow backup scripts to
separate themselves from the physical location of data files. Altering a script to backup elsewhere
can be done by changing the destination of the back device.

74
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

exec sp_addumpdevice N'disk',


N'mydevice',
N'e:\dbbackups\mydevice.BAK'

The above dialog will run exec xp_fileexist "e:\dbbackups\mydevice.BAK" to verify the location and
warn the DBA accordingly.

The device has some flow on affects within the Enterprise Manager in terms of viewing their content
and selecting the device as a drop down item when backing up databases via the EM.

IMPORTANT – The Database Maintenance Plan wizards do not utilise these backup devices
for some strange reason.

RMAN
There is no equivalent utility to RMAN in SQL Server. Recovery must be either manually instigated
by the DBA within Query Analyser or its equivalent command line utility, or via Enterprise Manager
and its GUI screens. Backups are performed via Database Maintenance Plans or via t-sql scripts
that DBA has custom written.

Database Maintenance Plans


If you are just starting out with SQL Server and want to get backups up and running quickly, along
with some integrity checking, then consider database maintenance plans.

NOTE – Maintenance Plans are found under the Management folder within Enterprise
Manager.

The maintenance plan is simply a wizard that generates a series of MSDB jobs that are scheduled
and run by SQL*Agent. These jobs may include the following against one or more databases:

Database backups (full and log backups only)

a. Can specify auto-removal of media sets that are N


days/weeks/months/seconds/minutes old
b. Can specify destination directory and the option to auto-create sub-directories
for each database to be backed-up
b) Database re-organisation

75
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

c) Update database statistics


d) Shrink databases (remove un-used space)
e) Database integrity checks

For backups, SQL Server will create one media set per backup set. This means one physical disk
file (media set) backup and inside it, a single log or full backup (backup set). It will NOT append
backup sets to existing media.

NOTE – Many of these items can be scheduled individually, away from the backup job times.
Note that SQL Server will not warn you of overlapping jobs or the fact that another
maintenance job already exists of that type.

When it comes to backups, the maintenance plan can be a little restrictive though, consider some of
these:

ƒ no support for differential backups

ƒ many of the backup options are not available, namely the password parameter

ƒ can not duplex backup files (copy to another disk or server as part of the backup)

ƒ does not support appended backups to an existing backup device (media set)

NOTE – Natively, SQL Server does no built in mechanism for compressing or zipping backup
files. Consider writing your own backup t-sql stored procedure and using the xp_cmdshell
extended stored procedure.

The maintenance plan backup screens are shown below. Remember that this point we have already
selected the databases to be included in this overall maintenance plan (first screen of the wizard).

This screen is for FULL backups of


the selected databases. We can
optionally verify the backup.

Disk or pre-defined tape backups

Full backup schedule

76
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Always use a different directory to


that recommended. The SQL
Server path is too deep in the
directory structure.

Nice feature, will remove media sets


that are N days (and other options)
old and auto-create sub-directories
for each database.

The next screen is related to transaction log backups. Be warned here that not all databases you
have selected in the first screen may be privy to log backups and can result in failure of the
scheduled maintenance plan.

This screen and those


following it are basically
identical to the FULL
backup screens. The
default file extension is
TRN rather than BAK.

The DBA can review and alter the maintenance plan at any time by simply selecting properties for
the generated plan and editing it as need be within Enterprise Manager.

Data Dictionary Views (Media Sets, Backup Sets)

77
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

It is important to understand the difference between a media set and a backup set. These
concepts are used throughout the following sections and within the online help for SQL Server.

A physical backup device is the media set, within the media we can store one or more logical
backup sets of one or more databases (typically its all the same database). This is shown
below with their properties:

MEDIA SET (NAME, DESCRIPTION, PASSWORD, MEDIA-SEQUENCE)

BACKUP SET (NAME, SERVER, DATABASE, BACKUP TYPE, DATE, EXPIRES, SIZE, DESC)

BACKUP SET (NAME, SERVER, DATABASE, BACKUP TYPE, DATE, EXPIRES, SIZE, DESC)

Backup set

Media set
BACKUP DATABASE [mydb]
TO DISK = ‘e:\dbbackups\mydb\mydb_20020624_full.bak’
WITH INIT,
NAME = ‘Full Backup of MYDB on 24/06/2002’

78
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The backup information is recorded in the MSDB database, here is a snapshot of the physical data
model:
media_ backup
set_id _set_id
Backup Backup set Restore Restore_ Restore file
media set history history_id

media_ backup Restore_


set_id _set_id history_id

Restore file
Backup Backup file Log mark group
media history
family

The DBA should purge this information on a regular basis. I have personally found that recovering
a database via the GUI with a large number of backup records can result in a huge delay (4+
minutes at times) as you wait for the GUI to return control back to you.

set dateformat dmy


exec msdb..sp_delete_backuphistory ‘15/06/2002’ -- remove records older than date

NOTE – rather than using msdb.. (which tells SQL Server that it will find the stored procedure
in the msdb system database and use the dbo owner), we could have entered use [msdb]
before we ran the procedure that also sets the current database.

If you append backups to a media set then we refer to each appended backup via the FILE
option as you will see in the examples presented throughout the chapter.

Hot / Online (Full) Backups


A full backup in SQL Server is equivalent to a hot backup in Oracle. The database does not come
offline or unavailable to the end-user during a full backup. In terms of the entire SQL Server
instance though, full backups should encompass all system backups in order to successfully
recovery the entire instance. There is no single backup or recovery statement that will cover all
databases within the instance.

At a bare minimum the DBA should consider:

MASTER Full backups, nightly


MSDB Full backups, nightly
MODEL Full backups, nightly
<User DB> Full backups, nightly

The tempdb system database is rebuilt automatically to the destination defined in the sysdatabases
system table in the master database on instance start-up.

79
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The GUI is very simple to understand and is not worth discussing. In most cases the DBA will
create a Database Maintenance Plan to schedule and manage the full database backup.

An example full backup statement is:

BACKUP DATABASE [mydb]


TO DISK = ‘e:\dbbackups\mydb\mydb_20020624_full.bak’
WITH INIT,
PASSWORD = ‘my db password’,
NAME = ‘Full Backup of MYDB on 24/06/2002’

Processed 112 pages for database 'mydb', file 'mydb_Data' on file 1.


Processed 1 pages for database 'mydb', file 'mydb_Log' on file 1.
BACKUP DATABASE successfully processed 113 pages in 0.534 seconds (1.720 MB/sec).

BACKUP DATABASE [ANOTHERDB]


TO DISK = 'e:\anotherdb_20020603_full.bak'
WITH INIT,
NAME = 'Full Backup of ANOTHERDB on 03/06/2002',
EXPIREDATE = '03/06/2002'

If we tried to run the above command again we get the error below due to the expiration date we
have set. To get over this and still use the INIT option then we need to use the SKIP option as
well.

Server: Msg 4030, Level 16, State 1, Line 1


The medium on device 'e:\aa_20020624_full.bak' expires on Jun 3 2002 12:00:00:000AM and cannot be
overwritten.
Server: Msg 3013, Level 16, State 1, Line 1
BACKUP DATABASE is terminating abnormally.

NOTE – take a close look at the WITH clause syntax, the books online cover this command
very well and should be reviewed thoroughly.

The DBA should have a good understanding of all backup and recovery options, but some of
the key items are:

• TO [DISK, TAPE] = ‘<backup device name or physical location>’


o Logical of physical location for the database backup to be place
• WITH INIT
o Force overwrite of the backup file if its exists
• WITH NOINIT
o Will “append” the backup to the existing backup set within the media.
• MEDIA[name, password, description]
o These options set the name, description and password for the entire media, a
backup media (disk or tape) can contain one or more backup sets
• FORMAT, NOFORMAT
o Format renders the entire media set un-usable and ready for new backup sets.
Does NOT preserve the media header.
o No-format tells SQL Server to retain the existing media header. It will not
overwrite the media device unless INIT is also used.

80
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

• EXPIREDATE = <date>, RETAINDAYS = <number of days>


o Prevents the overwriting of a backup based on the expire date and retain days
parameters.
• BLOCKSIZE = <bytes>
o If media requires backups to be of a specific block size in order for a restore
from that media to be successfully read.

The Enterprise Manager GUI is a little restrictive when it comes to restoring database backups when
the PASSWORD option has been used. It does not give you the option to specify it and comes up
with the error:

Differential Backups
The differential backup will backup any 64Kb extent that contains an altered page within the
database. Remember this when viewing the backup size of the media set as you may be surprised.
The tracking is managed by the SQL Server storage engine using the DCM (differential change
map) page present in each non-log data file. In Oracle, differential backups are known as
differential incremental backups that are supported within RMAN and it is also possible to do
cumulative database exports.

A differential backup is not supported in Database Maintenance Plans (should change in the next
version of SQL Server), therefore the DBA needs to resort to writing their own scripts that can be a
right pain. In many cases, full and log backups will suffice, but can slow the recovery process
when applying large numbers of archived log files. This is where differentials can be used to speed
the recovery process. The DBA will need to do their own performance tuning to determine if
differentials are required to meet their recovery SLA.

Here is an example differential backup:

BACKUP DATABASE [mydb]


TO DISK = ‘e:\dbbackups\mydb\mydb_20020624_full.bak’
WITH DIFFERENTIAL,
INIT,
NAME = 'Differential Backup of MYDB on 24/06/2002'

The differential backup will backup all extents modified since the last full backup, and NOT the last
differential. This is very important to understand, especially during recovery. The last differential
backup done must be used on recovery; they are not cumulative as log backups are.

81
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

To get these backups up and running quickly, write a T-SQL stored procedure and an associated
DTS to call it with an email notification for error tracking. Then simply schedule the package to run
as required.

Important – You cannot use differential backups to do point-in-time recovery (i.e. the STOP
AT clause is not valid to recover to a point in time for the period the differential backup
covers).

Archived Log (Transaction Log) Backups


Transaction log backups are the same as archived redo log backups in Oracle. Remember that a
transaction log exists for each database within the SQL Server instance and is a mandatory
requirement for the database to exist. The log backup is supported via Maintenance Plans, making
it very simple for the DBA to quickly set up full backups with scheduled log backups.

The database must be in full or bulk-logged recovery modes before attempting a transaction log
backup. If not you will receive the error:

Server: Msg 4208, Level 16, State 1, Line 1


The statement BACKUP LOG is not allowed while the recovery model is SIMPLE. Use BACKUP DATABASE or
change the recovery model using ALTER DATABASE.
Server: Msg 3013, Level 16, State 1, Line 1
BACKUP LOG is terminating abnormally.

Attempting to backup the log file for the master database will result in the error:

Server: Msg 4212, Level 16, State 1, Line 1


Cannot back up the log of the master database. Use BACKUP DATABASE instead.
Server: Msg 3013, Level 16, State 1, Line 1
BACKUP LOG is terminating abnormally.

You can alter the recovery modes of the MSDB and MODEL databases if you like and do transaction
log backups, but it is not recommended unless there is an important requirement to do so.

Attempting to backup the log file for the tempdb database will result in the error:

Server: Msg 3147, Level 16, State 1, Line 1


Backup and restore operations are not allowed on database tempdb.
Server: Msg 3013, Level 16, State 1, Line 1
BACKUP LOG is terminating abnormally.

Do not attempt a full or differential backup whilst a transaction log backup is running as it may
result in error. Even so, Microsoft documentation states that concurrent full and log backups are
compatible.

There are several important parameters the DBA should understand when using log backups. Note
that many of these parameters are NOT available when creating maintenance plans, therefore, for
the advanced DBA this may be too restrictive.

BACKUP LOG [mydb]


TO DISK = 'c:\master.bak'
WITH <see books online for comprehensive list of parameters>

82
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Parameter Notes
NO_TRUNCATE Special parameter used when database is in a damaged state,
allows us to attempt a log backup without truncating the virtual log
files. This is important if we are still trying to recover the instance
whilst we attempt to build another (i.e. standby database).

NOTE – Remember that the databases transaction log will continue to fill as committed and
non-committed transactions execute against the database. The backup transaction log will
write (archive in Oracle) all committed transactions to your selected transaction log backup file
(an archived log).

The DBA can truncate the transaction log via the WITH NO_LOG or WITH TRUNCATE_ONLY option.
This is used in a variety of situations, the classic being when you accidentally used the full or bulk-
logged recovery model when you didn’t want transactions permanently logged for point in time
recovery and now the log has grown and typically results in full transaction log errors. This
command will remove all non-active transactions from the log, from there, the DBA can think shrink
the log files and change the recovery model as need be.

BACKUP LOG [mydb] WITH TRUNCATE_ONLY

Remember - you cannot selectively truncate transactions in the log file, it’s all or nothing.
The DBA must do a full backup as you cannot recovery through a truncate (as you would
except).

Tablespace (Filegroup) Backups


The DBA can also do tablespace (file-group) backups, although fine I rarely use them as it typically
complicates recovery. Even so, for very large databases this may be the only option. Here is an
example:

BACKUP DATABASE [mydb]


FILE = N'myprimarydatafile', -- logical filename of physical file
TO DISK = N'C:\mydb_fg_myprimarydatafile.bak' -- backup destination
WITH
INIT ,
NOUNLOAD ,
NOSKIP ,
STATS = 10,
NOFORMAT

NOTE – Your database must be using the full or bulk-logged recovery model

83
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Moving DB &Transportable Tablespaces


The DBA can move or copy databases via the sp_attach and sp_deattach commands. This works
on all database files, not selected file-groups. At present, SQL Server has no equivalent option to
Oracle’s transportable tablespaces, the closest option we have here is to backup and restore file-
groups. Even so, we have a variety of other options:

a) Shutdown instance, copy database files, and re-attach at destination server


b) Offline the database, copy files, and re-attach at destination server.
c) De-attach the database, copy files, and re-attach at destination server.
d) Run a split mirror, offline or read-only the database, break the mirror and get the
e) live database back up and running whist you work with the split mirrored files in the
background.

Some of these methods are described below.

Remember - copying a database will not take the logins with it, as this information is stored
in the master database.

Remember – If you have not database backups, but still have all the database files, the re-
attaching the database will be your last remaining hope to recovering your database.

Shutdown instance method

Simply shutdown the SQL Server instance, taking care when running multiple instances on the
same server. When down, copy the database files to the other server (or copy/rename/move if it
will be attached to the same server). As the database was cleanly shutdown there will be no issues
with re-attaching so long as the copy and destination did not fail unexpectedly. If the instance did
fail unexpectedly and you have no backups, re-attaching may still be possible (with the added risk
of data corruption).

When using this method, the database will of course remain on the source server with no change
what-so-ever to the source database.

To shutdown the instance use one of the following:


a) use NET STOP service command from the operating system
b) use Enterprise Manager and their GUI option
c) issue the SHUTDOWN transact-SQL command
d)

Offline a Database method

Once the database is “offline”, you can copy its database files to a new server and re-attach.
Use this method when shutting down the SQL Server instance is not desirable and you want to
retain the database on the source server.

Reminder – User sessions will not be disconnected; this is applicable for sp_dboption and the
ALTER database command.

84
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

To take the instance offline:

exec sp_dboption N'mydb', N'offline', N'true'


or
alter database [mydb] set offline with rollback after 60 seconds
or
alter database [mydb] set offline with rollback immediate
or
DBCC DBCONTROL (mydb,offline)

Using the alter database statement (SQL Server 2k and beyond) is the preferred method. The
rollback after statement will force currently executing statements to rollback after N seconds. The
default is to wait for all currently running transactions to complete and for the sessions to be
terminated. Use the rollback immediate clause to rollback transactions immediately.

When running the command with users connected you will get something like:

sp_dboption (does not wait like the alter database command, see below)

Server: Msg 5070, Level 16, State 2, Line 1


Database state cannot be changed while other users are using the database 'mydb'
Server: Msg 5069, Level 16, State 1, Line 1
ALTER DATABASE statement failed.
sp_dboption command failed.
alter database [aa] set offline [any parameter combination]
This command will run forever, waiting for sessions to disconnect. When it completes you will get something
like:
Nonqualified transactions are being rolled back. Estimated rollback completion: 100%.

See the script http://www.sqlservercentral.com/scripts/scriptdetails.asp?scriptid=271 to kill off all


connections for a database.

To confirm the offline status:

SELECT DATABASEPROPERTY('pubs','IsOffline') -- 1 if yes


or
SELECT DATABASEPROPERTYEX('mydb', 'Status')

Attempting to connect to the database will give you:

Server: Msg 942, Level 14, State 4, Line 1


Database 'mydb' cannot be opened because it is offline.

De-Attaching the database

If you want to completely remove the database from the master database and the SQL Server
instance, use the deattach command rather than offlining the database.

When attempting to de-attach with Enterprise manager it will warn you when:
a) there are users connected to the database
b) replication is active

85
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

All user sessions must be disconnected and replication disabled before attempting the de-
attachment. The command is:

exec sp_detach_db N'mydb', N'false'

The second parameter denotes wether to include a statistics collection before de-attaching the
database. You must be a member of the sysadmin system role to issue this command. Also note
the error:

Server: Msg 7940, Level 16, State 1, Line 1


System databases master, model, msdb, and tempdb cannot be detached.

Funny enough, statistics are still updated before receiving this error.

The de-attachment will remove the database from the sysdatabases table in the master database.
The sysxlogins table will retain references to the de-attached database, therefore, you will need to
either remove the login(s) or alter their default database connections, this is shown below.

exec sp_defaultdb N'myuser', N'master'


change default db from myuser to the master database.
exec sp_droplogin N'mytest'

Dropping logins is not straight forward, you need to either orphan the login from its associated
database user or drop the user, otherwise you will get this message:

Server: Msg 15175, Level 16, State 1, Procedure sp_droplogin, Line 93


Login 'myuser' is aliased or mapped to a user in one or more database(s). Drop the user or
alias before dropping the login.

You cannot remove users that own database objects, the standard drop user command is:

use [mydb]
exec sp_dropuser N’myuser’

Checking Files before Attaching

You should note that you cannot re-attach more than 16 files for a single database. Before
attaching the database, issue the following commands over the primary file-group data file to get a
listing of files that make up the database structure:

--Is the file a primary file-group MDF file?


dbcc checkprimaryfile (N'E:\SQLServerData\MSSQL\Data\mydb_Data.MDF', 0)

--Get me the database name, version and collation


dbcc checkprimaryfile (N'E:\SQLServerData\MSSQL\Data\mydb_Data.MDF', 2)

--Get a list of all files associated with the database. (original name)
dbcc checkprimaryfile (N'E:\SQLServerData\MSSQL\Data\mydb_Data.MDF', 3)

Attaching the database

86
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The sp_attach_db command allows you to re-attach your database onto the SQL Server instance.
For example:

exec sp_attach_db
N'mydb' ,
N'E:\SQLServerData\MSSQL\Data\new_aa_Data.MDF',
N'E:\SQLServerData\MSSQL\Data\new_aa_Log.LDF'

The syntax is simple enough, the first being the name of the database to attach and its associated
database files you have checked via the methods outlined previously. The database being attached
must not already exist, you can also attach databases not previously de-attached so long as the
database was closed successfully.

Server: Msg 1801, Level 16, State 3, Line 1


Database 'mydb' already exists.

After re-attaching, especially if its on different server, you will need to fix orphaned logins via the
command:

exec sp_change_users_login <see SQL Server BOL for parameter list>

Attaching a single file

The sp_attach_single_file_db command is quite powerful. It allows you to re-attach a database my


specifying only its initial master data file, if your database had other data files (even in the primary
file-group) they will be automatically re-attached (only to their previous destination though) for you
by reading the sysfiles. This is all fine if you want the data files restored to the same location from
which the database once existed along with the physical file name, but apart from that you have no
control and will need to opt for sp_attach.

When re-attaching with this command, you have the ability for SQL Server to automatically
recreate your log file so long as it’s not available for SQL Server to automatically re-attach when it
looks up sysfiles. This method is handy when you want have massive log file and want to shrink it
back to a manageable size. For example:

exec sp_attach_single_file_db N'MyxxDb' , N'E:\SQLServerData\MSSQL\Data\xx_Data.MDF'

<..shows the message below..>

Device activation error. The physical file name 'e:\sqlserverdata\MSSQL\data\xx_Log.LDF'


may be incorrect. New log file 'E:\SQLServerData\MSSQL\Data\xxxx_log.LDF' was created.

The new file size E:\SQLServerData\MSSQL\Data\xxxx_log.LDF will be 512k.

This will not work if you have multiple log files thought, you will get an error like:

Server: Msg 1813, Level 16, State 2, Line 1


Could not open new database 'mytest'. CREATE DATABASE is aborted.
Device activation error. The physical file name 'e:\sqlserverdata\MSSQL\data\mt_Log.LDF'
may be incorrect.
Device activation error. The physical file name 'e:\sqlserverdata\MSSQL\data\mt_2_Log.LDF'
may be incorrect.

87
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

In this example, the database had a single data file with two log files. When I have only one file the
attachment works file and re-creates the log in the destination of the previous file (but has a
modified size). Two or more files will result in the error.

Some issues with MODEL and MSDB databases

To detach the model or msdb system databases, you need to set the trace flag –T3608 on instance
startup. In all cases you must attach the model before the msdb database, remembering that
SQL*Agent for the instance must be stopped. As a side note, the attach command executes
something like the following:

CREATE DATABASE [mydb] ON


(FILENAME = ‘C:\dbdata\mydb\mydb_data.mdf’,
FILENAME = ‘C:\dbdata\mydb\mydb_log.ldf’)
FOR ATTACH

The create database command has dependencies on the model database, therefore affecting it’s re-
attachment.

Fixed dbid for system databases

The DBA should also be aware of the master..sysdatabases system table and its value for dbid for
system databases. In some very rare occasions, it is possible that a restore results in a corruption,
or “mixup” in the dbid for the database, this may occur when restoring databases in the wrong
order. The flow on effect is some very strange errors and confusion all round. See reference (57)
for a great example of this.

The dbid for system databases are:

1 Master

2 Tempdb

3 Model

4 Msdb

88
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Scripting Databases
The only option here is via Enterprise Manager. Right click properties on any database and the
following GUI is shown:

The screen is simplistic and requires no explanation but there are a few things to remember:
a) You must select objects (tables, views) in order to script
indexes/triggers/constraints/permissions. You cannot “generically” script all indexes for
example without selecting all tables/views first. This can be a pain as you need to filter
out what you need from the generated script.
b) You cannot script many databases at once
c) You cannot script logins specific to database (i.e. logins that map to a single user in one
database – typically the one you are scripting). You cannot script the sa login.
d) You cannot script linked or remote servers.

Use the preview option to view the generated script in mini-dialog windows (which you can cut
into the clipboard from).

89
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The diagrammer is also another handy place to generate scripts. As an example, if you need to
make a variety of schema changes, and then create a new (or use an existing) diagram, save,
make you changes and then hit the script button (see below). Once copied, you can apply the
changes as need be to the database. You can then use the saved script to apply on other identical
databases (i.e. test / support / prod databases) to mimic the changes and/or new objects.

You can cut the


scripted text from
here into notepad.

One of the key problems with the diagrammer is that you cannot allocate object permissions whilst
editing tables. This can adversely complicate your script generation ideas.

NOTE – Be careful with generated scripts from the diagrammer, it can take the long route to
a simple change that can result in heartache for the DBA if the takes are very large. Always
review the generated script before running. In all cases though, in my experience EM has
never generated a script with errors.

If you select the “design table” option and alter the table, the same script option is available to the
DBA. Note that this is not the case for “design view” although the SQL statement is selectable.

90
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Another method for scripting is via EM and its listing pf tables, for example:

Select objects in
Enterprise Manager,
CTRL-C to copy.

Run Query Analyser, open a new


connection, and paste, a script is
generated for the selected objects.

Backup control file to trace


There is no control file so it is not applicable. The closest equivalent is doing a full backup of the
system databases.

Verifying Backups
To verify a backup, use the command:

restore verifyonly from ‘c:\myfullbackup.bak’

The DBA can also load the backup history in the backup file into the MSDB database. This can
be handy when analysing the backup before attempting a recovery.

91
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Recovery
Recovery in Oracle is either:
a) manual via svrmgrl / sqlplus
b) via RMAN
c) via 3rd party product
d) Enterprise Manager

In SQL Server, we use variety of methods:


a) rebuildm.exe (from setup CD for rebuilding the system databases)
b) Enterprise Manager and its GUI wizards
c) Query Analyser (GUI or command line version)
d) SQL Server Service Control Manager

Recovery is potentially more complex that Oracle at times due to the fact that we are not
dealing with one database, but many system databases then associated user databases. This
section provides a summary by example in which the DBA can then base further tests to drill
down into this very important topic.

NOTE – Many of the examples use the GUI tools and at times, with reference to the
equivalent T-SQL command.

Killing User Connections and Stopping Further Connects

Killing off user connections is simple enough and there are endless scripts on the internet to do the
job. An example script by ruba.kumar@aurumtechnology.com is shown below:

CREATE PROC Kill_Connections (@dbName varchar(128))


as
DECLARE @ProcessId varchar(4)
DECLARE CurrentProcesses SCROLL CURSOR FOR
select spid from sysprocesses where dbid =
(select dbid from sysdatabases where name = @dbName )
order by spid FOR READ ONLY

OPEN CurrentProcesses
FETCH NEXT FROM CurrentProcesses INTO @ProcessId

WHILE @@FETCH_STATUS <> -1


BEGIN
--print 'Kill ' + @processid
Exec ('KILL ' + @ProcessId)
--Kill @ProcessId
FETCH NEXT FROM CurrentProcesses INTO @ProcessId
END

CLOSE CurrentProcesses
DeAllocate CurrentProcesses
GO

Also consider the command to more elegantly terminate users and closing off the connection:

92
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ALTER DATABASE mydb


SET SINGLE_USER WITH [<termination clause>]

eg:

ALTER DATABASE mydb


SET SINGLE_USER WITH ROLLBACK IMMEDIATE

To stop further connections, consider altering the database to dbo access only, or disable the
database logins via sp_denylogin (NT logins only).

Remember – you cannot restore a database whilst users are connected.

Using the GUI for Recovery


Unless you have major system database problems (which require additional steps before running
EM), the DBA will find that using EM for recovery is the most simplistic approach. The best thing
about the GUI when it comes to recovery is the reading of the MSDB sys backup tables and
correctly listing out the backup files to be used in a recovery scenario. Later, we will discuss a
script I wrote some time back that does a similar thing.

Name of the database, we can enter a new


name if required. Click on the options tab
if you do to double check the name of the
database files and the destination

For the selected database in the drop


down above, is listed the date of all full
backups.

From this full backup selected above, the


MSDB is searched and lists, in hierarchical
order its proposed restore list to do a
complete recovery. We can select the
option to restore to a point in time if
available.

The DBA can uncheck the appropriate


backup files as need be. Note that we
cannot alter the destination of the backups
listed which can be very restrictive.

NOTE – When using EM for recovery, run profiler at the same time to trace the T-SQL
recovery routines being executed. This is the best way to learn the recovery commands and
the context in which they are being used.

93
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

WARNING – If you restore a database, say, Northwind, and restore it as a different name
(database), then be careful when removing the new database. It will ask if you want to
remove all backup history, if you say yes then kiss good-bye to the Northwind databases
MSDB backup entries.

We will cover some of the GUI options in brief. Remember that virtually ALL restore
operations require no users to be connected to the database.

Options - Leave database in non-operational state but able to restore additional logs

This option allows us to restore the instance to any specific point, but leave it in a state where we
can apply further backups as need be.

Selecting properties of the restored instance in loading state gives us the error:

If you realise that you have no further backups and want to complete the recovery of the instance,
then (note that exec sp_helpdb will not show the database):

SELECT DATABASEPROPERTY('aa', N'IsInRecovery')


SELECT DATABASEPROPERTYEX('aa', 'status')

restore database aa with recovery

RESTORE DATABASE successfully processed 0 pages in 1.178 seconds (0.000 MB/sec).

A instance re-start will also issue the recovery statement. The non-operational state simply
executes the with norecovery option on restore of the last specified backup file.

Options – Using the Force restore over existing database option

Using EM can be a tad strange when restoring databases. If you attempt to restore the currently
selected database, it will never prompt you that you are trying to overwrite an existing databases

94
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

data files, even though (technically speaking here), you are! If we attempted to restore say the
northwind database as the pubs database, we will be promoted with the following dialog:

It seems be to something related to the MSDB backup and restore tables which determines
whether or not this dialog is shown. Anyhow, to get around this, we click on the options tab and
select the Force restore over existing database option.

The command is not different to a standard restore, there is no magical restore option related to
the prevention of file overrides.

RESTORE DATABASE [bb]


FROM DISK = N'c:\northwind_full.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, RECOVERY ,
MOVE N'Northwind_log' TO N'C:\dblog\bb_log.ldf',
MOVE N'Northwind' TO N'C:\dbdata\bb_data.mdf'

Be very careful with this option in EM. Personally, I never use it unless I am 100% sure that
the files I am writing over are fine and I have already backed them up if possible.

Restoring a databases backup history from backup files


In this example we have the following database, with associated backups:

Database: mydb
Data and Log files: c:\mydb.mdb, c:\mydb.ldf
Backups:

Full c:\mydb_full.bak
Diff c:\mydb_diff.bak
Log c:\mydb_log1.bak
Log c:\mydb_log2.bak

On selecting the restore in EM for the database, it magically lists all backups for a successful
restoration of my database up to the point of mydb_log2.bak. If we lost this information, then
suddenly our nice GUI dialog is not so helpful anymore.

To re-populate the MSDB database tables with the backup history I recommend that you do
not use the GUI, it is overly time consuming for such a simple task:

RESTORE VERIFYONLY FROM DISK = N'C:\mydb_full.bak' WITH NOUNLOAD , LOADHISTORY


RESTORE VERIFYONLY FROM DISK = N'C:\mydb_diff.bak' WITH NOUNLOAD , LOADHISTORY
RESTORE VERIFYONLY FROM DISK = N'C:\mydb_log1.bak' WITH NOUNLOAD , LOADHISTORY

95
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

RESTORE VERIFYONLY FROM DISK = N'C:\mydb_log2.bak' WITH NOUNLOAD , LOADHISTORY

NOTE - if you backup media had multiple, appended backups, then you may also need to
use the WITH FILE = option.

Once done, using the EM restore option, we select the database and work off the restore
history to pick the best plan for restoration.

Remember, before restoring, always double check the database name and the options, ensuring
paths and names are correct.

Restore cannot fit on disk


This is a classic problem. Basically, your attempt to restore a backup results in an out of
space error and asks you to free more space before re-attempting the restore. In this
particular scenario, SQL Server wants to restore the database files to the same size as at the
time when they were backed up. There is no option to alter the physical file size (i.e. shrink)
during the restore.

The general recommendation here is the shrink the database before any full backup to reduce
the possibility of this error. If that doesn’t work, try and restore and move files as best you
can to distribute the space amongst many disks, then shrink after the restore, backup and try
to restore again with a more appropriate placement of database files.

Restore uses “logical” names


In the examples presented below, the restore operations work over the logical name for each
database file being restored (where this is appropriate of course). If you do not know the
logical name of the physical files or the name of the file-group, then you will have some
problems successfully restoring. Apart from using the GUI, we can execute the command:

restore filelistonly from disk='c:\mydb.bak'

Also review the commands:

96
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

restore headeronly from disk='c:\mydb.bak'


restore labelonly from disk='c:\mydb.bak'

Restoration by Example

Restore Master Database


Restoring the master database is not fun but does occur in rare circumstances. In this scenario we
need to restore back to the last full backup of the master database as a variety of logins have
disappeared and some configuration changes have been made, so we are sure that the restore will
assist in resolving the problem.

1. Backup the existing master database and verify the backup


i. Copy the back to another server and also to tape where possible
2. Attempting to restore from EM will give you this:

3. Kick off all users, and shutdown the instance.


4. Alter the service properties to force instance startup in single user mode by
entering –m in the startup options for the service.

5. Leave the service window open


6. Run EM, connect to the instance and open the restore database dialog for the
master database. Here, we have selected the backup to be restored and
ensured beforehand that the file is ready and available.

97
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

7. On successful restore, the following dialog is shown. Go back to the service


control window and remove the –m single user mode option and re-start the
service.

8. Close and reopen EM, connecting to the instance. Check the SQL Server error
logs on failure to start the instance.

This example is simplistic and there are scenarios where this operation can create further problems.
The key issue here is that the master database includes a variety of system tables, with the file
paths for the model and msdb and tempdb system databases. If you restore the master (which
stops your instance immediately), and attempt to re-start, unless those paths are still valid, the
instance will not start.

Consider the rebuildm.exe command (rebuild master) to assist in restoring back to a state where at
least the instance starts and then you can recover each system database thereafter.

98
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Restore MSDB and Model Databases


For a system database, this is simplistic and painless. The DBA must shutdown SQL*Agent before
attempting a restore. Once done, double check via exec sp_who2 and connections to the MSDB
database, they must be disconnected before attempting the restore.

Restoring the MODEL database is like any other user database.

The DBA should restore MODEL before MSDB.

Suspect Database
A database may become suspect for a variety of reasons, such as device errors, missing files
etc, or another process (like a 3rd party backup program) has a lock on the database files
during instance startup etc.

Within EM you will see this:

First of all, check the error logs to better gauge the extent of the problem. In this particular case
the error is:

Starting up database 'Northwind'.

udopen: Operating system error 32(error not found) during the creation/opening of physical device
C:\Program Files\Microsoft SQL Server\MSSQL$MY2NDINSTANCE\data\northwnd.mdf.

FCB::Open failed: Could not open device C:\Program Files\Microsoft SQL


Server\MSSQL$MY2NDINSTANCE\data\northwnd.mdf for virtual device number (VDN) 1.

If the physical device is missing, then a simple restore is required with the move option.
This is assuming we cannot quickly resolve the error otherwise. The DBA may need to use a
third party utility to determine if another process has the file open, there are many available
on the internet for example www.sysinternals.com. If the file is “open” but the process is
orphaned for whatever reason, we can attempt:
a) Attempt to kill off the rough process holding the file open and stop/start of the instance
b) Attempt to run: exec sp_resetstatus ‘northwind’
c) Reboot of the server

WARNING – Before attempting any recovery or change of database status, always


shutdown the instance and backup the database files.

99
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

On any change of DB status related to recovery, the DBA should run the following on the
database :
dbcc checkdb
dbcc newalloc
dbcc textall

IMPORTANT - I should iterate that suspect databases must be carefully analysed, in some
cases I have found that, for some unexplained reason (i.e. no error log entries) the instance
starts and a user database is in suspect mode. If you have verified the existence of all
database files, then attempt to re-attach the database via the sp_deattach and sp_attach
commands. Always backup the database files before attempting any sort of recovery.

The DBA may also consider deattaching the suspect database (via EM is fine). Go to your file
system, move the missing files if need be and return back to EM and run the attach database
wizard. In the wizard window, you will see red crosses where the file name/path is invalid,
alter the path/filenames, set the “attach as” and set the owner to “dbo” (very rare that is not
dbo) and the database should be successfully re-attached and operational.

Database is in “Loading” Mode ?


The DBA may see something like this:

This typically occurs when the database has been restored to an inconsistent state in which it
is still pending full recovery. Attempting complete recovery may give you something like:

restore database nonefs with recovery

Server: Msg 4331, Level 16, State 1, Line 1


The database cannot be recovered because the files have been restored to inconsistent points in
time.

Verify your order of restore carefully before attempting the restoration again.

Restore with file move

Here is a simple example:

RESTORE DATABASE [nonefs] FROM DISK = N'C:\aa.bak'


WITH FILE = 2,
NOUNLOAD ,

100
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

STATS = 10,
RECOVERY , MOVE N'nonefs_Log' TO N'f:\nonefs_Log.LDF'

Restore a specific File Group


Database: mydb
File-group name Physical file-name
mydb_primary c:\mydb_system.bak
mydb_data c:\mydb_data.bak
mydb_index c:\mydb_index.bak
N/A c:\mydb_log.ldf

Backups:
C:\mydb_full.bak Full
C:\mydb_log1.bak Log
C:\mydb_diff1.bak Differential
C:\mydb_log2.bak Log
C:\mydb_log3.bak Log
{failure occured}

If mydb_data file-group failed (the logical name of the filegroup and the logical name of the
file are the same in this case), we need to restore:

-- File Group from FULL backup


RESTORE DATABASE [mydb]
FILE = N'mydb_data', -- logical name of the file in the FG
FILEGROUP = N'mydb_data' -- thisis optional if only 1 file in the FG
FROM DISK = N'C:\mydb_full.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, NORECOVERY

-- Log backup @ time 1, restore logs as normal


RESTORE LOG [mydb]
FROM DISK = N'C:\mydb_log1.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, NORECOVERY

-- Log backup @ time 2


RESTORE LOG [mydb]
FROM DISK = N'C:\mydb_log2.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, NORECOVERY

-- Log backup @ time 3


RESTORE LOG [mydb]
FROM DISK = N'C:\mydb_log3.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, RECOVERY

Adding or Removing Data Files (affect on recovery)

Following on from the above, we consider the situation where a database file has been added to the
database between transaction logs. Therefore we have this scenario:

Backups:
C:\mydb_full.bak Full backup

101
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

C:\mydb_log1.bak Log backup


-- new file added to database
ALTER DATABASE mydb
ADD FILE
(
NAME = mydb_newfile,
FILENAME ='c:\mydb_newfile.mdf',
SIZE = 1MB,
FILEGROWTH = 10%
)
GO

C:\mydb_log2.bak Log backup


{failure occured}

To restore we need to:

RESTORE DATABASE [mydb]


FROM DISK = N'C:\mydb_full.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, NORECOVERY

RESTORE LOG [mydb]


FROM DISK = N'C:\mydb_log1.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, NORECOVERY

RESTORE LOG [mydb]


FROM DISK = N'C:\mydb_log2.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, RECOVERY

The completed restore will show the newly added file with no further issues. Be aware though,
Microsoft Support document Q286280 states otherwise, and there may be a scenario where the
above does not work. Revise this support document for assistance.

Emergency Mode
This mode is undocumented and is technically unsupported, but is required on very rare
occasions. This mode allows the DBA to access a database without the log file being present.

-- Allow updates to sys tables


exec sp_configure N'allow updates', 1
reconfigure with override

-- If possible, attempt to set db in DBO only access mode (for safety sake)
exec sp_dboption N'Northwind', N'dbo use', N'true'

-- Record the existing record entry for the database


SELECT * FROM master..sysdatabases WHERE NAME='northwind'
-- Set DB into emergency mode
UPDATE master..SYSDATABASES SET STATUS=32768 WHERE NAME='northwind'

Stop and Re-start MSDTC.

-- Refresh Enterprise Manager

102
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Attempting a backup or any other operation that uses transactions will result in the error:

To export out the data and associated objects, create a blank database in the same or another
database instance. Once done, run the Export wizard, select the database in emergency mode and
follow the prompts. A DTS will be created and will happily export the database, typically, without
error so long as there are no underlying permission issues.

Drop the source database as need be.

This is a very simplistic example but provides some direction towards dealing with the problem.

NOTE – Setting a database to emergency mode is very handy when suspect databases wont
allow you to investigate the problem via DBCC commands etc. Altering the status to
emergency mode and then running, say, DBCC CHECKDB will allow you access to the
database and a variety of commands to resolve the problem.

Restore Full Backup


A full database restore can be as simple or as complex as you like. I very rarely backup direct
to tape or individual file groups as I have always had the free disk space. For user databases,
I tend to opt for EM as its simple and quick. Before restoring always check:
a) can I backup the database before the restore? (i.e. yes)
b) notification of end-users and killing sessions
c) database name
d) location and name of the files
e) remembering to fix orphaned logins if restoring to another server
f) re-checking the database recovery model and associated options
g) verifying subsequent backups will still operate as per normal
h) always write down in a log what you did, why and the files used.

No example is required for this scenario.

103
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Partial (stop at time) PITR Restore on a User Database


To restore to a point in time, ending at a specific transaction log backup in your backup sequence,
we use the STOPAT command, for example:

RESTORE LOG [mydb]


FROM DISK = N'C:\mydb_log2.bak'
WITH FILE = 1, NOUNLOAD , STATS = 10, RECOVERY ,
STOPAT = N'8/08/2002 9:42:02 PM'

Use the GUI, or the commands:

restore headeronly from disk = 'C:\mydb_log1.bak'


restore headeronly from disk = 'C:\mydb_log2.bak'

and the backupfinishdate column to determine the most appropriate log file to be used.

Corrupt Indexes (DBMS_REPAIR)


The DBA should be regularly running the following against all databases:

DBCC CHECKDB

DBCC TEXTALL

DBCC CHECKCATALOG

DBCC CHECKALLOC

These routines will report on allocation inconsistencies with tables and indexes that typically point
at data corruption. Even so, don’t be too quick to react. Before doing anything always full backup
the existing databases and try the following:
DBCC CHECKDB(‘mydatabase’, REPAIR_REBUILD)

a. Kill off all users or wait till they disconnect


b. exec sp_dboption 'northwind', 'SINGLE_USER', 'on'
c. DBCC CHECKDB('northwind', REPAIR_REBUILD)
d. exec sp_dboption 'northwind', 'SINGLE_USER', 'off'

b) As above, but try DBCC CHECKALLOC

IMPORTANT – Do not use dbcc dbrepair

If you are getting desperate, Microsoft has an undocumented command (typically suggested by
Microsoft support) called sp_fixindex. Before running this restart the instance in single user mode,
checkpoint, run sp_fixindex, checkpoint again and backup once more. Re-start the instance and re-
run the DBCC routines once more.

See Microsoft support document Q106122 for more information.

104
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Reinstall NORTHWIND and PUBS


Run the scripts found in the /install directory for the instance:
Instnwnd.sql
Instpubs.sql

Other Recovery Scenarios


Scenario 1 - Lost TEMPDB Database

If you delete the tempdb and templog databases files, they are simply re-created on instance
startup, assuming of course the model database is available and the disk sub-system:

It is created based on the entry in master..sysdatabases

use tempdb
go
sp_helpfile
go

The DBA can move this location via the commands below and re-starting the instance.

use master
go
alter database tempdb modify file (name = tempdev, filename = 'c:\tempdb.mdf')
go
alter database tempdb modify file (name = templog, filename = 'c:\templog.ldf')
Go

File 'tempdev' modified in sysaltfiles. Delete old file after restarting SQL Server.
File 'templog' modified in sysaltfiles. Delete old file after restarting SQL Server.

Note that after the alter statement, the entries in master..sysaltfiles, master..sysdatabases and
master..sysdevices remains unchanged. On restart, the tempdb files have now moved to their new
location but the entry in master..sysdevices remains unchanged, only sysaltfiles and sysdatabases
has been altered.

If the device is no longer available in which the tempdb datafiles are created, the instance will not
start, as there is no other default value SQL Server will magically use. To resolve this problem we
need to use the rebuildm.exe (see Scenario 2.)

Scenario 2 - Rebuildm.exe

105
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

There comes a time in every DBA’s life where the rebuildm.exe (rebuild master) utility is used,
either to change the instances global collation or due to a disaster in which one or more system
databases need to be restored and we don’t have a valid or any full backup (this should never
happen for any reason).

The rebuildm.exe is found on the installation CD, cd-rom:\x86\binn. In the following example we
will run the command and highlight the subsequent steps to complete the recovery.

NOTE – If copying the CD to disk, make sure the files in ?:\x86\data\ are not read-only or
have their archive bit set.

When using disk 2 and running rebuildm.exe, I received the following error:

this was an authenticate CD, to get around this unforseen problem I copied it to disk and renamed
the directory c:\x86\binn\res\1033 to c:\x86\binn\Resources\3081. The utility then ran without a
problem.

REMEMBER – DON’T restore your master database after running rebuildm.exe if the
objective was to alter the server collation. Always backup as much as possible, and consider
scripting logins before attempting this process.

106
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

1. Shutdown the instance we plan to rebuild


2. Run the rebuildm.exe from the CD-ROM or do the above and copy to disk (not a bad idea
generally during emergency recovery scenarios). The following dialog is shown:

The instance whose system


databases will be restored
over.

Source of the CDROM default


database files.
The DBA can also set the new
collation.

Default data directory for the


installation, this can not be
altered.

3. Press the rebuild button and respond yes to the prompt

4. The database files are copied to the new destination and the “server configuration
progress” dialog is shown, this takes around 1-2mins maximum.

Try This – Run FileMonitor from www.sysinternals.com to view the file IO and thread
calls during this process.

5. Don’t be fooled, this process affects ALL system database, not just the master database.

107
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

6. Check data file properties before re-starting to ensure they are not read-only.
7. Start your instance
8. Review the previous and current error log. The previous log has some good information
about the tasks undertaken with the system databases rebuild.
9. Optionally re-apply service packs
10. Optionally restore your master, model, msdb databases as need be

Before your re-start the instance with the files copied by rebuildm.exe, double check they are
not read-only. This is a classic problem when the files are copied off the CD-ROM. If this
problem affects the use of rebuildm.exe then copy the files to disk and refer to point two
above.

Be careful when only restoring one or two of the system databases. All system databases
should be current with and single service pack, I have never been in a position where a
subsequent restore of the master database that had SP2 applied existed with the MSDB
database with no service packs. The DBA should think very carefully about this and apply the
service pack as required to ensure minimal amount of error.

Scenario 3 – Lost all (or have no) backups, only have database files

To recover from this scenario:

1. Backup all database files (if available) to another server and/or to tape.

2. Check the registry for the MASTER database, and alter and/or ensure the files are in
the correct registry entry HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft
SQL Server/<instance name>/MSSQLServer/Parameters/{SQLArg0 and 1}

3. Attempt to re-start the instance

i. If there are still errors with system databases, namely MSDB, MASTER or
MODEL, check error log carefully and attempt to place database files at these
locations.

ii. If you have no luck, run rebuildm.exe (see previous scenario)

4. The instance should successfully start

5. For MSDB database

i. Shutdown SQL*Agent service

ii. Drop MSDB database

108
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

iii. Reattach from your original database files

6. For each user database re-attach database files

7. Fix orphaned logins as need be (if any)

8. Run DBCC checkdb and checkalloc against all databases

9. Check database recovery models

10. Backup databases

The DBA should revise trace flags on instance startup to assist in the task.

Scenario 4 - Disks lost, must restore all system and user databases from backup to new drive/file
locations

This is a difficult scenario. In order to start the instance, we require a valid master database;
this database also defines the subsequent location of the MSDB, MODEL and TEMPDB database
data files. If we restore the master database from our full backup (with the move option to
another disk), the sysdatabases, sysaltfiles and sysaltdevices system tables will still contain
invalid paths for the other system and user databases as we lost those particular disks. This is
made even worse, as any time you restore the master database the instance shuts down
immediately, therefore, an instance re-start will result in numerous file-missing errors and fail
to start.

This may bring mixed comments from DBA’s, but consider the following:

1. Run rebuildm.exe to restore system databases onto new disk(s)


2. Recover MSDB database from last full backup
3. Recover MODEL database (if very different from the original)
4. Restore master database from full backup and master_old
5. Alter system to allow changes to system tables
6. Transfer contents of syslogins from master_old to the master database
7. Re-start instance
8. Check system error log
9. Recover user databases from full backups

NOTE – SQL Server has no equivalent command to the RESETLOGS option when SQL Server
opens a database.

109
5
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Transactions and Locking

O
ne of the most important concepts to grasp for any DBA, is transactions and
transaction management. In SQL Server, one of the biggest problems related to
overall system performance and stability is the poor handling of transactions,
especially long running ones. Throughout this chapter we will discuss this is in
depth. If you walk away with nothing else from this chapter, remember that it is
critically important for your OLTP systems under SQL Server to keep transactions as short as
possible to ensure blocking and lock escalation is kept to an absolute minimum.

Rollback Segments & Redo Logs


Oracle - Summary of Undo Management / Rollback Segments
Oracle has made some inroads in rollback (undo) management with 9i (due to mis-management
issues by DBA’s and new 9i options), moving away from rollback segments within a rollback
segment tablespace, to an undo tablespace with automatic undo management. Before we look at
SQL Server’s version of undo management (read-consistency), let us revise the architecture of
Oracle.

The undo / rollback segment allows the Oracle DBMS to provide read-consistency for all
transactions and is therefore essential for a transaction to execute and subsequently complete
(commit/rollback). The DBA needs to specify the undo management strategy for the database ,
that being either:

a) Manual Undo Management (rollback segments and tablespace)


b) Automatic Undo Management (AUM)

NOTE - To distinguish between the two types of undo segments, ROLLBACK segments are
called UNDO segments when AUM is enabled.

At the start of a transaction, the DBMS assigns it a rollback segment and records the current SCN
(last completed commit point). As the transaction continues with any variety of DML, the DBMS
uses the rollback segment to:

ƒ store before image of altered (updated or deleted) data

ƒ newly inserted data

110
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ assist the DBMS in constructing a read-consistent view of the database objects as at the
start of the transaction (defined by SCN). To do this, the DBMS will lookup existing and
other rollback segments to construct a read-consistent view.

This effectively allows transactions to be completely segregated from one another, to do whatever
they like to the data as at the SCN and when ready, commit or rollback. On the commit of the
transaction, the DBMS will utilise the buffer cache and rollback segments to complete the
transaction. At this point, locking is required to complete the transaction. All transactions in Oracle
require an explicit commit or rollback; the developer must issue one of the two statements (or end
their session to rollback automatically) to end the transaction, which is started when the first DML
statement is issued.

All DLL is implicitly committed in Oracle and SQL Server.

The user (programmer) may issue save point throughout the transaction to rollback to specific
points in time.

The type of undo method is used within the DBMS can be verified with:

select name,value
from v$parameter
where name in ('undo_management','undo_tablespace');

Undo Management – Manual (Rollback Segments)

Rollback Segment Tablespace


Transaction table Transaction table

Rollback Segment Rollback Segment


Active Extent
(transaction –
update, insert etc..)
they are either idle,
active, passive, in
doubt distributed.

Transactions cannot
cross more than one
segment.

Programmers/DBA
can write code to
target a segment for
the transaction to
NEXT EXTENT SIZE Non-active extent within run under.
OFFLINE MINEXTENTS segment.
ONLINE MAXEXTENTS
INVALID OPTIMIAL SIZE
PARTLY AVAILABLE
NEEDS RECOVERY
ROLLBACK_SEGMENTS in init.ora specify
online segments on instance startup

111
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Undo Management – Automatic (AUM)

The concepts are the same in principal, but the DBA has no control over the sizing, online/offlining
(altering status) and number of segments within the undo (rollback) tablespace on startup. There
are a range of new database startup parameters and subsequent DDL to create and setup the new
undo tablespace. This paradigm of self-managed DBMS “smarts” is collectively known as Oracle
Managed Files.

Undo Tablespace

Undo segments managed by the DBMS

undo_management
undo_tablespace
undo_retention, undo_pool

On setting the startup parameter undo_managagement = auto, undo segments are managed
automatically within an undo tablespace. The segments are removed when the tablespace is
removed, online/offlined as the undo tablespace changes, and segments completely managed by
the DBMS. The DBA does not explicitly create or control undo segments (rollback segments), the
DBA only specifies:

ƒ one or more undo tablespaces (undo_tablespaces=), and the associated create undo
tablespace command. Undo tablespaces may only hold undo segments.

ƒ only one undo tablespace can be used at any one time.

ƒ undo_retention – parameter, clock time to retain of committed undo data in the tablespace.
Required for the flashback option in 9i.

ƒ undo_pool – multiple pools with restrict undo properties can be created and allocated to
users to restrict usage.

ƒ v$undostat – to monitor undo transactions, space consumed etc

ƒ v$rollstat – monitor automatic segment statistics

NOTE – The Oracle 9i flashback option requires AUM.

Oracle – Redo Logs


For redo management Oracle utilises two or more redo log groups, consisting of one or more
physical files (members) per redo group. As we know, the redo logs store all changes (there are
some variations to this) made to blocks in the buffer cache and are key for recovering committed

112
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

data that has yet to be written to the actual database files. The DBA has full control over the
positioning, sizing, onlining / offlining, switching, limiting number of and the associated archive log
process.

The DBA must archive logs to prevent the database locking up and is the key to PITR (point in time
recovery).

Oracle supplies the log miner tool to analyse database activity via the reading of redo and archived
redo log files. This tool is implemented as a series of PL/SQL packages, views, utilities to the read
associated redo log dictionary objects, and the associated java based logminer GUI tool.

Oracle – Locking

Where possible, both Oracle and SQL Server attempt to allocate locks at the lowest level possible
(that being at the row). Also, like both DBMS’s, shared and exclusive locks exist, in which one and
only one exclusive lock can be taken out on a resource at any one time, whilst multiple shared locks
are possible. The only key difference here was described previously, where in Oracle reads are
never blocked by exclusive locks, in SQL Server they will be (especially update locks described
next).

All locks are held for the duration of the transaction as with SQL Server, which is completed via a
commit or rollback command (optionally to a save point as well). Oracle will not escalate locks,
but will do the appropriate lock conversion to obtain the most appropriate lock at the highest level
as possible (that being a row-exclusive lock - RX). The locks themselves are maintain via enqueue
processes in which the DBA via enqueue_resources can control this internal locking structure.

Oracle includes the following lock types (may not be definitive):

a) DDL
a. Protect the schema objects and their definition.

b) DML
a. Ensures only one row can be updated at any one time.
b. Objects cant be dropped whilst transactions are pending
c. Row or table level
i. TX – row level lock
1. readers do not wait for writers for the same data
2. writers not wait for readers (for update excluded)
3. writers wait for other writers over the same row
4. table level shared lock is also taken.
ii. TM – table level locks
1. RS (SS) – row share
2. RX (SX) – row exclusive
3. SRX – share row exclusive lock
4. X – exclusive
c) Latches
d) Distributed (OPS)
e) PCM (parallel cache management) used in the shared server configuration.

113
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The compatibility for lock conversion/acquiring matrix is shown below as summarised on


Oracle Metalink:

Mode Held NL SS SX S SSX X


NL Ok Ok Ok Ok Ok Ok
SS Ok Ok Ok Ok Ok Fail
SX Ok Ok Ok Fail Fail Fail
SSX Ok Ok Fail Ok Fail Fail
X Ok Fail Fail Fail Fail Fail

The type of SQL statement will also determine the lock modes permitted against the resource (out
of scope for this book).

SQL Server - Undo & Redo Management Architecture


The previous two sections very briefly covered rollback and redo within the Oracle RDBMS. This is
an important review in order to understand the SQL Server architecture and bring the concepts of
Oracle into context.

The key to rollback and redo for SQL Server is the transaction log that is present in each database
within the instance. The transaction log is a serial record of all transactions (DML and DDL)
executed against the database and is used to store:

a) start of each transaction


b) before and after changes made by the transaction
c) allocation and de-allocation of pages and extents
d) commit and rollback of transactions
e) all DDL and DML

The transaction log itself consists of one or more physical database files, the size of the first must
be greater than or equal to 512Kb in size. SQL Server breaks down the physical file into 2 or more
logical transaction logs. The size of the file and its auto-growth settings will influence the number
of virtual logs and their size. The DBA cannot control the number of or sizing of virtual logs.

Physical transaction log file (min size 512Kb with 2 virtual logs)

Virtual Log File


(min 256Kb)

The log writer thread manages the writing of records to the transaction log. As pages are
requested and read into the buffer cache, changes are sent to the log-cache as a write-ahead
operation which log-writer must complete with a write to the transaction log before the committed
change is written to the data files as part of a check-point. In terms of an update, the before and
after images are written to the log; a delete the before image is written; an insert tracks only the
new records (not including many other record entries as mentioned previously as part of the
transaction). The log-writer allocates a LSN (log sequence number, similar to the as the SCN in
Oracle) to each statement including the transaction ID.

114
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Log Cache Log flushed, LSN allocated and Physical transaction log file
transaction id stamped with before/after
images of the records updated.

Write-ahead log cache, must


complete before buffer cache
pages written back to
physical data files.

Buffer Cache
Dirty buffer pages,
log-write requested

Select and update of database record

Database Data Files


Checkpoint completes - writes back to
buffer cache entries to data files only
after log write is compete.

The transaction entries (committed and uncommitted) in the transaction log are doubly linked lists
and each linked entry may contain a range of different (sequential) LSN’s. The transaction itself
remains in the active portion of the transaction log until it is either committed or rolled back and
the checkpoint process successfully completes.

Physical transaction log file


Doubly linked list log-entries for the transaction.

Free space
Active Portion of
in virtual
Log
logs

Although not shown above, space is also allocated for each log entry record for rollback purposes;
therefore actual space utilisation can be significantly more than expected. Microsoft defines the
active part of the log to be the portion of the log file from the MinLSN to the last written log record
(end of logical log).

115
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Cyclic and serial


transaction log End/start of next virtual log file

Free virtual log BEGIN UPD BEGIN COMIT CHECK DEL


space TRAN TRAN TRAN TRAN POINT TRAN
T1 T1 T2 T1 T2

LSN LSN LSN LSN LSN LSN


112 113 114 115 116 117

- active portion -

MinLSN Last Log


record

The MinLSN is the first of possibly many yet uncommitted (or rollbacked) transactions.

When the database is using a full or bulk-logged recovery model, the non-active portion of the log
will only become “free” (can be overwritten) when a full backup or transaction log (archived log
backup in Oracle) backup is executed. This ensures that recovery is possible if need be via the
backup and the DBMS can happily continue and overwrite the now free log space. If the database
is using the simple recovery model at a database checkpoint, any committed (and check pointed)
or rollback transactions log space will become immediately free for other records to use. Therefore,
point in time recovery is impossible.

The checkpoint process is key to completing the committed transactions and writing the dirty
buffers back to disk. In relation to the transaction log, this will:

a) write log entry for the start of the checkpoint


b) write the start LSN for the checkpoint chain to the database book record for subsequent
recovery on instance failure
c) write list of active (outstanding) transactions
d) write all dirty log and data pages to disk
e) writes a log file record marking the end of the checkpoint

This is far from definitive but you get the idea. The checkpoint will occur:

a) On issue of the CHECKPOINT or ALTER DATABASE statement


b) On instance shutdown (SHUTDOWN statement)
c) On service shutdown
d) Automatic checkpointing
a. DBMS calculates based on the recovery interval setting
b. “Fullness” of the transaction log and number of transactions
c. Based on timing set with recovery internal parameter
d. Database using simple recovery mode?
i. If becomes 70% full
ii. Based on recovery interval parameter

116
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Apart from the recovery interval and recovery mode parameters, the DBA has little control of
checkpointing. Although, it can be forced via the CHECKPOINT statement if need be.

To drill into the virtual logs and the position, status, size, MinLSN within the transaction log
files, use the commands:

dbcc loginfo
dbcc log(<db#>, TYPE=-1)

NOTE – The transaction log is a write-ahead log. Log writes are synchronous and single
threaded Actual DB writes are asynchronous, multi-threaded and as shown in the diagrams,
optimistic.

In Summary

Fundamentally, the two DBMS are very. The key differences are primarily highlighted with the
rollback segments, which effectively results in writers blocking readers with its default isolation level
(read-committed as with Oracle) as a database change cannot be dynamically re-constructed to a
point in time. As we will see next, the result is a more complex locking mechanism, more
transaction isolation levels and associated hints, and programmers needing to be much more strict
in keeping transactions as short as possible.

The following sections discuss locking and isolation levels for transaction management.

In terms of redo, the transaction log is the equivalent to the redo logs in Oracle. The DBA can only
control the number of logs used and cannot manipulate the virtual logs within them. As with
Oracle, the DBA needs to archive logs (backup log command) on a regular basis to prevent the
database from “stalling”. Functionally, the redo logs are identical in terms of their requirement for
database recovery.

117
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Locking & Isolation Levels


The locking mechanism for SQL Server is complex to cater for the lack of rollback segments. In
SQL Server, locks, lock escalation and the use of additional isolation levels to maintain read-
consistency (and concurrency) results in the possibility for writers to block readers, and the
increased possibility of deadlocking issues or long sustained blocking. Because of this,
programming against a SQL Server DBMS and an Oracle DBMS is somewhat different in terms of
transaction longevity.

The transaction isolation levels are:

SQL Server Oracle


Read Uncommitted N/A
Read Committed (default) Read Committed (default)
Repeatable Read N/A
Serializable Serializable
N/A Read Only (ANSI)

The isolation is very important in determining transaction concurrency (enforcing atomicity and
consistency in relation to other running transactions) and determining the locking required by the
DBMS to meet the isolation level. The SQL Server DBA does not explicitly set the isolation level and
cannot control a minimum global setting or restricted set of isolation levels that can be set against
the DBMS. The programmer can alter the databases default isolation level on connect (ADO, OLE-
DB, ODBC property), T-SQL or via a SQL hint.

The T-SQL command is:

SET TRANSACTION ISOLATION LEVEL


[ READ COMMITTED, READ UNCOMMITTED
REPEATABLE READ, SERIALIZABLE ]

You can view the isolation level via the command:

DBCC USEROPTIONS

NOTE - that isolation level property is not shown if the default is in use.

The SQL Server locking schemes are completely automatic in context with the isolation level, with
lock escalation as need be to fulfill the request (Oracle never escalates locks). Where possible, SQL
Server will start at the lowest granularity of locking and in terms of exclusiveness, then use a
variety of other lock types at higher levels to pre-empt future intentions and escalations on the
underlying object. The lock types are divided into four modes:

INTENT (I) – future intention to acquire other locks


SHARED (S) – allows many concurrent reads, blocks updates until share is
released, there is always 1 shared lock on the DB for the connection.
UPDATE (U) – prior to data modification, is upgraded to exclusive on change
EXCLUSIVE (X) – complete lock of the resource

118
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SCHEMA (Sch-[M,S]) – Schema modifications, DDL, schema stability lock


BULK UPDATE (BU) – Bulk copy of data (bcp) with TABLOCK hint
RANGE[I]_[S,U,X,N] – Key range lock, used in serialized transactions, covers index
keys and the ranges of the index rows.

And of course combinations of the above, such as:

IS Intent shared
IX Intent exclusive
SIX Shared with intent exclusive

The resources in which locks are applied (and escalated in order of) include rows, pages, keys
(index keys), range of keys, indexes, tables, and databases. These are of course abbreviated:

RID Row Identifier


PAGE Page (data or index)
EXT Extent (8 contiguous pages, data or index)
TAB Table
IDX Index
FIL File
KEY Key (row lock with index)
DB Database

The status of the lock request against the resource may be:

GRANT Lock obtained


WAIT Blocking due to another process
CNVRT In processes of being converted (escalation)

Again, the duration of the lock will depend on the isolation level, hints, DML/DDL operation being
performed and the range of rows affected by the operation (some internal threshold being
exceeded that results in escalation).

The DBA can do very little to control the lock manager, the best we have (apart from isolation
levels and hints) is the lock option altered via the sp_configure stored procedure. The default
option is to let SQL Server manage the maximum number of lock structures (96Kb each), which in
99% of cases is the best option.

It is difficult to describe and summarize every example of locking, the DBA really needs to explore
the sp_lock procedure with a variety of different isolation levels and DML/DDL to view the locks
taken out not only against the database, but also against the master and tempdb databases.

Here is a short example:

119
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Table definition:

CREATE TABLE [mytable] (


[col1] [int] IDENTITY (1, 1) NOT NULL ,
[col2] [varchar] (50) COLLATE Latin1_General_CI_AS NULL ,
CONSTRAINT [PK_mytable] PRIMARY KEY CLUSTERED
(
[col1]
) ON [PRIMARY]
) ON [PRIMARY]
GO

User SQL:

set transaction isolation level serializable


begin transaction
select * from mytable
exec sp_lock @@spid
commit transaction

Example Results:

set transaction isolation level [repeatable read or serializable]

select OBJECT NAME(1173579219)

It should be noted that KEY locks are shown when the table has a clustered index rather than
showing rowlocks. For non-clustered indexes the KEY locks exist for the leaf nodes. Locks may be
retained until the transaction is complete; this is especially the case with shared locks over a
repeatable read isolation level. At the end of the day, the DBA must be very strict on the timing of
transactions, the operations being performed (DDL, DML), objects being affected (multiple indexed
tables etc), use of triggers, and keep the transactions as short as possible.

120
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

NOTE – There is no equivalent to Oracle’s IDLM (integrated distributed lock manager) as


used in the OPS (Oracle Parallel Server) environment too coordinate parallel access to DBMS
resources. With this, there are no equivalent LCKn processes used for inter-instance locking in
OPS.

Transactions

Drilling now into transactions, the syntax is similar to Oracle in some respects. The key
difference here is the in-ability for SQL Server to pause or re-start transactions as we can in
Oracle.

The syntax is straight forward enough:

BEGIN TRAN[SACTION]
<SOME CODE HERE>
[COMMIT, ROLLBACK TRANS[ACTION]]

The transactions can be nested, be aware of the rollback transaction command as it does not give
you the result most would expect:

begin transaction
print @@trancount
begin transaction Transaction Count
print @@trancount
begin transaction 1
print @@trancount 2
commit transaction
3
commit transaction
print @@trancount 1
commit transaction 0

begin transaction
print @@trancount
begin transaction 1
print @@trancount 2
begin transaction 3
print @@trancount Server: Msg 3902, Level 16, State 1, Line 9
rollback transaction The COMMIT TRANSACTION request has no
commit transaction corresponding BEGIN TRANSACTION.
print @@trancount 0
commit transaction Server: Msg 3902, Level 16, State 1, Line 11
The COMMIT TRANSACTION request has no
corresponding BEGIN TRANSACTION.

In SQL Server 2k we can also mark transactions and set save points to rollback to. Marking
transactions can be very handy when tracking long running jobs and ease the rollback process on
transaction failure. The syntax is simple:

The transaction log marks are held in the MSDB database table logmarkhistory.

121
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Monitoring Locking Issues


The DBA should review the following commands via the books online:

ƒ sp_lock – get some reasonably detailed information about locks and spids

ƒ @@SPID – get sessions current spid

ƒ sp_who2 – get list of all sessions connected to the instance

ƒ sp_helpdb – get summary of the database in the instance

ƒ dbcc inputbuffer(<spid>) - what is a session running/doing now or last statement run

ƒ sysprocesses table - check the block, cpu and physical IO columns

ƒ profiler – your key tool for session tracing

ƒ enterprise manager – general database administration tool

ƒ dbcc stackdump - will generate a low level dump of processes,.dmp file is generated in
the log directory of the instance

The sum of the commands above is similar to utllockt.sql and catblock.sql scripts in Oracle (not
including EM and other 3rd party tools). In terms of DBMS_LOCK, apart from table level SQL
locking hints, there is no equivalent to this package.

Third party tools vary greatly in function and actual usefulness and like all things, require a lot of
evaluation and pre-thought before handing over your money. As an example in terms of
block/locking issues, Diagnostic manager from NetIQ returns to me SMTP emails:

2838: The monitor has determined that process ID 11 has been blocking another process for
longer than 30 seconds. The process is being executed by program 'SQLDMO_1', on computer
'MY-SERVER', by user 'sa'.
The blocking lock's details are : Database - msdb, Table ID - 213575799, Lock Type -
Blocking Intent Exclusive.
The statement being executed is :
dbcc checkdb WITH NO_INFOMSGS
16/08/2002 5:57:12 PM [MY_DB]

Within Enterprise Manager (EM), we have a small number of options. Some example screen shots
of EM and viewing blocking issues are shown below:

122
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Take a careful
look at the lock
modes, namely
X and U or
ranged
exclusive locks.

Like all locking, most are short and point in time events that at times can be hard to trace. This is
where profiler comes into play. Be aware that EM can take some time to refresh and at times the
DBA “thinks” its locked itself, only to return back with the results some minutes later. Here is a
classic error; right at the time we are trying to sort out the blocking issue:

123
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The blocking locks can be a real problem with SQL Server, even more so than deadlocking. The
DBA may really struggle to pin point the actual problem, as both profiler and DBCC input buffer
might not return the statement being blocked. As described by Q224453, “Blocking is an
unavoidable characteristic of any relational database management system (RDBMS) with lock-
based concurrency. On SQL Server, blocking occurs when one SPID holds a lock on a specific
resource and a second SPID attempts to acquire a conflicting lock type on the same resource.”.

Here are some general pointers to resolve the problem:

ƒ Attempt to repeat the problem on a quiet server in which tracing the blocked and blocking
SPID’s and locks is much easier.

ƒ The developer will have an idea as to the code being executed, discuss the code and
consider a mini walkthrough (demand it if necessary), are we taking about COM+ with
transactions? How are transactions being used? Isolation levels? Are hints being used?

ƒ Attempt to trace and filter over the key tables involved with the lock. Rather than using
profiler, consider “command line” trace via sp_trace in Query Analyser to ensure events are
not missed in very busy databases.

ƒ Consider dbcc opentran to analyse long running open transactions that may be causing the
blocking and allow more effective (filtered) tracing via profiler.

Controlling Locks
Locks can be controlled at a SQL level via hints, I don’t like hints and am never comfortable
with them, but there are cases where they come in handy (especially bulk data loading and
concurrent data loading/selecting). The hints include:

HOLDLOCK
NOLOCK
PAGLOCK
READCOMMITED
READUNCOMMITED
REPEATABLEREAD
READPAST
ROWLOCK
TABLOCK
TABLOCKX
UPDLOCK
XLOCK

124
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

For example:

Select * from mytable (tablockx)

select a.lname, b.job_desc


from employee a (xlock), jobs b (tablockx)
where a.job_id = b.job_id

Hints are described in more detail later in this book.

Apart from SQL hints, the DBA can use the sp_indexoption to set locking options at an index level.
The options are somewhat limited but include:

AllowRowLocks FALSE or TRUE


AllowPageLocks FALSE or TRUE
DisAllowRowLocks FALSE or TRUE
DisAllowPageLocks FALSE or TRUE

The default is to allow row locks where possible. An example is:

exec sp_indexoption 'mydb.mytable', ‘disallowpagelocks', TRUE

Do not use this option unless there is a very good reason too.

125
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Finally, we can set the isolation level (and thus control locking), via the begin transaction
command. For example:

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ

In terms of lock timeout, the developer may use the LOCK_TIMEOUT command. Where possible the
DBA should discourage (i.e. DON’T USE) its use and opt for a more elegant solution. Here is an
example of its use:

Session 1 Session 2

begin transaction SET LOCK_TIMEOUT 5000


update authors begin transaction
set au_lname = ‘timeout test' update authors
where au_id = '238-95-7766' set au_lname = ‘timeout test'
waitfor delay '000:00:10' where au_id = '238-95-7766'
rollback transaction rollback transaction

Server: Msg 1222, Level 16, State 50, Line 1


Lock request time out period exceeded.

Without it, session two will wait indefinitely until the session one completes.

Detecting and dealing with Deadlocks


The NT performance monitor is a good start to determine the extent of the problem. We use
the counter:

SQLServer:Locks \ Number of Deadlocks\sec

Ideally its value is zero and/or a rare event. There are situations where this is difficult, especially
third party applications or your OLTP database that is also being used for reporting and other batch
type events out of your control. The DBA should follow up with SQL Profiler to better trace the
deadlocks occurring.

Profiler is a powerful tracing tool, but it does have some problems when tracing deadlocks as we
will see later. On starting a new trace, the DBA should include the events:

Errors and Warnings


Exception
Locks
Lock: Deadlock
Lock: Deadlock Chain

If you stayed with this, and waited for your expectant deadlock to occur, you will get very little
information of the objects affected or statements executed unless you select the data column
Object Id. From here you need to manually use OBJECT_NAME to determine the object affected.

Why is this a problem? to get more information you typically include the event T-SQL: SQL: Batch
Completed, if you run the trace with this option then you will be tracing ALL completed batches,
and in a busy system, this can mean thousands of entries within minutes; making tracing a difficult

126
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

and time consuming task. Even so, if you can deal with this, you will get a thorough list of
statements related to the deadlock; stop the trace after the deadlock occurred and use the find
dialog to search the columns for deadlock event, then search backwards from the SPIDS involved in
the trace to get a summary of the commands before the deadlock.

NOTE – Running profiler whilst locking is already underway and a problem, will do you no
good, and you may only get a small amount of relevant information about the issue (i.e.
profiler doesn’t magically trace already running processes before continuing on its way with
current events).

The client application involved in a deadlock will receive the error# 1205, as shown below:

Server: Msg 1205, Level 13, State 50, Line 1


Transaction (Process ID 54) was deadlocked on {lock} resources with another process and has
been chosen as the deadlock victim. Rerun the transaction.

To assist in this circumstance, utilise EM or run the following commands:

exec sp_who2 -- view all sessions


dbcc inputbuffer (52) -- get SQL buffer for 52
exec sp_MSget_current_activity 56,4,@spid=52 -- get extended locking information

Finally, the DBA can utilise trace flags. This is an effective method for debugging deadlocks and
provides some excellent error log data. The flags are:

1204 Get lock type and current command effected by deadlock


1205 Get extended information about the command being executed (eg. graph)
1206 Complements 1204, get other locks also participating in the deadlock
3605 Send trace output to the error log (optional, will go there anyhow).

The screen shots below illustrate the output from a deadlock with the traces enabled. I have no
statistics on the adverse effect to DBMS performance, but this is a very effective method for
debugging problem systems that are deadlocking frequently but you can never get a decent set of
data to debug it.

127
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The actual deadlock is around the customer and employer tables, in which two processes have
updated one of the two separately and have yet to commit the transaction; they attempted to
select each others locked resources resulting in the deadlock. This is not reflected in the log dump.

The ECID is the execution context ID of a thread for the SPID. The value of zero represents the
parent thread and other ECID values are sub-threads.

Check with http://support.microsoft.com for some excellent scripts to monitor blocking in SQL
Server.

Example Deadlock Trace

We have a large COM+ based application that was experiencing deadlocking issues. The key issue
here is that COM+ transactions use an isolation level of serialisable, as such, locks of any sort can
be a real problem in terms of concurrency. To start resolving the problem we:

a) worked with the developers in working out how to repeat the error

a. this allows us to identify the code segments possible causing the error and assist of
course with re-testing.

b) Set instance startup parameters -T1204 -T1205 -T1206, re-start instance

c) Run Profiler

a. Filter the database we are concerned with

b. Include event classes

i. Lock:Deadlock

128
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ii. Lock:Deadlock Chain

iii. SQL:StmtCompleted

iv. RPC:Completed

c. Include standard columns, namely TextData and SPID

d) Run the code to cause the deadlock.

Search the profiler trace:

Lock:Deadlock identifies that SPID 67 was killed. Go back through the trace, to locate the
commands executed in sequence for the two SPIDS in the chain, take some time with this, you
need to go back through the chain of transaction begins (in this case they are COM+ transactions)
to clearly determine what has happened for each SPID’s transaction block.

To assist with further debugging, goto your instance error log and locate the deadlock dump chain:

IX lock wanting to
be taken out

Last command from


buffer. (stored proc or
DML statement

Current lock being


select object_name(918450496) will give held
you the table name to help identity the
possible problem statement to start looking
for in the batch of SQL being executed.

129
6
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Performance Tuning

T
he art of performance tuning requires good theoretical and practical knowledge of the
underlying operating system, physical hardware, applications components and of course,
the DBMS. Many of these skills can only be acquired with years of practical experience with
a variety of server’s configurations and, most importantly, applications. This chapter
attempts to highlight some of the key items of interest to the DBA.

Tracing (profiler)
Tracing database events and users sessions in SQL Server is done via the profiler utility. This is a
powerful tool that allows the DBA to:

a) trace a range of database events


a. including grouping of events and selectively picking data columns to be used
b. apply filtering rules to further define the events you are after
c. save output to a file (can set max size) or a database table (set max rows) and
optionally enable trace stop time.
d.
b) edit and define trace templates
c) replay saved traces (including break-points and stepping through a trace)
d) scripting a trace
e) running trace file results through the index wizard
f) assist with auditing and of course performance tuning
g) error tracing and blocking/locking detection

Run the GUI and play with it against a development or test instance. The interface is simplistic and
like all things, read the screens carefully and you will find it self-explanatory. The utility, by default,
will trace all DML and DDL database activity within the instance you are connecting too.

There are numerous events you can trace via profiler, some of which are:

Event Trace Type Summary


Cursors Cursor prepare open, close, recompiles etc

Database Automatic growth and shrink of data and log files

130
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Errors and warnings Missing column statistics, missing join predicates, oledb errors, tempdb
sorts over memory sorts, exceptions etc.

Locks Lock escalation, timeout, deadlocked etc

Objects Auto stats collection, objects accessed via DML, objects created and
objects dropped or deleted.

Performance Execution plan, degree of parallism

Scans Table or index scan started/stopped

Security audit Numerous audit events, including password changes, failed logins,
adding and removing role members, adding/removing database users,
server starts and stops etc.

Server Memory change

Stored procedures Recompiles, started and completed, procedure cache miss, removal
from the procedure cache, cache hit for stored procedures.

Transactions DTC transaction, SQL transaction (commits, rollback transactions etc),


log entry written to transaction log

T-SQL SQL started, completed, batch started/completed etc.

Within profiler, you can apply many filter conditions for a single trace event. In virtually all cases I
do not include system objects by checking the box provided:

The DBA may also want to filter on a specific database within the instance. Use the database ID as
the name will not work. Get the database ID by querying sysdatabases found in the master system
database.

Here are some example event filters and traces to consider:

Events Columns Filters Our Aim


RPC:Completed DatabaseID Filter on a specific database ID Performance
SP:Completed Duration as need be. Exclude or Include Tune SQL
SQL:BatchCompleted Event Class selected statements as need be. and Monitor
TextData Select a specific SPID for single Adhoc SQL
LoginName user tracing. Select a duration
CPU (ms) >= ???? (i.e. 1000) milliseconds

131
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Reads for more selective tracing.


Writes
SPID
Start Time
RPC:Starting Object Id Deadlock
SQL:BatchStarting Event Sub Class Detection
Lock:Deadlock Connection Id
Lock:Deadlock Chain SPID
Text
Server Name
Database Id
Index Id
Application Name
SQL Use Name
Start Time
Integer Data
Binary Data
SP:CacheHit DatabaseID Stored
SP:CacheInsert Duration Procedures
SP:CacheMiss Event Class
SP:Completed TextData
SP:Recompile LoginName
SP:Starting CPU (ms)
SP:StmtCompleted Reads
SP:StmtStarting Writes
SPID
Start Time
Audit Add DB User Event Database ID Filter on a specific database ID Auditing
Audit Add Member to DB Event Class as need be.
Role Event NT Domain
Audit Addlogin Event Name
Audit Backup/Restore Event Role Name
Audit Login Target Login
Audit Change Password Name
Event Target User
Audit Login Failed name
Audit Server Starts and Application Name
Stops NT User Name
Audit Statement GDR Event Client Process ID
SPID
Start Time
Errors and Warnings: Database ID Consider SP:StmtCompeted and Error Tracing
errorlog Event Class SQL:BatchStarted to get more
Oledberror TextData information about the event
Exception NT User Name before the error.
Exception warnings SPID
Start Time

132
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Use the predefined trace template called Filter on a specific database ID Use the
“SQLProfilerTuning”. as need be. The DBA may still Index Tuning
selectively apply filters for Wizard
specific types of SQL, namely:

The DBA may add further events to the trace, such as SQLTransaction to capture the begin and
subsequent commit/rollback sub-classes. Additionally, the DBA may also consider the RPC events
(remote procedure calls). I have to say that profiler is something Oracle is sorely missing in terms
of fast and easy to use tracing.

NOTE – the generic trace is a good start, use the default trace, exclude system processes,
and use the database ID filter (see sysdatabases in the master database or exec sp_helpdb,
filtering on database name may not work for you and in many cases will return a blank string).
This trace is an excellent start as it includes text data of submitted SQL and is a good basis for
further exploring the power of the tool.

IMPORTANT – Be very careful re-running saved traces through profiler, if they include a
range of inserts, updates, deletes, they will all be repeated against the database instance.
This is very handy in various debugging and tuning workloads, but you do not want to get it
wrong if you know what I mean.

The DBA should spend a good amount of time on profiler. It is a very powerful tool for not only
SQL performance tracing, but for auditing, error detection, cache misses and recompiles and much
more. For a good overview with some performance tuning tips, I highly recommend the e-book
“Start of Finish Guide to SQL Server Performance Monitoring”, Brian Kelly 2002.

NOTE – Take care with the duration column. This may not accurately reflect the execution
time of the actual SQL statement. For example, I had a large application where profiler
reported that the selected statements were taking 20sec to execute. Running them via query
analyser gave a different story and they were running under 1sec. Going back to the client
application and drilling into the code segment was the only way to more effectively time and
resolve the problem.

Saving & Scripting Traces

The DBA can choose to save a profiler trace to a database. The DBA can specify the name of the
database in which to create the table, and the name of the table. The tables’ columns are created
based on the data columns selected for tracing. The table has a single primary key called
RowNumber (identity) that is a clustered index. If the DBA selects an existing table, it will ask if it
is ok to overwrite it, which involves dropping an re-creating the table.

The greatest option in regard to profiler tracing, is that we can script out the trace script in T-SQL
code. For the DBA wanting to further customise the trace, this is an excellent feature. Once a

133
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

trace has been set and is running, select File Æ Script Trace Æ For SQL Server 2000 to generate a
.sql file of the sp_ stored procedures used to create the trace.

NOTE – Don’t assume the GUI is showing all commands executed. If you are relying on the
trace window be aware that it buffers trace data. On very busy systems this can result in a
loss of data in the trace window.

If you forgot to save the trace to a trace file or trace table, don’t fear, stop the trace and select File
Æ Save As Æ Trace File and specify your .trc filename. Be careful though, if you start again the
trace screen (buffer) is cleared and all will be lost, also, pausing the trace, altering event columns
and starting again will also clear the buffer of all previous tracing.

One handy feature in SQL Server is the ::fn_trace_gettable system function. After creating a trace
file via profiler, run the following and get a table representation of the files contents:

SELECT * FROM ::fn_trace_gettable('C:\mytrace.trc', default)


GO

Other system functions to check are:

• ::fn_trace_setstatus <id>, <status>

• ::fn_trace_setevent

• ::fn_trace_setfilter

• ::fn_trace_getfilterinfo(<id>)

• ::fn_trace_getinfo(0)

• ::fn_trace_geteventinfo(<id)

Index Tuning Wizard


The DBA can access the index-tuning wizard via query analyser. The wizard option is under
the query menu option and is only available when a connection has been established to an
instance and something has been entered into the query pane (even a space is enough), as
the option remains greyed out until you do.

The wizard works hand-in-hand with the traced output file from profiler or a manual trace via
sp_trace.

The first main screen is shown below.

134
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Select the database to tune, this


and the server is defaulted from
the connection made in query
analyser. I tend to opt for not
keeping existing indexes to get a
better idea of new indexes to
support the SQL trace I am
tuning, even so, if you know the
batch of SQL has been running
well, retain the option to see what
additional recommendations are
made over and on top of existing
indexes.

Use the thorough analysis method


in all cases.

The DBA can select a previously


run trace from profiler,
remembering that profiler allows
the DBA to save the trace as a
.trc file or to a database table. If
the DBA has a range of SQL
statements in the query analyser
pane, then it can utilise them to
perform its analysis.

ALWAYS select the advanced options.


The defaults can be very strange
indeed. Remove the limit for the
workload queries to sample, bump up
the space recommended for indexes to
around 100Mb+ (worst case largest
index size?). The next option really
depends on the DBA, if you leave the
default at 16, then SQL Server may
decide to recommend a single index
with all columns in the table, this is not
good practice for many installations.

135
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Select all tables, unless of you


know for a fact that only a small
number of the total tables in your
schema are being used. The cool
feature here is the projected
column, in the example I have
projected a growth of 80000
orders over the existing 830
currently in the table.

The index analysis will start when the next button is pressed. The existing database structure is
not altered in any way what so ever. If you traced inserts, deletes and updates they are not
actually run, they are only parsed and the tuning wizard will apply the rules previously set.

The analysis is reasonably well presented; the analysis screen provides a series of reports that can
be saved to disk for further checking. Be very careful though with the overall recommendations. A
classic example is shown below, where my three statements in the trace (which only covered 3 of
the total tables) result in the recommendation to drop all existing indexes off the non-utilised
tables. At the end of the day, the DBA should save all recommended changes to disk and evaluate
each one very carefully in context with the big picture.

The index wizard will also recommend statistics (histograms) for tables.

136
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

On clicking Next the DBA is asked if the recommendations should be saved to disk and/or for them
to be applied immediately or scheduled as a SQL*Agent job on the instance to be run later. Take
the time to re-check the individual table indexes, a classic example is with the sample northwind
database. Here in the Orders table we have two indexes over the CustomerID column, why? well
the index tuning wizard asked the same question and suggested that we remove the duplicate
indexes.

Explain Plan
Within Query Analyser the DBA has a variety of choices when it comes to viewing the optimiser’s
execution plan:

set showplan_text {on, off}


or
set showplan_all {on, off}

Some of these can be set via toolsÆ optionsÆ connection properties.

When using the Query menu options above, the only toggle item is the show execution plan, the
display estimated execution plan will be executed immediately based on the SQL selected, or, if
nothing is selected then all SQL is parsed and the plan displayed. A different plan of course will be
shown from top to bottom if there are multiple SQL statements.

Both query menu options show a graphical representation of the generated plan. This, like all
plans, should be read from bottom to top. Placing the cursor over each step within the plan
provides further statistical information.

137
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Place cursor here


to view stats on
rows returned

If you set the showplan_text or showplan_all options, the graphical version of the plan is not
shown. A text version will shown instead and will continue to be shown until you set the options
off. Switch between Results in Text and Results in Grid to get a better view of the plan.

Microsoft Technet provides some good documentation related to SHOWPLAN and the optimiser in
general. Search in the books online for “Graphically Displaying the Execution Plan Using SQL Query
Analyzer” for a general overview of each displayed icon. See reference (45).

When performance-tuning queries, like all things, indexes and update statistics will play a major
part in the optimiser selecting the best execution path. The DBA should revise index and the query
joins and filter conditions carefully before choosing hints.

NOTE – You can find the complete books online at


http://www.ddart.net/mssql/sql2000/html/, which is equivalent to http://tahiti.oracle.com

To obtain further statistics in terms of execution time and IO, we can set the following:

set statistics time on

eg.
SQL Server Execution Times:
CPU time = 270 ms, elapsed time = 330 ms.

set statistics io on

eg.

Table 'Order Details'. Scan count 77, logical reads 4467, physical reads 0, read-ahead reads 0.
Table 'Categories'. Scan count 77, logical reads 154, physical reads 0, read-ahead reads 0.
Table 'Products'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0.
Table 'Orders'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0.

Where:

Scan Count – #times that tables referenced in the query where accessed.
Logical Reads – database buffer cache page reads
Physical Reads – physical page disk read from disk into the data cache for processing

138
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Read Ahead Reads - read ahead cache manager page reads, is a separate asynchronous process (anticipated
page reads)

Switch to results in text to view the timings. Take care with statistics time as other server activity
can also skew the result set. The time displayed will also list parse and compile time when
appropriate. In all cases, ignore the first portion of the timing of the SQL statement being
analysed, this is not related to the command but previously run SQL.

SQL Server parse and compile time:


Ignore this.
CPU time = 0 ms, elapsed time = 5 ms.

SQL Server parse and compile time:


CPU time = 0 ms, elapsed time = 0 ms.

NOTE – Developers can run explain plan and set the time and IO statistics on without any
special privileges. Also note that index pages are also read into the buffer cache.

Another method of timing is simply declaring datetime variables and printing the time difference
between the start and current time in each phase of your SQL. Be aware that you will be restricted
to seconds, rather than hundredths of a second.

Black Box Tracing?

A range of 3rd party tools I have used typically recommends the black box trace. The trace itself
will create the files blackbox.trc, blackbox_0n.trc (switches every 5Mb), of critical system error
message traces. This can be very helpful when working with Microsoft support in diagnosing
system errors. The trace is activated via:

-- ###########################
-- Start the black box trace
-- ###########################
declare @traceID int

exec sp_trace_create @traceID OUTPUT, 8 -- Create the TRACE_PRODUCE_BLACKBOX


exec sp_trace_setstatus @traceID, 1 -- Start the trace

and produces this file:

If you want to start the trace every time SQL Server starts, then place the code into a stored
procedure within the master database and set the option:

exec sp_procoption ‘mystoredprocnamehere’, ‘startup’, true

To verify the trace:

USE master

139
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

GO
SELECT * FROM ::fn_trace_getinfo(1)
GO

Latch Statistics
The term latch is synonymous to that used in Oracle. To monitor latch based statistics we can
use the command:

DBCC SQLPERF(WAITSTATS, CLEAR) -- initialise counters


DBCC SQLPERF(WAITSTATS) -- get statistics

This will return cumulative data so we need to re-run this command and compare the
difference to determine the point-in-time (or an average) statistic. In a majority of cases the
DBA will be able to determine the performance problem via profiler and tracing poor
performing SQL, deadlocking, page-splitting and more without having to drill into latch
statistics.

Be aware that SQLPERF returns more than just latch statistics, the command can provide
some interesting lock architecture statistics.

See section on Wait Statistics for more information.

Page Splits
The page splitting problem primarily occurs when new data insertions (over a non-sequenced key)
or updates result in the row not fitting into a page. This results in a page split, as the destination
page is split into two and requires the re-linking of the index pages in the b-tree and associated
linked leaf page list chain to accommodate the row. As you can imagine, this is a resource
intensive tasks that can affects overall system performance, longer latch waits and concurrency
issues.

NOTE – No matter the index (clustered or non-clustered), the leaf nodes are always kept in
order of the indexed key.

The fillfactor and padindex parameters can be altered to reflect the storage characteristics of
indexes only. The fill factor controls the table density, where a high value increases the number of
rows stored per page and enhances index-scan and read-ahead performance, but adversely affects
page splits on row updates or new insertions. The padindex setting controls free space higher up

140
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

in the b-tree structure, leaving space at the intermediate nodes in the b-tree based on the current
fill-factor setting (will always leave space for one row).

Monitoring page splits is tough, why? because there is not real way to tracing in real time
where the splits are occurring (especially on a very busy database).

To begin with we can use the NT performance monitor, select the Access Methods performance
object for the instance and choose the page splits/sec counter. There is no specific value as
such we should be looking for, I tend to look at an hourly average over a number of days to
determine the need for further concern. You may be experiencing bursts of splits based on
batch data loads and bulk record manipulation which will ease the process of identifying the
tables concerned.

To drill down further, I typically scour the internet for a script that will run DBCC SHOWCONTIG
over all tables in my database. It is important to note that page splitting not only occurs in your
user databases, but can occur frequently in the system tables (especially MSDB). Anyhow, this
DBCC command displays fragmentation information for data and indexes. This will assist in
determining the tables requiring index rebuilds (re-indexing). Saying that, online index
defragmentation should be a regularly scheduled job for virtually all databases (consider
maintenance plans or again, writing your own script). This of course is based on the premise that
page splitting will increase index and table fragmentation.

The DBA should not spend hours attempting to resolve page splitting. I have yet to see any SQL
Server database that doesn’t experience some page splitting. The DBA will find it very difficult to
get any indicative figure on the rate of page splitting vs the overarching system performance. As
such, you should refocus on data reorganisation, and setting padindex and fillfactor appropriately
for frequently updated tables.

An example of re-indexing to alter padding and fill factor:

CREATE UNIQUE
INDEX [PK_efs] ON [dbo].[efs] ([col1])
WITH
PAD_INDEX,
FILLFACTOR = 80,
DROP_EXISTING
ON [PRIMARY]

On a side note to page splits, defragmentation of clustered indexes provides the best
opportunity to resolve fragmentation on the index and the physical (data) pages. The online
defragmentation option allows the DBA to alter the fillfactor, therefore, assisting in reducing
page splitting for the table. As there is no specific trace for a page split (there is but it is very
difficult to use), we need to proactively monitor fragmentation historically to determine the
effect of our change.

At the end of the day, the DBA needs to have a good understanding about:
a) database hot spots
b) indexing currently in place
c) frequency of de-fragmentation jobs
d) types of operations performed against the hardest hit tables

141
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Read the section on Index Skewing for more information on page splitting.

Important – Page splitting does not occur on clustered indexes only, any page that is near
full and a subsequent update cannot be accommodated in the page, resulting in a split. The
point is, index structure maintenance adds to total time to complete the split.

Performance Monitor (perfmon.exe)


For each SQL Server instance installed on the server a series of NT performance monitor counters
are installed. The DBA or system administrator should not remove them, as it will be very difficult
to monitor instance and database performance without them.

In Oracle, the counters are also applicable per database instance. The DBA can utilise the
command line utility operfcfg.exe as shown below:

C:\Chris Kempster>operfcfg -usystem -pking -dseca


Usage: OPerfCfg [-U <username>] [-P <password>] [-D [database name]]

C:\Chris Kempster>operfcfg -u system -p king -d seca


OPerfCfg: New registry values have been successfully set.

This utility alters selected entries in the registry for Oracle, namely:
HKEY_LOCAL_MACHINE\SYSTEM\CURRENTCONTROLSET\SERVICES\ORACLE?\PERFORMANCE

See \Oracle\DBS\operfXX.txt and sqlnet.txt for


more error information related to loading the
performance counters.

See oracleX.pmw performance monitor script file


to load the counters.

The SQL Server counteres are automatically installed with the instance. If they are not, then
try to re-register sqlctr80.dll and run the file sqlctr.ini, both located in the binn directory for the
instance. The DBA should also try the command lodctr.exe sqlctr.ini, and the unlodctr
command.

It is assumed that the DBA knows how to use performance monitor (perfmon.exe) and will not
be discussed in detail. Some important items to remember though:

a) each database instance has its own set of counters.

b) the system table master..sysperfinfo includes many of the database performance


counters. Many of these values are cumulative. See this Microsoft article for example
views over this table:
http://support.microsoft.com/search/preview.aspx?scid=kb;en-us;Q283886

142
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

c) you can monitor a server remotely, if you are having problems, map a drive or
authenticate to the remote domain first then try again, try the server IP then the host-
name (\\163.222.12.11 for example). You may need to re-start performance monitor
after authenticating as you can continue to have authentication problems.

d) use a scheduled collection of statistics over a period of time, attempt to get a “typical”
series of working days as a base line for analysis. Watch out for pay periods in HR
systems and key events for financial systems that can see dramatic variances in
performance.

e) attempt to understand the applications running against the database and associated
server architecture well in advance, this can take some time in complex environment
but is essential in the overall interpretation of performance monitor statistics.

f) don’t just rely on performance monitor, real-time analysis for a short period may see
dramatic spiking in CPU, IO and other counters that, when averaged out, may not be
evident in collected statistics.

g) get a list of all software installed and running (especially scheduled applications) on all
servers in the domain you are analysing. Relate these back to counters and counter
processes where possible.

h) take care with setting Y scale properties

i) be carefully when selecting counters and test with a small collection (a few minutes) to
be 100% sure you are collecting all counter data you require. This sounds obvious, but
never take it for granted as it is not worth the trouble.

j) to enable disk counters, execute the following from the command line and re-boot the
server. Run diskperf.exe /? for list of all options.
diskperf -y

To assist with performance analysis via the NT counters, the following are discussed:
Counter Meaning Category
Processor Utilization of each CPU of all threads for a specified process (or CPU
(_Total): % all processes if selected). Is total elapsed time that all threads
Processor Time of the process used the processor to execute instructions.
Anything over 75% over a sustained period needs to be
(or single process) investigated, users may be experiencing response time issues at
lower figures though.

Filter on the sqlservr process if need be. This can also be used
to determine if SQL Server is using all CPU’s.

(Each processor has an idle thread to consume CPU cycles when


no other activity is going on.)
System: % Total Average CPU % utilization of all CPU’s are busy executing non- CPU
Processor Time idle threads. See System : Context Switches/Sec if >80% for 5-
10min periods
Processor Queue Thread queue length per CPU (ready threads only, not running CPU
Length ones), should be <= 2 per CPU. Reduce “max worker threads”

143
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

if this exceeds max/cpu and CPU utilization is not high. Use this
counter and one above to get overall CPU utilization.
Processor (_Total) This is the time spent running Kernal mode (privileged) code. If CPU
: % Privileged this counter is >= 20% over a period in relation to %UserTime,
Time this may indicate IO (paging) and disk array problems. Re-
and check % Disk Time counter (over 55%?) and other disk related
Processor (_Total) counters (such as queue length) to determine is this is not the
: % User Time cause.

System : Context How often NT switches context from one thread to another. If CPU
Switches/Sec >15000/sec for over 5-10mins then consider NT fibres. Re-
evaluate CPU performance by checking queue lengths.

A context switch occurs when a running thread is pre-empted by


a higher priority thread to hand over its CPU time. Other
scenarios include switching user modes. The counter is the sum
of all threads running on all processes.
Physical Disk To monitor each disk array (physical disk). Monitors read/write I/O
Object: Avg. Disk wait time for each array. If >2 for 5-10min periods the
[read, write] probably have a IO bottleneck. Use calculation physical-disk /
Queue Length disk-queue-length = avg-queue-length-per-disk. Use diskperf –
y to enable disk performance statistics on server.

For the drive being analysed, you need to divide the value by
the number of spindles in the drive, remember this, especially
for your RAID arrays. As an example, a RAID-5 array of 4 disks,
means you need to divide the value returned by 4, but a
RAID0+1 array of 10 disks means a division of 5, so a queue
length any greater than 10 (10/5 = 2) may be a problem.
Physical Disk: % How busy the physical array is. Should be <90%, use two I/O
Disk Time counters below to determine where the majority of the work
may be (on the read or on the write)
Physical Disk: % % IO Read performance. I/O
Disk Read
Physical Disk: % % IO Write performance I/O
Disk Write
Soft Paging – A value >0 indicates paging, both hard and soft. Soft paging is Soft Paging
Memory : Page applications referring to page file memory pages in RAM rather
Faults / sec than within the physical page files. Use for formula :

"Memory: Pages Faults/sec" minus "Memory: Pages Input/sec"


= Soft Page Fault/sec

Monitor Process : Page Faults/sec counter for sqlserver process


to determine if the sqlserver.exe process is being affected.
Paging File: % Check utilization of pagefile.sys. Is rarely used by SQL*Server Page File
Usage (if at all!), resize page file to a value slightly higher than what is Utilisation
reported. Check SQL*Server memory alloc to determine if the
usage of pagefile.sys is due to SQL*Server dynamically
allocating memory. Anything over 70% is a concern.
Memory: Pages/sec is the #pages per second that are paged out to disk Memory
Pages/Sec or paged into memory from disk (to resolve hard page faults). and Paging
and If pages/sec > 0 or page reads/sec > 5, windows may be going
Memory Object : to disk to resolve memory references (hard page fault). This is
Page Reads/Sec an important counter when evaluating paging on the server as it

144
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

will adversely affect IO and Kernal CPU time.


Memory: Available Should be >=5mb. SQLServer attempts to keep free at least 4- Memory
MBytes 10Mb. Is a sum of zeroed, free and standby memory lists.
Network Interface #bytes sent back and forth between the server and the network. Network
: Bytes Total/Sec Includes ALL traffic. Compare statistics with network card
supported maximums etc and take into consideration network
bandwidth and the number of cards in the server.
SQLServer Buffer Ratio of DB buffer cache hits. OLTP >= 95%, influences by free SQLServer
Manager: Buffer RAM and type of SQL running against server. Anything under
Cache Hit Ratio 90% is a concern.
SQLServer Cache Procedure cache (execution plan) hit ratio. Should be >= 90% SQLServer
Manager: Cache although can be application specific (i.e. large numbers of adhoc
Hit Ratio queries).
SQLServer Buffer How much physical RAM devoted to the DB buffer cache. Value SQLServer
Manager: Cache is in pages so multiple by 8192 to determine size in Kilobytes.
Size (pages) Should be very high, check if using dynamic memory allocation.
SQLServer General #user connections currently made to SQLServer. Single user SQLServer
Statistics: User may have multiple connections and multiple users may be
Connections sharing a single connection.
SQLServer Select all or some of the database instances. Count of SQLServer
Databases: transactions started on the database.
Transactions/sec
SQLServer Access Occurs when an index page becomes full and is split between SQLServer
Methods: Page the current page and newly allocation page on data insertion or
Splits / Sec key update. This is an intensive process that should be kept to
a minimum. Consider an index rebuild, and decreasing the fill-
factor from 100 (with padindex option) on indexes before the
rebuild. Use DBCC showcontig as required to evaluate user
tables.
SQLServer : SQL The ratio of recompilations to compilations should be very small. SQLServer
Server SQL High recompilations means numerous, adhoc dynamic SQL being
Compilations/sec run against the instance. This reduced procedure cache hit
and ratios and subsequently, overall performance.
SQL Re-
Compilations/sec
SQLServer Access Measure of unrestricted full table or index scans per second. SQLServer
Methods: Full Evaluate SQL and consider using the Index Tuning Wizard.
Scans / sec Performance may be fine and this is very much application
dependent. Remember that full table scans are not necessarily
bad (large number of smaller tables?) and this counter can be
difficult to interpret without good knowledge of the underlying
schema. Consider profiling (tracing) the application to
determine
SQLServer Access Average wait time of a variety of locks (DB, key, page, RID, SQLServer
Methods: Average table). Need to ID transactions that are causing the locks,
Wait Time (ms) consider using profiler for in-depth analysis.
SQLServer Locks: # deadlocks per second to monitor locking. SQLServer
Number of Use profiler for detailed analysis of deadlocks. Check application
Deadlocks / sec isolation levels and database isolation level. Evaluation code
segments and long running tasks with ranged operations over
numerous data sets. Anything > zero is a concern.
SQLServer These three counters can provide a measure of how busy your SQLServer
Database: (_Total) instance is in terms of transactions per second, coupled with the
Transactions/sec total number of SQL batches (all DML activity). The transactions
and / sec counter can be a tough one to really gauge actual

145
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQLServer transactions, for example, I may open a transaction, execute 20


Database: (_Total) SQL statements, and end the transactions, as such, the counters
Active reflect figures I may not expect.
Transactions/sec
and Example via Query Analyser (you should check this with COM+
Batch Requests/ VB code and a simple OLE-DB connection not using COM+):
sec
Transactions/sec
only measures inserts/deletes/updates

Batch Requests/sec
-- query analyser, batch requests / sec = 1
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses

-- query analyser, batch requests / sec = 8


select count(*) from sysprocesses
go
select count(*) from sysprocesses
go
select count(*) from sysprocesses
go
select count(*) from sysprocesses
go
select count(*) from sysprocesses
go
select count(*) from sysprocesses
go
select count(*) from sysprocesses
go
select count(*) from sysprocesses
go

-- query analyser, batch requests / sec = 1


begin transaction
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
select count(*) from sysprocesses
commit transaction

-- query analyser, batch requests / sec = 1


-- transactions / sec = 3
insert into aa values (1)
insert into aa values (1)

146
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

insert into aa values (1)

-- query analyser, batch requests / sec = 1


-- transactions / sec = 0
begin transaction
insert into aa values (1)
insert into aa values (1)
insert into aa values (1)
commit transaction
-- query analyser, batch requests / sec = 3
-- transactions / sec = 1
begin transaction
insert into aa values (1)
go
insert into aa values (1)
go
insert into aa values (1)
go
commit transaction

SQLServer Backup How fast backups are performing. If going to disk also review Backups
Device: Device queue length and the RAID array configuration in conjunction
Throughput with the counter.
Bytes/sec

I should point out that it is easy to get “hooked up” with some of them, and one poor performing
figure may not correspond directly to the specific problem, only to find another counter is skewing
the result. There are a range of websites and good books that cover performance counters in detail
to provide further assistance with analysis.

The DBA should take a “baseline” data collection using these counters. The interval may range
from every five minutes to as little as every twenty seconds (ideally over a range of days). The
collection is essential for ongoing performance monitoring, and performance tuning.

Trace Flags
There are numerous trace flags available to the DBA but most are not formally documented. A
great source of information for the documented and undocumented trace events comes from the e-
book “Transact-SQL Language Reference Guide” (47). I highly recommend that you register this e-
book as it is an excellent introduction to T-SQL programming commands.

The T-SQL language reference lists 20+ trace flags, whilst the online documentation lists four.
Some of the flags are shown below.

Trace# Summary

260 Print extended stored procedure version information

147
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

326 Prints information about the cost of non-clustered index sorts

552 Disable read-ahead manager

653 Disable read-ahead manager for current connection

1204 The locks participating in the deadlock

1205 Detailed information about the command executed at the time of a


deadlock.

1206 Shows additional formation about locks at the time of a deadlock

1807 Allows the use of network based database files.

3104 Bypass checking for free space

3502 Log start and end of a checkpoint

3602 Record all error and warning messages send to the client

3607 Skip recovery of all database at instance startup

3608 As above except the master database

3609 Skip creation of the tempdb on startup. (important for tempdb


creation issues related to model database problems).

4022 By-pass auto-start stored procedures in the master database.

7300 Get extended error information related to the execution of distributed


queries.

8687 Disable query parallelism

8602 Ignore all index hints

8687 Disable query parallelism

The trace events can be set on instance start-up, or for a session.

On startup, we use the –T or –t option, this can be set via Enterprise Manager as shown
below, or you can go to the registry and alter the startup options. You need a new –T[trace#]
for each flag being set, do not try separating them via commas or spaces.

148
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

This particular trace will force the logging of checkpoints:

checkpoint -- force the checkpoint

Important – Trace flags set with the –T startup option affect all connections.

To view the current enabled session and database wide traces, use the command:

DBCC TRACESTATUS(-1)

Or rather than using –1, enter the specific trace event#.

For the current connection we can use the DBCC TRACEON and DBCC TRACEOFF commands.
You can set multiple flags on and off via DBCC TRACEON(8722, 8602[,etc])

Use profiler to trace existing connections, even so, remember that these trace flags are not
the same as trace events as used by profiler (sp_trace_setevent).

NOTE – Use trace flags –T1024 and –T3605 to enable extended deadlock tracing.

149
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Indexing
It is worth mentioning indexing in terms of their use, performance, reorganisation and
statistical collection. It is important to remember that, no matter the DBMS, the indexing
mechanics are typically the same (in concept) and are critical for the overall performance of
your system.

Index Types

In SQL Server, we are somewhat restricted in terms of the types of indexes available when
compared to Oracle, this may change over time but the time being we only have:

a) Indexed Views (materialised views)

b) Clustered indexes
a. Leaf nodes contain the actual row data pages

c) Non-clustered indexes
a. Leaf nodes are pointers to row data pages, or, if the table also includes a
clustered index then it will point to the clustered index leaf nodes (requires a
bitmap lookup step in the execution plan).

The first question we ask ourselves is when to use a clustered index verses the standard heap.
As you can only have one per table, this gets somewhat tricky as you need to understand the
types of queries being executed. There is no definitive answer, but consider the following:

a) clustered indexes are best suited to range queries rather that highly selective row
lookups. A range based query may be over a series of dates, category types etc.

b) clustered indexes are also beneficial for single key lookups, primarily when most of the
record will be retrieved. Remember that non-clustered indexes use the clustered index
to locate the data rows and hold the clustered keys in their leaf nodes (resulting in
more IO).

c) clustered indexes are ideal around columns used in order by and group by clauses

d) a tables data pages can only be defragmented online via its clustered index (row re-
allocation may occur with the command DBCC shrinkdatabase command, being a form
of re-organisation).

e) identity column primary keys, clustered indexes can be beneficial (so long as its not
being wasted on a more commonly used complex query).

With identity keys in general (clustered or not) the possibility of page splits is close to
zero (not taking into consideration subsequent row updates etc) as the in increasing
key value will be inserted in order. Be aware though, that the adverse affect is the
creation of “hot spots” over the last page that can result in locking/blocking issues.

150
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Although fine, such points are close to useless unless you have a good understanding of the
DML running against your DBMS.

NOTE - As with oracle, the more indexes on a table, the slower subsequent DML will be.
Consider this when bulk loading data especially or systems requiring high insert/update/delete
throughout over query speed.

Moving to non-clustered (heap) indexes, be aware that if you drop or re-created a clustered
index associated with the table, all non-clustered indexes must also be rebuilt. The DBA
should consider in non-clustered indexes over all foreign key columns not partaking in the
primary key. This is a common practice; even when there is poor selectivity in improving
merge join performance. Always remember the following statement from the SQL Server 2k
BOL:
“If the table does have a clustered index, or the index is on an indexed view, the row locator is the clustered index key for the row. If
the clustered index is not a unique index, SQL Server 2000 makes duplicate keys unique by adding an internally generated value. This
value is not visible to users; it is used to make the key unique for use in nonclustered indexes. SQL Server retrieves the data row by
searching the clustered index using the clustered index key stored in the leaf row of the nonclustered index.”

The non-clustered indexed as in Oracle are ideal for highly selective columns. As you expect, a
scan over a non-clustered index results in a scan over the clustered index to locate the
physical row. You will see this in your explain plans as:

In a bookmark lookup, we utilise the clustered index (over the primary key in this example), to
look up the rest of the table data. This can be a misnomer though, as the optimiser will also
shown this operation even though a clustered index does not exist, but we still need to locate
the rest of the column data to suffice the query. Also note that this lookup will occur if we
have a covering index.

WARNING – Take care with indexing, you can index the same column multiple times in SQL
Server.

The final index type is not really any different from the two mentioned, but in terms of Oracle,
is equivalent to materialised views.

Like Clause

Using a leading ‘%’ wildcard pattern character at the start of a string will not allow optimizer to use
indexes. Take are good think about what the end-user really wants, and consider full text indexing
for complex searching over string columns.

151
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Functions and Indexes

Within Oracle, the Function Based Index was created to allow the DBA to index a column with a
function applied to it. A classic example is:

where UPPER(surname) = ‘KEMPSTER’

where a function based index is created over the function/column UPPER(surname).

In SQL Server this is a problem that will result in indexes not being used. To get around this, take
a careful look at the where clauses, and determine if you can remove or reverse the call, here is a
classic example:

where convert(varchar, sale_date, 103) = ‘19/1/2001’

use this instead:

where sale_date >= ‘19/1/2001’ and sale_date < ‘20/1/2001’

Composite Indexes

As with Oracle, a composite key will not be used unless the left most column is used in the where
predicate. Within the where, the column must also be first (top most) column to be used by the
optimizer. Such indexes are good for clustered indexes, especially where only some of the leading
columns are being used.

Indexed Views (Materialised Views)

A view can be indexed, unfortunately there are a whole range of restrictions that can make the
option undesirable. Some of which are:

a) select statement cannot include


a. union
b. sub-queries
c. self joins
d. TOP
e. ORDER BY
f. DISTINCT
g. COUNT(*)
h. * or table.*
b) Session options set ON
a. ANSI_NULLS
i. When set ON, this also sets the following SQL-92 options:
1. ANSI_NULLS (set at execute time)
2. ANSI_PADDING (set at execute time)
3. ANSI_WARNINGS (set at execute time)
4. ANSI_NULL_DFLT_ON (set at execute time)
5. CURSOR_CLOSE_ON_COMMIT (set at execute time)
6. IMPLICT_TRANSACTIONS (set at execute time)
7. QUOTED_IDENTIFIER (set at parse time)

152
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

b. ANSI_PADDING
c. ANSI_WARNINGS
d. ARITHABORT
e. CONCAT_NULL_YEILDS_NULL
f. QUOTED_IDENTIFIERS
c) Session options set OFF
a. NUMERIC_ABORT
d) All columns must be named (column name with suffice but if using function calls the
explicitly name the column).
e) Cant index columns using indeterministic functions (eg. Getdate)
a. The view must be deterministic
f) Clustered index must exist before other non-clustered indexes are created. The
clustered index must be unique
g) Must refer to tables using the two part syntax
a. dbo.mytable – ok
b. mytable – fails
h) Must be bound to the schema (tables) in which the view is sourced from

The DBA can check session properties via the command:

Select sessionproperty('ARITHABORT')
or
DBCC USEROPTIONS

A value of zero means the property is not set.

The schema binding option is the critical part to creating the materialized view. Once done, we will
create a clustered index over the view and optionally a number of non-clustered indexes. For
example:

CREATE VIEW viewtest1 WITH SCHEMABINDING


AS
select title, au_ord, au_lname, price, ytd_sales, pub_id
from dbo.authors, dbo.titles, dbo.titleauthor
where authors.au_id = titleauthor.au_id
and titleauthor.title_id = titles.title_id

CREATE UNIQUE CLUSTERED INDEX viewtest1_ix ON viewtest1(title, au_ord)

Its not until you create the index will you get errors related to function calls used within the view.
For example, you may get something like:

Server: Msg 8662, Level 16, State 1, Line 1


An index cannot be created on the view 'viewtest' because the view definition includes an unknown value (the
sum of a nullable expression).

You can pre-determine this via the command:

select ObjectProperty(object_id('viewtest2'),'IsIndexable')

To force the index over the view, use the hint:

153
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

select * from viewtest1 with (noexpand)

Take care with hints, the optimizer will chose the optimal indexing path where possible based on
the expansion of the view, its tables and the tables underlying indexing and histograms. The index
on the view may simply be the wrong way to go to suffice the query.

In the above view created against the PUBS database, the expansion and nonexpansion gives some
interesting results:

set statistics io on

-- use the indexed view


select * from viewtest1 with (noexpand)

Table 'viewtest1'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0.

-- optimizer chooses, expand view forces the optimizer not to use indexed views
select * from viewtest1 option (expand views)
or
select * from viewtest1 -- even with no hint, the optimizer expanded the view

Table 'titles'. Scan count 25, logical reads 50, physical reads 0, read-ahead reads 0.
Table 'titleauthor'. Scan count 24, logical reads 48, physical reads 0, read-ahead reads 0.
Table 'authors'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0.

To change the underlying tables in any way, the schema bound view must be dropped first.

Covering Indexes

A covering index is one in which the index includes all columns required for the index to resolve the
query without having to do a further lookup for the rest of the column data. An example is shown
below.

drop table mycovering


create table mycovering (col1 int, col2 int, col3 int, col4 int)
create index mycovering_ix on mycovering (col2, col3, col4)
select col2 select col2
from mycovering from mycovering
where col4 = 2 where col4 = 2
and col3 > 1 and col1 > 1

154
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Index Skewing

In Oracle, we have the concept of Reverse Key Indexes, which resolves index skewing in the b-
tree, where one side of the tree becomes a “hot spot” in terms of new insertions and whose depth
also increases (skewed to one side) with a monotonically increasing key values. For example:

101 201

101 102

So in the example above (very rough example mind you), the key value is reversed to produce a
more balanced tree structure, especially during deletions resulting in index browning. The only
option in SQL Server is the ASC or DESC options when creating the index, altering the sort order of
the key columns, this is not the same as reverse key indexes. To monitor index height, use the
INDEXPROPERTY command, for example:

SELECT INDEXPROPERTY(OBJECT_ID('MyTable'), 'PK_MyTable', 'IndexDepth')

In the case of identity columns, the depth increases slowly, with more intermediate index keys
being added (resulting in page splitting higher at these nodes). In the example below, the index
height remains at two, but during the bulk insertion of records over the clustered primary key
identity column, we see a large number of page splitting due to page allocations and the increased
number of intermediate nodes.

page splits during 115k record insertion.

CREATE TABLE [test1] (


[col1] [int] IDENTITY (1, 1) NOT NULL ,
[col2] [char] (200) COLLATE Latin1_General_CI_AS NULL ,
CONSTRAINT [PK_test1] PRIMARY KEY CLUSTERED
(
[col1]
) ON [PRIMARY]
) ON [PRIMARY]
GO

With 303104 rows, index depth 2, index size 216Kb, data 63816Kb, reserved 64064Kb

155
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Index Statistics and Fragmentation

The following commands can be used to view table indexes and subsequent statistical
information:

exec sp_helpindex ‘products’

Notice the duplicate


indexes over
categoryID and
supplierID.

To analyse index effectiveness (products = table, productname = index name):

DBCC SHOW_STATISTICS (products, productname)

To analyse index and table fragmentation:

DBCC UPDATEUSAGE ('northwind', 'products','productname')


DBCC SHOWCONTIG (products, productname)
use DBCC SHOWCONTIG (products) to view the tables storage characteristics.

To rebuild indexes:

DBCC DBREINDEX ('northwind.dbo.products', productname, 80) -- 80 is new fillfactor


DBCC INDEXDEFRAG (northwind, products, productname)

NOTE – As with composite keyed indexes in Oracle, the leading column must be used for the
index to be utilised by the optimiser. Also note that in non-clustered indexes (heaps), the leaf
nodes are not linearly linked listed.

You cannot alter the padindex parameter via the DBCC commands.

Heaps, Clustered Indexes and Fragmentation

We know that DBCC DBREINDEX and INDEDDEFRAG can be used to defragment the index, but not
necessarily the table itself. We have assumed though, that a clustered index that is defragmented
will also defragment the table itself and not only the index. The following example attempts to test
this theory:

In the Northwind sample database, we have duplicated the products table, retained the identity
column used for its primary key and forced some fragmentation to occur. We will defragment with
the DBCC DBREINDEX command and review the subsequent storage characteristics of the table
and the associated index structure.

156
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

-- Insert rows into the new table (non-clustered primary key)


name rows reserved data index size unused
MyProducts 19712 2576 KB 2216 KB 328 KB 32 KB
Table Storage Summary
DBCC SHOWCONTIG scanning 'MyProducts' table...
Table: 'MyProducts' (1877581727); index ID: 0, database ID: 6
TABLE level scan performed.
- Pages Scanned................................: 277
- Extents Scanned..............................: 39
- Extent Switches..............................: 38
- Avg. Pages per Extent........................: 7.1
- Scan Density [Best Count:Actual Count].......: 89.74% [35:39]
- Extent Scan Fragmentation ...................: 12.82%
- Avg. Bytes Free per Page.....................: 616.5
- Avg. Page Density (full).....................: 92.38%

-- Delete random rows (493 rows)


name rows reserved data index size unused
MyProducts 19219 2576 KB 2216 KB 328 KB 32 KB
Table Storage Summary
DBCC SHOWCONTIG scanning 'MyProducts' table...
Table: 'MyProducts' (1877581727); index ID: 0, database ID: 6
TABLE level scan performed.
- Pages Scanned................................: 277
- Extents Scanned..............................: 39
- Extent Switches..............................: 38
- Avg. Pages per Extent........................: 7.1
- Scan Density [Best Count:Actual Count].......: 89.74% [35:39]
- Extent Scan Fragmentation ...................: 12.82%
- Avg. Bytes Free per Page.....................: 801.8
- Avg. Page Density (full).....................: 90.09%

-- Insert more data (cause fragmentation)


name rows reserved data index size unused
MyProducts 38438 4944 KB 4240 KB 608 KB 96 KB
Table Storage Summary Primary Key Storage Summary
DBCC SHOWCONTIG scanning 'MyProducts' table... DBCC SHOWCONTIG scanning 'MyProducts' table...
Table: 'MyProducts' (1877581727); index ID: 0, database ID: 6 Table: 'MyProducts' (1877581727); index ID: 2, database ID: 6
TABLE level scan performed. LEAF level scan performed.
- Pages Scanned................................: 530 - Pages Scanned................................: 73
- Extents Scanned..............................: 71 - Extents Scanned..............................: 12
- Extent Switches..............................: 70 - Extent Switches..............................: 12
- Avg. Pages per Extent........................: 7.5 - Avg. Pages per Extent........................: 6.1
- Scan Density [Best Count:Actual Count].......: 94.37% [67:71] - Scan Density [Best Count:Actual Count].......: 76.92% [10:13]
- Extent Scan Fragmentation ...................: 8.45% - Logical Scan Fragmentation ..................: 1.37%
- Avg. Bytes Free per Page.....................: 475.1 - Extent Scan Fragmentation ...................: 41.67%
- Avg. Page Density (full).....................: 94.13% - Avg. Bytes Free per Page.....................: 197.8
- Avg. Page Density (full).....................: 97.56%

-- attempt to fix fragmentation


DBCC DBREINDEX ('northwind.dbo.myproducts', PK_MyProducts)
name rows reserved data index size unused
MyProducts 38438 4944 KB 4240 KB 608 KB 96 KB
Table Storage Summary Primary Key Storage Summary
DBCC SHOWCONTIG scanning 'MyProducts' table... Table: 'MyProducts' (1877581727); index ID: 2, database ID: 6
Table: 'MyProducts' (1877581727); index ID: 0, database ID: 6 LEAF level scan performed.
TABLE level scan performed. - Pages Scanned................................: 72
- Pages Scanned................................: 530 - Extents Scanned..............................: 10
- Extents Scanned..............................: 71 - Extent Switches..............................: 9
- Extent Switches..............................: 70 - Avg. Pages per Extent........................: 7.2
- Avg. Pages per Extent........................: 7.5 - Scan Density [Best Count:Actual Count].......: 90.00% [9:10]
- Scan Density [Best Count:Actual Count].......: 94.37% [67:71] - Logical Scan Fragmentation ..................: 0.00%
- Extent Scan Fragmentation ...................: 8.45% - Extent Scan Fragmentation ...................: 0.00%
- Avg. Bytes Free per Page.....................: 475.1 - Avg. Bytes Free per Page.....................: 88.1
- Avg. Page Density (full).....................: 94.13% - Avg. Page Density (full).....................: 98.91%

157
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

We see no change in the physical table storage with a heap index. Altering the index to a cluster,
deleting and inserting more data, we see that re-indexing will also defragment the underlying table as
well as the immediate nodes for the index. As we would expect.

name rows reserved data index size unused


MyProducts 38438 4944 KB 4240 KB 608 KB 96 KB
Table Storage Summary Primary Key Storage Summary
(identical to that of the table)
DBCC SHOWCONTIG scanning 'MyProducts' table... DBCC SHOWCONTIG scanning 'MyProducts' table...
Table: 'MyProducts' (1877581727); index ID: 1, database ID: 6 Table: 'MyProducts' (1877581727); index ID: 1, database ID: 6
TABLE level scan performed. TABLE level scan performed.
- Pages Scanned................................: 757 - Pages Scanned................................: 757
- Extents Scanned..............................: 100 - Extents Scanned..............................: 100
- Extent Switches..............................: 99 - Extent Switches..............................: 99
- Avg. Pages per Extent........................: 7.6 - Avg. Pages per Extent........................: 7.6
- Scan Density [Best Count:Actual Count].......: 95.00% [95:100] - Scan Density [Best Count:Actual Count].......: 95.00% [95:100]
- Logical Scan Fragmentation ..................: 0.13% - Logical Scan Fragmentation ..................: 0.13%
- Extent Scan Fragmentation ...................: 4.00% - Extent Scan Fragmentation ...................: 4.00%
- Avg. Bytes Free per Page.....................: 2681.3 - Avg. Bytes Free per Page.....................: 2681.3
- Avg. Page Density (full).....................: 66.87% - Avg. Page Density (full).....................: 66.87%
Table Storage Summary after reindex Primary Key Storage Summary
(identical to that of the table)
DBCC SHOWCONTIG scanning 'MyProducts' table... DBCC SHOWCONTIG scanning 'MyProducts' table...
Table: 'MyProducts' (1877581727); index ID: 1, database ID: 6 Table: 'MyProducts' (1877581727); index ID: 1, database ID: 6
TABLE level scan performed. TABLE level scan performed.
- Pages Scanned................................: 510 - Pages Scanned................................: 510
- Extents Scanned..............................: 64 - Extents Scanned..............................: 64
- Extent Switches..............................: 63 - Extent Switches..............................: 63
- Avg. Pages per Extent........................: 8.0 - Avg. Pages per Extent........................: 8.0
- Scan Density [Best Count:Actual Count].......: 100.00% [64:64] - Scan Density [Best Count:Actual Count].......: 100.00% [64:64]
- Logical Scan Fragmentation ..................: 0.00% - Logical Scan Fragmentation ..................: 0.00%
- Extent Scan Fragmentation ...................: 0.00% - Extent Scan Fragmentation ...................: 0.00%
- Avg. Bytes Free per Page.....................: 58.9 - Avg. Bytes Free per Page.....................: 58.9
- Avg. Page Density (full).....................: 99.27% - Avg. Page Density (full).....................: 99.27%

Rebuilding Indexes

The DBA can use WITH DROP EXISTING clause to rebuild indexes. If a clustered index is rebuilt, so
will any other index. . SQL Server support parallel index rebuilds.

Performance Counters

There is no simple way of determining the relevancy of indexing. I tend to run profiler (trace) and
collect all DML being executed against the database of interest (or filter out specific tables). I then
run this data through the index-tuning wizard and carefully read the summary reports on table
access, columns accessed and recommended indexes. For in-house applications where you have
some control over indexing (without breaking your support agreement) this method works well on
your development and test servers to get a feel of the queries being executed and the most
commonly used tables.

The performance counters may compliment the tracing approach, but I find them somewhat limited
and very easy to misinterpret, as you will see in the comments below. The counters are:

¾ SQL Server:Access Methods\Index Searches/sec


As an example of this, a 6 row table with a clustered index scan over the primary key,
resulted in a avg count of 12 to 20 for this counter. Dropping the table returned a value of
30 and the batch insertion of 6 rows also saw a count of 30. This may be helpful in

158
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

determining the performance impact of too many indexes with heavy insert/delete/update
SQL. With no indexes but 6 rows, we see a single full tablescan but also 6 index scans.

¾ SQL Server:Access Methods\Full Scans/sec


From a lot of testing, this counter provides a accurate figure of full table scans.

The counters are for the entire instance and not database specific.

Index Management via Enterprise Manager

The DBA can alter index structures via:

a) Database Diagrammer

b) Designing a table (right click on table, select design table and select index icon)

c) Manage Indexes option (right click on table, All Tasks Æ Manage Indexes)

Option c) is quite functional and has that sort of Oracle Enterprise Manager type feeling to it. Be
aware though that this option can be a little restrictive when shifting between clustered and non-
clustered index storage. As such, switch to b) to resolve the issue. Trace the output via profiler (or
view scripts generated via their menu options) to understand how to manage indexes via raw SQL
commands.

Summary

There is no magical wand for indexing. The DBA needs to have an intimate understanding of
the application(s) running against the database, and from there, make informed decisions on
the indexing paradigm. As a very broad rule, you can not go too wrong with:

a) indexing all foreign keys


b) altering and monitoring index storage properties (padindex and fill factor) according to
the avg% of inserts, updates, deleting going on verses reads.
c) Leave auto-statistics collection on
d) Utilising profiler to collection SQL, pass through index tuning wizard to assist in gauging
the possibility for new indexes and reworking existing indexes.
e) Re-indexing (de-fragmenting) on a regular basis.
f) Utilising clustered index primary keys if another option is not suitable (see clustered
index issues previously).

159
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Database File IO stats


At SQL Server Central.com, the columnist Cathan Kirkwood wrote a great article titled “How to
Diagnose and Fix Wait Locks”. Within this it describes a call to ::fn_virtualfilestats to retrieve file IO
statistics. With the appropriate smarts you could write a great real-time IO monitoring tool for your
database with such a function.

The call is simple enough:

-- 6 = DB ID, 1 = file id
select * from ::fn_virtualfilestats(6,1)

Showing these cumulative results:

Take care with the NumberReads, these are physical IO’s, and will not measure buffer cache
lookups. The NumberWrites is another tricky one, as its very much dependent on the
checkpointing and flushing pages to disk. The IoStall MS represents IO waits in milliseconds
between refreshes. Here is an example, without the DBCC and checkpoint commands, you may
see little or no change in the figures returned by the file IO function call.

DBCC DROPCLEANBUFFERS
select * from ::fn_virtualfilestats(6,1)
select count(*) from products
delete from EmployeeTerritories
checkpoint -- flush the log buffer
select * from ::fn_virtualfilestats(6,1)

Wait Statistics
To view wait statistics, use the command:

DBCC SQLPERF(WAITSTATS)

160
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Also query sysprocesses where waittime > 0 and spid > 50, looking up waittype, waittime,
lastwaittype, wait resources.

Many of the wait types listed is related to the specific types of lock objects SQL Server can take out
(see Transaction Management chapter). Two key waits to review are related to transaction log
management, they are:

LOGMGR Waiting on the log writer to start writing


IO_COMPLETION Waiting on disk resources to be free
WRITELOG Waiting on the write (finish) of transactions to disk

Microsoft poorly documents the figures. Carefully evaluate their use and always use in conjunction
with broader statistics from performance monitor.

STATSPAK
There is no equivalent utility to Oracle statspack in SQL Server. The analysis of the databases
overarching performance requires a range of tools but we can get “similar” statistics via
performance monitor and its numerous counters.

General Performance Tips


Some readers will not like this section, but I am not converting it to lengthy paragraphs that take
forever to complete. Here we present a series of tips and “food for thought” in terms of
performance.

Server Configuration
• NTFS
o partitions <= 80% capacity
o cluster size to 64k
o format in NTFS 5.x or above
o don’t place database files on compressed NTFS partitions
• Control Panel
o Start -> settings -> control panel -> system -> performance, Set “Application
Performance” to None.
o Start -> settings -> control panel -> network -> services, set “maximize
throughput for network applications” as the default is “maximize throughout for file
sharing”. Reduces RAM usage.
o Remove unused network protocols
• Networking
o Windows 2k Server supports a larger MTU (1.5Kb to 9kb), consider altering it on
your network card based on careful analysis of network performance
o Check your network protocol list, if using, for example TCPIP, then ensures it is the
first protocol to be validated by Windows.
o Disable power management features for your network cards
• General

161
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

o By as much RAM as possible for the server, include array cache


o Use a very simple screen saver
o Avoid multiple terminal service sessions.
o Try and contact in professional NT administrators where possible to
check/recommend/configure your servers. Clearly outline the purpose and
application architecture up-front and any other constraints (SW/HW/$/MTTR).
o Don’t use your domain server as a database server, don’t install DHCP, DNS, time
servers etc, avoid or take care with Virus Scanners and their file scan properties.
o Verify the tape backup strategy, are backups running throughout the day? where is
the tape loader? can a delay cause the file backups to run during your busiest parts
of the day?

What can affect performance (not an exhaustive list)

• Application code
o T-SQL stored procedure code performance, use of stored procs vs inline
(embedded) data access code at the business layer
o Cursors are notoriously bad performers, utilise single DML statements where
possible
o Architecture (tiered architecture on separate servers?)
o Not using native XML from SQLServer (or code managed/generated?)
o Poor selecting of connection provider
o Lengthy transactions resulting in blocks and deadlocks
o Mis-understanding of COM+ transaction handling
o Triggers and user defined function (check affect of DML performance carefully)
• SQL performance
o Use of cursors vs batch-sql statements
o Indexing scheme
o Length of transactions
o Batch processing during the day
o Mix of OLTP vs DSS vs Reporting requirements on server verses auditing
requirements (trigger driven?)
• SQL Server Configuration
o Disk and file layout
o Automatic statistics collection
o Memory configuration
o Isolation level and transaction processing
• Physical data model design
o Query plan reuse, use of cursors, adhoc reporting
o Middleware (COM, COM+, MSMQ), location of data tier code
o Database Design
o Indexing scheme vs actual usage patterns from programmers
o Backup/Recovery model vs database usage and recoverability
o Normalisation
o Trigger design and usage
• Client and Server Hardware
o Client and Server Operating System Settings and Configuration
o Network Hardware and Bandwidth
o Verify with network administrators –

162
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ Link speeds and network card settings/config based on existing network


infrastructure.
o Other applications or systems sharing the same network links.
o How communication flows between all servers (routing, linked servers, firewalls)
o How internet users access your webservers
• The workload expected vs reality and peak periods.
o Total Number of Clients, connection method and pooling
• Varied client usage patterns, including batch jobs throughout the day,month,year
• Network design, routing, packet timeouts/loss, competing with other applications

Collecting SQL Server Statistics

• When running performance monitor, take care when setting the interval. The collection
and reporting is based on an average between the current and last collection, therefore,
if you are monitoring every 5mins, but your CPU time is spiking throughout this period,
the overall average may be somewhat low and will not reflect this in your graphs. A
consistent “spiking” in CPU time is typically related to poor performing application code
and/or SQL, if multiple users happen to hit the same code at the same time, this spike
will of course run longer but still may not reflect in the graphs. This may result in good
server performance statistics but poor application performance (end user experience).
• If you are using COM+ (component services), look at the properties for each installed
package, it will show:
o #objects instantiated
o #objects activated
o #objects pooled
o #objects in-call
o #objects call-time(ms)
this is very handy when tracking possible issues with DLLHOST.EXE processes going
wild with the CPU.
To locate the PID for a COM+ package, select properties for the “COM+ Applications”
folder within Component Services.
• Profiler is the key utility for collecting SQL and other SQLServer internal event
activities. It is important that the DBA has a good understanding on this trace utility
and the numerous parameters and events that can be monitored. Don’t run Profiler on
same server as you are monitoring.
• If collecting statistics to a file or a database, don’t write to the server you are
monitoring.
• Index tuning wizard

General DB Parameters, Settings and other DBA items

• Turn off the auto-close and auto-shrink options for your databases
• Manually configure database memory settings to control SQL Server memory usage and
its potential impact on the server.
• I rarely recommend any internal database setting changes unless there is a real,
testable need for it. Even so, setting such as max-async-io, recovery interval, min
memory per query, max degree of parallelism, max worker threads and common areas
that DBA’s consider altering.
• The DBA should put in place:

163
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

o Script (or use maintenance plan) to reindex user databases on a weekly basis
ƒ Dbcc Dbreindex
ƒ Dbcc indexdefrag
o Consider a script to manually update statistics daily
ƒ Dbcc updateusage
ƒ Update statistics..
o Do not alter locking and other advanced options without direction from Microsoft
OR you are completely satisfied that the change IS making a difference and is
repeatable on dev/test before moving to production. The DBA must be able to
monitor it over-time.
ƒ Use dbcc traceon and dbcc traceoff as required, some flags are at
instance startup only via –T parameter.

Physical Database Design

• Determine the requirements for fill-factors early. The fillfactor not only applies to
indexes but also affects the physical table themselves if clustered indexes used.
Consider the following settings:
o Very few updates/inserts (DSS/OLAP) – 0 or 100%
o Minor insert/delete/update activity – 90%
o OLTP system
ƒ Reference data – 90% to 100%
ƒ Other – 50 to 70%
ƒ Heavy inserts/updates – 25 to 45%
• Utilise file-groups (FG) with one or more physical data files (file-group striping) to
assist with separate data structures from one another, for example:
o PRIMARY – sys only objects
o DATA_FG – all tables (made default FG)
o INDEX_FG – all indexes
o AUDIT_FG – all audit tables
• File group considerations
o # files per group?
o what datafile should be placed on which storage set?
o what file groups do objects reside?
o FG backups vs other
• Do not use multiple files for transaction logs.
• A shorter row length = more data per page (also consider pad and fill-factors) = more
data in buffer cache per read
• Use varchar instead of char unless its:
o Always of a set, fixed length
o Very short (i.e. Y / N), if so, consider bit data type for 0 and 1 indicators
• Avoid uni-code data types where possible (eg. Nvarchar etc)
• Only make columns large enough (namely varchar data type) to support what is really
needed.
• Consider using the TEXT IN ROW feature for S2k. This allows you to control the storage
of smaller amounts of text and image data onto the data page. See article
http://www.sqlservercentral.com/columnists/bknight/textinrow.asp for a thorough
summary.
• Consider alternative datatypes for numerics based on the following:

164
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

o Bit (0 or 1)
o Tinyint (0 to 255)
o Smallint (-32768 to 32767)
o Integer (-2,147,483,648 to -2,147,483,647)
o Bigint (-9,223,372,036,854,775,808 to -9,223,372,036,854,775,807)
o Money (-922,337,203,685,477.5808 to +922,337,203,685,477.5807)
o Smallmoney (-214,748.3648 to +214,748.3647)
o Float (-1.79E + 308 to -2.23E – 308, 0, .23E + 308 to 1.79E + 308)
o Real (-3.40E + 38 to -1.18E - 38, 0, 1.18E - 38 to 3.40E + 38)
• Consider smalldatetime if the nearest minute is ok.
• Avoid GUIID columns, but may be unavoidable in some forms of replication
• Primary keys are, by default, clustered indexes. In many cases this may not be the
ideal candidate and other columns with range based scan characteristics may be a lot
more optimal.
• Index foreign keys not already part of the primary key to speed common table joins.
• For disconnected/stateless environment, consider the 3 columns:
o Last_updated_on
o Last_updated_by
o Update_count
for all tables to manage concurrency issues, but is also handy with applying batch
updates where you can use the last_updated_by column to “mark” the rows altered.
• Review auditing requirements as early as possible, retention periods, and the use of
these audit tables (in reporting and general lookup).
• Consider covering indexes (non-clustered index for every column in the table) for
selected tables with heavy read characteristics.
• Indexed views
o Can take a significant performance hit in write intensive applications
o Must create view with schemabinding option, when done, you cant alter table
structure until the indexed view dropped.
o In a situation where SELECT statements retrieve a result set that is an
aggregate, including summation or other calculations from one or more different
tables. In this case, a pre-aggregate result set stored as an indexed view speeds
up read performance tremendously.
• Consider using CREATE STATISTICS where you believe the optimizer may benefit from
information about data distribution
• Use non-clustered for highly selective columns (95% or more of results can be
eliminated) and clustered for range lookups. Remember that primary keys are, by
default, clustered indexes unless altered. This rule is not hard-and-fast, and should be
carefully considered early in the project as there is only 1 clustered index per table and
it can be difficult to alter this at a later point in time.
• Use identity columns carefully. Follow standard normalisation practices. Don’t us
identity because its simply convenience, sure, single column numerics keys are fast,
but can have adverse affects with:
a) replication
b) readability and maintainability
In the end, the “because its simple and easy” attitude should not be you key reason for
sequenced columns.
• Begin to evaluate the need for federated databases early in the design phase. It will be
very costly to change to this infrastructure later.

165
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

• Evaluate as soon as possible database links (local and or remote ones) to the network
and what applications will they be sharing the data lines with (also the server
performance of the remote connection).
• Consider indexed views and indexed computed columns, this may be a result of
denormalisation to some degree. This will impact insert performance.
• Consider computed columns over standard de-normalisation practices:
o Example:
create table mytab (col1 integer, col2 integer)
alter table mytab add mycalccol as col1 + col2

creates a new column with the formula property set of data type INT. If one
data type was a int and the other float, the calculated col will take on the float
datatype. You can now create an index on the computed column (known as a
function based index) so long as the calculation is deterministic.
• Will full-text indexing be used?
o Use timestamp datatype for all tables to track incremental updates
o Plan well ahead of time with server administrators on CPU and IO impacts, they
can be significant.

SQL and Developer Tips

• Minimise network round trips where possible.


o utilise stored procedures and consider carefully the use of the FOR XML clause to
return XML wrappered result sets.
o Use SET NOCOUNT ON for all stored procedures once debugged and ready for
testing/production.
o Use stored procedures for all queries rather than embedding SQL logic in your
COM/COM+ VB code at the middle tier. The code will run faster and it will be
much easier to debug and perform impact analysis due to database changes.
• Only select what you need to, i.e. SELECT * FROM is not required in any case.
• Use the ANSI SQL standard where possible, i.e. INNER/OUTER etc join clause syntax to
assist the parser in generating plans.
• Review the indexing scheme used on tables before writing queries and suggest new
indexes to the DBA as required.
• Search arguments
o Optimal – exact match, range of values, joins with AND’s
o Sub-optimal – not, not in, !=, <>, NOT EXISTS, computations prior to data
access.
o Between – equivalent to >= and <= ranged lookup
o LIKE – if % is used at the start of the search criteria, an index cannot be used.
• Deadlocking
o Describe isolation levels and the SQL Server locking mechanism with senior
development staff and document the strategy.
o Access tables in the same chronological (name) order and DDL operation order
(if possible).
o Keep transactions short as possible, take care with COM+ transactions which
use a serialisable isolation level.
o Reduce large, range DML operations where possible.

166
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

o Consider locking hints (in liaison with the DBA) where appropriate to reduce
locking issues.
• Describe the following concepts to developers
o Selectivity of indexes (# rows returned)
o Join types
o Index usage and control
o Storage (row/page/extents and logical vs physical page access)
• For concatenated index, the 1st column in the index must be used in order for the index
to be included as a valid option for the optimizer.
• In most cases, NOT EXISTS will out perform inner join and NOT IN alternatives (based
on appropriate indexing).
• Take care with the WITH COMPILE option for stored procedures, unless the stored
procedure uses dynamic SQL, there is no need to re-generate the execution plan.
• Don’t name stored procedures with sp_ for its prefix as a master db lookup will occur
first, then a dbo owner check, then a check based on the users DB login name.
• Objects that are called within the same stored procedure should the same owner,
preferably dbo, own all. If not, SQL Server may need to do further name resolution to
resolve the objects (all objects should be dbo owned as best practice).
• Developers should have some basic understanding on reading the plan output.
• Some notes on the SHOWPLAN option:
o Use SHOWPLAN_ALL in SS2k, but will not actually run the SQL, therefore IO and
TIME set options will return nothing.
o Query type (insert, update, delete, select)
o Tables listed in order of processing
o For each table the access method is indicated (table scan, index lookup etc)
o Parallelism is indicated
o Worktables may be included – temporary table in tempdb
o Aggregates may require many steps
ƒ Vector (group by used in conjunction with aggregate function)
ƒ Scalar (aggregate function used in select statement)
o Exists table – exists, in, or,>=, any used
o STEP’s, where SQLServer required many steps to retrieve or access data
ƒ Step may involve sorting
ƒ Getsorted – temp work table created for sorting
• Some notes on the STATISTICS IO option:
o Also see STATISTICS TIME option
o Logical reads – total # of pages accessed
o Physical reads - # pages read from disk into buffer cache
o Read ahead reads – # pages cached by read-ahead manager
o Scan count - # times table was accessed
• When attempting to tune queries, consider dbcc dropcleanbuffers and free proc cache
to clear out the data base buffer cache.
• Sorting
o Optimiser will sort when distinct, union or order by clauses are specified
o If no order by criteria is specified, records are returned randomly based on
buffer cache lookup.
o Default is ascending order

167
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Backup and Recovery

• Backup Destination
o Is this a dedicated disk or also used for database files?
o How many disk spindles are in use?
o Is the backup over a network connection that is already very busy
o If you are going directly to tape, ensure stream speed is not imposing on your
backup window.
• Restoring Databases
o Purge MSDB backup history on a regular basis. If you are using the GUI to
restore and you select a DB that has a lot of historical data, the GUI may take
some minutes to respond whilst it reads the sys tables.
• The SQL Server backup command is very slow and produces large files, as it uses very
little of the CPU. Consider SQL*Lightspeed (3rd party product) for a fantastic
performance increase and much smaller backup files.

CPU is a Bottleneck?

• Have you accurately determined where the CPU bottleneck is occurring?, can it be
repeated successful for further testing, and is it kernel related or user process related.
• Get faster CPUs or add additional CPUs (do not forget the licenses).
• Get CPUs with a larger L2 cache. In most cases, simple opt for faster or more CPU’s
• Re-check application components and try to get an accurate measure between
database activity vs business layer activity. For example, is the wrappering of record
sets with XML the real problem vs database query performance issues?
• Move some of the processing load to another SQL Server.
• Consider turning on Windows NT fibres.
• Be sure that both OLTP and OLAP queries are not being run on the same server. These
different database applications should be performed on separate servers.
• Re-check your statistic, namely kernel time, if kernel time is high recheck your paging
statistics and other IO statistics as this may be a flow-on affect.

I/O is a Bottleneck?

• Consider file-group striping, create one file per disk array and re-import data, data will
be evenly striped over the file-groups physical file set, for a sequential read a separate
thread is created for each file in parallel.
• Add additional physical RAM, checking paging.
• RAID level 10 is the fastest RAID level you can choose that supports redundancy.
• Add more physical drives to the current arrays. This helps to boost both read and write
access times. But don't add more drives to the array than your I/O controller can
support.
• Replace your current hard drives with faster drives. Review SCSI channel usage,
controller cache and the connection itself (i.e. fibre interconnect?)
• Add faster or additional I/O controllers. Consider adding more cache (of possible) to
your current controllers.

168
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

• Revisit SQL tuning and index utilisation. Revisit buffer cache hit ratios and memory
utilisation.
• Move transaction log to its own dedicated RAID-1 array.
• Move tempdb to RAID-1 or RAID-0 (no redundancy though).

Task Manager
This sounds obvious, but many people seem to draw a blank at times and race off to use profiler
and performance monitor when simply opening task manager can give you a good snapshot of the
state of the system and its running processes.

You cannot kill database threads, only the


entire sqlservr.exe process. Also see the
kill command at the NT level (may need to
source from resource disks).

Selecting different tabs will alter the options available under the View menu option. The key
tabs are:
a) performance
b) processes

Select the process tab, the select columns option as shown below provides a good set of
columns to include for real-time process monitoring and problem identification. Sorting the
columns over, say, CPU or memory usage is a great start.

COM+
It is worthwhile spending a little time investigating how to view COM+ activity. The Component
Services (also known as DTC or Distributed Transaction Coordinator) program installed with the OS
allows the user to install and subsequently manage COM+ packages, an example screen shot is
shown below:

169
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

To view runtime statistics, highlight “COM+ Applications” in the left-hand panel and click the
properties icon in the top menu-bar. Shown is the list of COM+ packages installed and their
running stat with associated PID. To drill down, open up the Windows Task Manager:

170
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

We can drill further into COM+ and go to a class level within the package. This allows is to monitor
the number of instantiated objects, wether they are activated and pooled, in-call and the call time
in milliseconds.

Component Services under XP is a little different that Windows 2k Server and Advanced Server. In
XP the class strings (as found in the registry) are shown. Also, utilise the details display on
components at a variety of levels to view other information in regard to the user which the objects
are instantiated, their activation context etc.

Going any further requires intimate knowledge of the application, but further profiler tracing may
assist you.

Isolation level of COM+ components

Be aware that COM+ components utilise a isolation level of serialisable (Q215520). As with all
transactions in SQL Server, keep them small and fast as this sort of isolation level can destroy your
performance. In .Net Server and Enterprise Services (COM+ v1.5), this can be configured to
serializable, repeatable read, read committed, read uncommitted, or any.

The developer should consider altering the isolation level on connection to the instance where
possible to read committed.

There is a great article by Alan Gordan regarding COM 1.x titled “Generation 1.X: A New Era for
COM+” that is worth a read for all SQL Server DBA’s. Take time to understand the issues with
COM+ and the new features for enhanced scalability and manageability.

171
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Proxying your COM+ components

On monitoring your COM+ components, you may find some are hitting the servers harder than
others. Depending on your scenario in terms of server availability and your overarching server
infrastructure, consider proxying off you COM (known as DCOM) to another server. Here is an
example scenario:

Server A Server C
(WebServer) (Active Directory
Server)

UserSecurityAccess.dll UserSecurityAccess.dll
(proxy – very small (using 30-40% cpu time was moved from
CPU footprint) webserver and called via a COM+ proxy, turning
the AD box into an application server as well as
servicing its standard LDAP requests).

Stored Procedures
The use of stored procedures is the most effective way to:

a) reduce network bandwidth between the business layer and the database server

b) manage security – it is not uncommon in SQL Server applications to only grant stored
procedure access rather than access to the underlying tables/views.

c) Ease of administration, tuning and maintenance – much easier for the DBA to review SQL
and for developers to debug SQL problems or alter code without recompiling.

d) Higher probability of plan reuse and caching

Using SET NOCOUNT

When you execute a stored procedure, a variety of information is sent back to the client indicating
the number of rows affected (and other information). Generally, it is rare that the client (or middle
tier COM’s) require this information, whose effect increases network traffic. This is especially
evident in large stored procedures with looping clauses and DML activity, sending a message for
each DML executed. Turning this feature off is always best practice unless there is a specific
application requirement for it to be left on.

To turn this off in T-SQL we use:

create procedure myprocedurename AS


SET NOCOUNT ON
<..various code here..>
GO

172
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The DBA can turn this off globally via (current logins not affected):

exec sp_configure ‘user options’, 512


reconfigure

Or via the instance startup flag 3640, eliminating the DONE_IN_PROC messages globally for all
connections.

Summary - Top Performance Problems


Here is a broad summary of what we discussed throughout this chapter in terms of common
performance problems:

ƒ Blocking, locked/waiting and long running transactions, incorrect use of COM+ transactions
or mix of OLTP and DSS based transactions, poor selection of isolation level.

ƒ Non-fixed database instance memory settings chewing all server memory, or very little
memory available for a very busy instance.

ƒ Auto close and Auto shrink database options are enabled

ƒ Missing indexes, poor understanding of application SQL and indexing requirement,


composite keys not being used due to leading columns not be part of the where clause(s),
poor selection of clustered index verses heaps, poor key selectivity.

ƒ Long time between index defragmentation or re-collection of statistics (histograms)

ƒ Auto-statistics turned off at the database or individual indexes

ƒ High recompilation and cache misses due to large numbers of adhoc queries or SQL using
hard-coded predicate parameters preventing reuse

ƒ Server shared with other applications resulting in a conflict of interest in terms of resource
usage.

ƒ Disk IO and IO distribution (affects associated RAID level, array cache and disk queue
lengths)

ƒ High page splitting due to a poor understanding of DML activity against user databases and
their clustered indexes.

ƒ Lack of server memory

ƒ Incorrect use of hints

ƒ SET NOCOUNT is not being used in your stored procedures, creating additional network
bandwidth between server and client (or middle tier).

173
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ Not utilising stored procedures for the data tier or returning XML directly from the DBMS
and wrappering XML tags manually thereafter.

174
7
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

High Availability

O
ne of the most important issues for many organisations revolves around disaster recovery
(DR), which goes hand-in-hand with the topic of high availability.

When we talk about high availability, we are primarily focused on seamless failover of our
servers hosting the applications they are running; and the technologies to support the continuation
of service with as little interruption to the business as possible. The solution you come up with will
be dictated by the realisation of its:

a) value-add to the business and customer expectations (latent and blatant)

b) cost of system downtime and manual cutover

c) issues of business continuity and system reliance

The problem you tend to have is that systems typically grow into this realisation rather than being
born with it. As such, the DBA and system architects must carefully consider the overarching
issues with application state, server configuration, OS and DBMS editions purchased, technologies
being used (clusterable?) and to some degree, “brail the future environment” in which the
application will live and breath.

Throughout this chapter, we will compare and contrast the high availability options to support your
DR plan and assist in realising the possible issues in advance.

175
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Clustering
Oracle RAC and Application Clustering
Trying to diagram the architecture is difficult, but the following provides a basic overview:

Node 1 (server 1) Node 2 (server 2)


MyDBInstance MyDBInstance

Buffer Cache Buffer Cache


Redo Log Buffer Redo Log Buffer

Variable part of SGA Variable part of SGA

Global Resource Global Resource


Directory Directory

Global Cache Global Cache


LCK LMSn LCK
Service Service
LMD
LGWR Global Enqueue Global Enqueue LGWR
Service LMON Service
DBWR DBWR

Interprocess
Communications (IPC)

Redo Log Redo Log


Files Files

SAN (storage area network)

The following key points (not definitive) should be noted about this architecture:

• Known as Oracle RAC (renamed and enhance version of Oracle OPS)


• Does not utilise the Microsoft Clustering Service
• The database instances in the cluster are called component instances.
• The Oracle Net listener provides load-balancing, connection-timeout failover, inter-
listener connection failover etc of client connections amongst cluster nodes, supporting
shared and non-shared connection models. Client network configuration settings can
be altered to specify multiple listeners and the failover path the client will take.

176
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

• Server vendors provide OSD (operating system dependent) cluster-ware to access the
underlying OS and for cluster communication regarding the database instance. The
OSD is made up of:
o Cluster manager (CM) – oversee inter-nodes communications
o Node monitor – polls status of cluster resources, include DB instances
o Interconnect – IPC controls messaging amongst the nodes
• Global Daemon Service (GSD) – runs on each node, this coordinates with the CM and
deals with client administrative tool requests. It is not an Oracle instance process.
• LMSn (Global Cache Service, GCS) – locate, prepare and transmit buffer cache blocks
to multiple instances. The same block may exist over multiple caches and can exist in
different modes (null, shared, exclusive). The GCS allocates roles and resource modes
to control concurrency and the instance will retain read-consistent block versions via
RBS entries.
• LMON (global enqueue service, GES) – monitor global enqueues and resources and
perform enqueue recovery.
• LMD (global enqueue service daemon) – manages incoming remote resource requests
• LCK (lock process) – manages non-cache fusion resource requests (library, row cache
requests)
• DIAG (diagnostic daemon) – diagnostics amount process failure and alert log
management.
• The GCS and GES maintain the Global Resource Directory to record resource
information. This is an in memory data structure that is distributed throughout the
cluster. Each instance has a part of the directory in the SGA.
• GCS and GES nominate one instance to manage all information about a particular
cluster resource, this instance is regarded as the resource master.
• Interprocess Communications (IPC) – asynchronous queued message model to route
messages and other comms traffic to coordinate other node resources. May be either
ethernet or fibre-interconnect.
• Multiple servers are working together against the same data files, offering great
scalability and performance.
• On NT servers, you still require the Quorum (voting) Disk, Oracle stores essential
cluster configuration information here. All administrative tools (Enterprise Manager
etc) must also be on a shared disk, typically the Quorum disk.

Taking this one step further in terms of a complete Enterprise solution, we have many alternatives
based on the environment we are running against. Oracle has made distinct strategic moves to
Java where possible, and in many cases, is the core development environment over PL/SQL and/or
Oracle Forms and Reports for medium to large scale development. As such, we have seen the
expansion of the Oracle Application Server and associated middle tier components (web servers,
caching servers etc) to encompass the Java suite of modules. Clustering in this environment is
complex and is out of scope of this e-book, even so, see references (54) and (55) as a starting
point.

177
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

There are many scenarios as you can imagine in the complete clustering solution in Oracle, but
here is an example:

Oracle9i Application Server Clusters Oracle RAC

Web Cache OHS/OC4J DB Node 1


Node 1 Node 1 SAN

Web Cache OHS/OC4J DB Node 2


Node 2 Node 2

Web Cache OHS/OC4J DB Node 3


Node 3 Node 3

The iAS Web Cache providers server-side caching for dynamic content over HTTP. This caching
takes into consideration cookies, http request headers, parameters and more. Result sets from
Java or PL/SQL procedures can also be cached and subsequently clustered.

The OC4J represents the possible J2EE cluster (Oracle Containers for J2EE). This includes the
clustering capabilities for Servlets, JSP and EJB’s. This also includes the Java Object Cache. The
OHS component represents the Oracle HTTP Server. This typically comprises of a webserver
(apache), Perl execution environment and PL/SQL and J2EE container routing.

In terms of Oracle and Microsoft Web Development, although not technically part of this chapter,
we typically see the following comparisons:

a) PSP, JSP Æ ASP, ASPX

b) PL/SQL Stored Procedures Æ T-SQL Stored Procedures

c) Servlets, Enterprise Java Beans Æ COM+ Components, Enterprise Services

d) Oracle RAC Æ MSCS and SQL Server Virtual Instances

e) OHS/OC4J Æ Microsoft Application Centre (COM+ clustering)

f) Web Cache / HTTP Web Server Æ IIS 5 or higher, Proxy Server

SQL Server Clustering


Clustering is a big topic that is an e-book all on its own. Within the section we will cover as
best we can a variety of key issues that DBA and systems administrator must consider when
utilising clustering as the ultimate high availability option in SQL Server 2k. The Oracle DBA
will firs of all recognise that, when compared to Oracle, SQL Server is a long way behind in

178
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

terms of incorporating high availability with a horizontally scalable performance gain (i.e.
many servers utilising the same database data files at once).

Before we begin, remember that SQL Server Clustering is designed to provide high availability, not a
load-balancing solution.

The Microsoft Windows and SQL Server cluster solution is a share nothing resource model, meaning
that one and only one database instance can run on any server in the cluster at any one time.
Therefore, if we had 4 nodes (servers) in the cluster, one and only one node can actually accept
connections and run against the database files for the instance. This adversely means that the
clustering solution does not provide horizontal scalability as Oracle does.

An example is shown below we have an Active/Active cluster which we will explain in more detail.

Connect by specifying virtual server (cluster enabled SQL-


Server with own IP or network-name) and the database
instance name

Node 1 Node 2

InstanceA InstanceA
(virtual failover (failover)
instance)

InstanceB InstanceB
(failover) failover (virtual Cluster Service
instance) (MSCS)
Heartbeat
(private network)
Interconnect

SAN or SCSI/Fibre
connected Disk Array

Cluster Quorum Drive (Q:), Raid 1

Transaction Log Files (M:), Raid 1

Data Files (N:), Raid 5

Transaction Log Files (M:), Raid 1

Data Files (N:), Raid 5

179
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

IMPORTANT – Remember that when we talk about an instance we don’t mean a specific
database. See the first chapter for more information if this confuses you.

The configuration of a cluster is not overly simple and I would highly recommend visiting
Microsoft’s website and reading up on their comprehensive technical manuals beforehand.
Here is a summary of the issues for installation and configuration:

a) 2 or more cluster nodes


a. node is simply a physical server running Windows 2000 Advanced Server or
Data Center Server. The operating system determines the number of nodes per
cluster supported, where Advanced Server supports two nodes and data centre
server supports 4 failover nodes.
i. Cluster IP – for all nodes in the cluster, external connections use this
ii. Cluster Server Name - WINS name of the cluster for all nodes
iii. Cluster Administrator Account - administer and own the MSCS, it is a
domain level administrator account for all nodes.
iv. Cluster Group(s) – collection of cluster-aware applications (i.e. SQL
Server virtual instances) or resources.

b. all of which run in the same windows domain (cross-domain clustering is not
supported)

c. Each node has a minimum of two network cards. The public and private
networks must appear (or appear to be in) in a non-routed LAN.
i. One for the private network that interconnects all nodes in the cluster
1. disable NetBIOS for the private network cards.
ii. One for the public network connection
1. nodes may be “remote”, i.e. over an VPN so long as the ping rate
is <= 500ms

b) Disk array
a. One or more disk controllers installed on each of the nodes
b. SCSI or Fibre interconnect
c. NAS is not supported by MSCS
d. SCSI not supported by Data Center server (fibre channel only)
e. Dynamic disks are not supported by MSCS
i. This means cluster downtime when adding more disks to the cluster
f. File compression not supported by MSCS
g. Software RAID not supported by MSCS
h. Use RAID 0+1 for ultimate performance, be fully aware of your node
configuration and number of instances you want to support as the number of
drives can grow very quickly.
i. Only one node can control a disk at any one time.
j. Remember the disk configuration is based on the SQL Server cluster model
chosen (active/active or active/passives). Be very careful with your decision
and the capacity of the disk array.

180
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

c) The comclust.exe binary must be run after MSCS has been installed, this is used to
create the clustered MS DTC resource. This should occur after one node is installed.

d) 1 or more virtual sql-server instances


a. a virtual server instance is similar to a standard instance but is cluster aware.
The MSS exposes a cluster IP for the entire cluster of nodes, within this we have
1 or more virtual servers which SQL Server installer calls virtual server instances
that clients connect too. Both SQL Server and MSCS work in unison to establish
user connections and node availability.

b. the binaries of the instance are stored on the nodes local disks

c. the MSCS cluster must be installed, resource groups allocated and NIC’s
configured before attempting the SQL Server instance install.

d. on installation
i. select virtual server instance
1. virtual server name – virtual server name, this is not technically
the name of the actual database instance. This is the virtual sql-
server name, its like a logical server name.
2. virtual server IP – enter public IP address in which the node is
available for clients to connect, there may be multiple IP’s if there
are many connecting IP networks. The subnet mask comes from
the MSCS.
3. cluster group disk for data files (assumes MSCS cluster group of
resource disks setup previously)
a. don’t use the quorum disk for data files
b. all default instance databases (system and sample
database) data and log files are installed on the drive you
select.
4. pick other nodes in the cluster in which you want to partake in the
failover of the virtual instance (by default all nodes are selected).
This is also called the cluster management screen of the installer.
5. enter login credentials for the remote nodes, this account must
have administrator access to the other nodes. It is not
uncommon to use the domain administrator account. This MSCD
service account must have login privileges to SQL Server to
perform isalive checks. If it’s the Administrator account this will
naturally occur with the BUILTIN\Administrators domain group
login installed with SQL Server.
6. enter the database instance name, use a named instance rather
than the default to ease maintenance.
7. select destination path for the sql-server instance binaries.
8. enter the domain user name in which the database instance will
run. Using a local domain user can be a problem to administer
and its highly recommended using the domain administrator
account or equivalent.
The DBA should keep the Administrator and the SQL Server
service account separate where possible. The DBA should

181
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

consider using the same service account for SQL Sever and
SQL*Agent services. It should be a valid domain account.
9. select SA account authentication mode
10. select licensing mode
ii. use the VIRTUAL_SERVER\Instance-name string to connect to a clustered
instance

I cannot stress that it is important to understand that the virtual SQL Server, which maps 1:1 to a
single database instance, can not share disks with any other node, this is completely different to
the Oracle clustering model.

The active/active model allows the DBA to utilise the Node2 server with another SQL Server
virtual server and associated database. Therefore, both servers are actually working for us
and failing over to one another on failure. In this particular model, for example, I can run
DatabaseInstanceA on Node1 as my OLTP database, and on Node2 run my DSS/Reporting
DatabaseInstanceB simultaneously. Of course, if either server fails I will have a DSS and a
OLTP database on the same box, competing for CPU and memory resources which we need to
consider when purchasing the hardware solution.

NOTE – Always set the specific memory maximum the SQL Server database instance can
use. Also note that active/active and active/passive are functions of SQL Server clustering and
not the clustering service itself.

The SQL Server 2000 DBMS is a cluster aware application, in that it utilises the underlying
MSCS API. As such, it uses the heartbeat NIC to communicate between nodes to detect node
and sql-server instance failure (it cant detect a single database failure in the instance and
result in a fail over). The SQL Server instance “ping” (is-alive check) is a select
@@servername query. On five failures the instance is declared dead and a failover occurs.
This involves starting the next named instance that’s part of the virtual sql-server.

NOTE – If you need to alter the service account logins for SQL Server, use Enterprise
Manager rather than editing the NT services directly.

Going back to disk configuration, the quorum disk is critical to MSCS. DON’T use your quorum disk
for database backups/restores. The MS DTC is usually configured on this resource (500Mb free
required). See Q294209 on Microsoft Support for more information relating to MS DTC.

As for each database instance, standard database file placement strategies kick in based on
the database being installed and its IO characteristics. In general, this tends to mean:
a) separate disk for tempdb (if deemed an issue)
b) separate disk for database transaction log files
c) separate disk for database data files
a. this may extend one step further if we use different file-groups, i.e. DATA and
INDEX groups which may be place again on their own sub-set of disks.

Always remember that we are talking about an instance, not a single database.

To finish this section off before we get too carried away, some final notes:
a) SQL*Mail is not clusterable as the MAPI protocol is not clusterable

182
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

b) SQL Server Analysis Services (OLAP, Data Mining) is not clusterable


c) select * from ::fn_virtualservernodes() to review nodes for the instance
d) full text indexing is cluster ready

Ongoing Cluster Administration

To administer the cluster:

a) Enterprise Manager and other associated SQL Server utilities


a. Especially for database and SQL*Agent service account and password
management
b. Remember to install on both nodes.
c. In SS2k, EM can be safely used for start/stopping instances rather than the
cluster manager.
b) SQL Server setup
a. To install/uninstall virtual servers, add/remove nodes, change or add IP
addresses to the failover cluster
b. See advanced options after installation to see administration functions
c) Widows Cluster Administrator
a. Don’t use it to add nodes to the SQL Server resource definitions
d) CLUSTER command line utility
a. As per the above GUI utility.
e) comclust.exe

NLBS (Web Farm Cluster)


The DBA should not be limited to the example above in terms of high availability or performance
gain. It is worth mentioning the NLBS (network load balanced service, was once known as WLBS),
which basically scales (or clusters) IP services such as TCP, along with UDP and GRE across 1 or
more servers and runs on all servers in parallel. The NLBS is provided with Windows 2k AS and
Data Centre Server and is also part of the Microsoft Application Centre product.

Essentially, NLBS assigns a single IP address amongst the servers in your server farm, the set-up
of which is done via the network properties screen of each server partaking in the farm and
selecting the network load balancing properties. This does require a good understanding of IP
networking and I highly recommend getting your network administrator involved early in the
planning stage.

It is very important to understand that “routing requests based on SSL session IDs or cookies,
aren’t possible. This takes NLBS out of the running completely if your Web site uses sessions”
(35). Even so, the DBA needs to consider the client affinity settings for preserving client state
and test accordingly. The affinity settings are:
1. none – many requests from a client can go to any node in the NLB cluster
2. single - many requests from a client return back to the same node
3. class c – multiple requests from the same TCPIP class-c address range will use the
same node in the NLB cluster.

The incoming requests are balanced in terms of the percentage of requests they receive and of
course overall server availability.

183
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

If you were wondering, NLBS is the clustering technology is used in web-farms.

NLBS NLBS installed on each


node in the cluster and
clients connect via a
single, static IP and
servers communicate
via a private network
(intra-cluster comms),
isalive check approx
every 1sec.

In this scenario, (see CLB later), we may be running our business layer (typically COM+
components) on each individual web-server in the NLB server cluster, communicating directly to
the database cluster. After talking to a few DBA’s regarding the use of NLBS at the database
server, they have, apparently, used these scenario(s) below to achieve fail over:

Connections from Web Server Farm

100% load

Database Server 1 Database Server 2

MyDB Transactional MyDB Network Load


Replication Balancing Service
or (NLBS)
Log
Shipping

The concept is:


a) NLBS all TCP/IP database connections to database server one
b) We transactionally replicate or log ship to database server two
c) The two servers are not running in a cluster, which is implicit from b)
d) On failure of server one, database server two is prepared for cutover of the NLBS.
e) Database server two may be used for reporting and other functions as need be whilst
server one is taking the load.

184
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

I am not convinced of this option and it will require a fair amount of thought before running
with the architecture.

CLB (Component Clustering)


Taking the clustering model another step further, we have COM+ clustering, or component
load balancing. This feature is only available with Microsoft Application Centre, which is
licensed separately per node (you may be surprised at the cost of your cluster implementation
at the end of the day!). The CLB service is installed on all servers in the existing web server
NLB cluster, we also form a new “application server” (business layer) cluster managed by the
same CLB. The web-server CLB maintains a COM+ routing list per node in the NLB cluster;
the list contains all nodes in the application server cluster. The routing list servers are polled
every 800ms (approx), logs the response time of each server, ranks them and CLB distributes
the COM instantiations in a round robin fashion amongst the nodes. We proxy (DCOM) the
COM+ components to the web servers which have the IP of the applications server cluster.
The CLB of course manages node failure within the application server.

Web Server Farm (NLBS)

COM+ COM+ COM+ COM+


Proxy Proxy Proxy Proxy

Routing Cluster (CLB)

Application Centre Cluster (CLB)

COM+ COM+ COM+ COM+

Some keynotes regarding this architecture:

This model can be taken another step further with a separate COM+ routing cluster, this is not
discussed and is not recommend for web-based applications. Microsoft has some excellent
documentation related to NLB and CLB clusters, which can be found in the references.

Microsoft Clustering - The Big Picture

185
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

We have concentrated primarily on SQL Server, but to bring clustering in context with a complete
highly available and scalable solution we have also discussed (albeit briefly) CLBS and NLBS. The
following diagrams show a complete solution utilising Microsoft technology that the SQL Server DBA
should be familiar with.

Web Server Farm (NLBS)

COM+ COM+ COM+ COM+


Proxy Proxy Proxy Proxy

Routing Cluster (CLBS)

Application Centre Cluster (CLBS)

COM+ COM+ COM+ COM+

Database Server (MSCS)

SAN or SCSI/Fibre
connected Disk Array

186
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Federated Databases
I personally do not regard database federation as a form of high availability, but it is pushed by
Microsoft as a key technology to enhance performance. The architecture for federation can vary
significantly between installations. An example is shown below.

Client

Web Server 1 Web Server 2

IIS IIS Load Balancing Service (NLBS)

COM+ COM+

Database Server 1 Database Server 2

MyDB MyDB

DPV DPV

Linked Distributed partitioned


A-K Server L-Z
view(s).
Data Data

Database Servers with their Member Databases forming the


federation can be clustered to increase high availability.
Database instance names must be carefully considered.

Table data is horizontally partitioned amongst the member databases which reside on two or more
physical database servers. Linked servers (database links) are created between each database
server instance and distributed partitioned views (DPV) are created on each member database, for
example:

187
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

-- Database Server 1 (dbserver2 is the name of the linked server)


CREATE VIEW dbo.salesdata AS
SELECT * FROM mydb.dbo.customersales
UNION ALL
SELECT * FROM dbserver2.mydb.dbo.customersales

-- Database Server 2 (dbserver1 is the name of the linked server)


CREATE VIEW dbo.salesdata AS
SELECT * FROM mydb.dbo.customersales
UNION ALL
SELECT * FROM dbserver1.mydb.dbo.customersales

With such simple views, they are naturally updateable and support all forms of DML. There are
ranges of conditions imposed on the view and the underlying table that are described in the books
online within SQL Server.

At the table level with each member database we apply check constraint conditions to ensure the
partitioning occurs correctly in terms of data integrity.

The key to the entire architecture is the business object layer, namely the COM+ routines.
The business layer must be “federated aware”. This can be done in a variety of ways:

a) Stored Procedures – if the COM+ routines utilise stored procedures for all DML, the
procedures can encapsulate the necessary logic to distribute data over member
databases.

b) COM+ routing – call a custom built routing component that has the necessary smarts to
communicate to the appropriate member database.

The trick here is the connection string used by the COM+ routines.

It can be very difficult to move an existing application to a federated model but it is not impossible.
If the application has been architected well (yes – that would be another ebook), and data access is
typically via stored procedures, then utilising distributed partitioned views within the procedures
should be completely seamless to the application.

188
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Log Shipping
Conceptually, log shipping in SQL Server and Oracle are the same. The process in SQL Server
works at a database level, not at a global instance level as you will see later. The aim here is the
create a warm standby server in which one or more databases are permanently in recovery mode.
The source database ships transaction log backup files to the destination server and we restore
(with no recovery option) the logs sequentially (in order). If there is a failure on the source server
we attempt to recover the last of the transaction logs, ship it to the destination server and complete
the database recovery. Once done, we send client connects to the new server and they continue to
work with little or no data loss.

Windows Domain

Server A Server B
(primary) (standby)

DatabaseA DatabaseA
Client
Connections

Backup Restore
Transaction Log with
Log to network norecovery on
share destination
server

NOTE - we have not diagrammed the full database backups that must also be log-shipped to
start the process.

The DBA can use a custom written script or the SQL Server Wizard to do the shipping. The
shipping in most cases will be to a server on the same Windows 2k network domain, but there is no
reason why VPN tunnels over large distances or other remote scenarios are not utilised.

189
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The supplied wizard provides all necessary steps to setup log shipping for selected databases.
Before doing so remember the following:

ƒ document the process before running the wizard

ƒ how will the client application components detect the failover?

ƒ Databases must be in full or bulk-logged recovery mode

ƒ ensure instance names are the same on source and destination servers

ƒ pre-determine the log backup schedule for the source database

ƒ pre-setup the transaction log backup directory via a network UNC path (referred to by both
source and destination DTS jobs)

ƒ create DTS packages on both servers and use the transfer logins job to facilitate the
transferring of login information between shipped servers.

ƒ Must run the wizard via a login that has sysadmin system privileges

Once the log shipping DTS (maintenance plan) has been created, go to the Management Folder in
EM and select properties of the log-shipping job to alter the process in place.

See reference (56) for a documented “How-To” for log shipping in a SQL Server 2k environment
using the Wizard.

190
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Manual Log Shipping - Basic Example


Here we will discuss a working example that was coded using two stored procedures, a linked
server, two DTS packages and (optionally) pre-defined backup devices.

This example revolves around a single server with two named instances:

Primary Database Instance - SECA\MY2NDINSTANCE


Standby Database Instance - SECA\MY3RDINSTANCE

i. Setup disk locations from primary to destination server and test with SQL Server service
account.

Backups on primary server are dumped to \primary and


are then “shipped” via a simple xcopy to the \standby
directory from which they are restored.

ii. Pre-determine what account will be used for doing the backups, establishing the linked
server and restoring backups on the primary and standby databases. I recommend that
you create a new account with sysadmin rights on both servers to facilitate this.

iii. Setup Linked Server on primary server to destination server

We will link from the primary server


over to the standby server via the
account specified in step 2. Data
source is the server/instance name we
are connecting too.

191
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

In this case we are using the SA


account which is not best practice, but
will suffice for this example.

Apart from the SA account mapping


above, no other mapping will be valid.

Ensure remote procedure call options are


set to facilitate the calling of t-sql stored
procedures on the standby server from the
primary server.

* If you are using EM, and have registered the server under an account no mapped in the linked server, then
the linked server will no work for you. Check your EM registration before attempting to view tables/view under
the linked server within EM.

iv. Setup database backup devices on primary server

This is completely optional and really depends on the backup model you are using. SQL
Server allows you to pre-create backup devices, once created, we can use the logical
name for the backup device (which maps to a physical file) rather than the using the
physical path and filename for the backup. This makes scripting much nicer and easier to
read/change.

Here we create two devices, one for full backups and the other for logs. See
management folder in EM and the backup item to create these.

v. Check primary server database recovery model. Select properties of the database via
EM. Ensure the model is in line with the backups you will be log-shipping.

192
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

vi. Write two stored procedures that will reside in the master database on the standby
server for recovery of the FULL and LOG backups. The standby restore option is what
tells SQL Server that the database is in warm standby mode.

CREATE PROCEDURE dbo.StandbyServer_restore_full_database_backup AS SET NOCOUNT ON

RESTORE DATABASE logshiptest


FROM DISK = 'e:\backups\standby\logship_primaryserver_full_backup.BAK'
WITH
RESTRICTED_USER, -- leave db in DBO only use
REPLACE, -- ensure overwite of existing
STANDBY = 'e:\backups\standby\undo_logshiptest.ldf', -- holds uncommitted trans
MOVE 'logshiptest_data' TO 'e:\standbydb.mdf',
MOVE 'logshiptest_log' TO 'e:\standbydb.ldf'
GO

CREATE PROCEDURE dbo.StandbyServer_restore_log_database_backup AS SET NOCOUNT ON

RESTORE LOG logshiptest


FROM DISK = 'e:\backups\standby\logship_primaryserver_log_backup.BAK'
WITH
RESTRICTED_USER,
STANDBY = 'e:\backups\standby\undo_logshiptest.ldf' -- holds uncommitted trans
GO

vii. Write two DTS packages on the primary server, one to do a full backup and the other a
log backups.

Package 1 – Primary Server, Full Database Backup

BACKUP LOG logshiptest exec


WITH TRUNCATE_ONLY standbyserver.master.dbo.StandbyServer_restore_full_database_backup

WAITFOR DELAY '00:00:05'

BACKUP DATABASE logshiptest TO


logship_primaryserver_full_backup
WITH INIT

WAITFOR DELAY '00:00:05'

193
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Package 2 – Primary Server, Log Database Backup

BACKUP LOG logshiptest TO exec


logship_primaryserver_log_backup standbyserver.master.dbo.StandbyServer_restore_log_database_backup
WITH INIT, NO_TRUNCATE

WAITFOR DELAY '00:00:05'

viii. Test Full then Log DTS routines and debug as required

ix. Schedule DTS packages

x. Monitor

xi. On failure of the primary, do the following

-- Login to primary server (depends on failure), and attempt to backup last database log file

BACKUP LOG logshiptest TO logship_primaryserver_log_backup WITH INIT, NO_TRUNCATE

-- Login into standby server

restore database logshiptest with recovery

Deleting database file 'e:\backups\standby\undo_logshiptest.ldf'.


RESTORE DATABASE successfully processed 0 pages in 4.498 seconds (0.000 MB/sec).

-- Ensure client connections are connection to the now live “standby” server.

194
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Some thoughts about this setup:

a) The full and log backups are being appended to the same file, consider writing better
backup routine on the primary server than produces separate files for each backup with
a date/time stamp. Do this is a T-SQL stored procedure on the primary database and
consider replacing the DTS copy command with a call to xp_cmdshell within the stored
procedure.

b) If using a), parameterise the two recovery procedures on the standby server to accept
the file path/filename of the file to be recovered. The routine in a) will have all this
information and can pass it to the standby server without any problems.

c) Consider email on failure DTS tasks.

d) Consider how you will remove backups N days old?

e) Will the standby ever become the primary and effectively swap serve roles?

Online Object Redefinition


In Oracle 9i, we see the release of the oracle redefinition PL/SQL package
(DBMS_REDEFINITITION). The process basically allows the DBA to stage schema alterations,
for the DBMS to track the changes and to cut them over to the “new” database structure with
a simple command and very little downtime to the end-user (if any). This is a very powerful
option that is covered in good detail in the article “Don't Shut Down That Database! Use Oracle
9i Online Object Redefinition Instead” (34).

There is no equivalent option in SQL Server.

195
8
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Globalisation Services (NLS)

W
ith the advent of Oracle 9i, the NLS (national language support) services has been
extended significantly and has been rebadged as Oracle Globalisation Support.
Previous NLS implementations could only support one national language and
character set per database, the architecture can now support many locales
(languages, character sets, sort orders etc) loaded at runtime. This effectively means that
single database instance implemented correctly can support error messages, sort orders,
date/time, monetary, numeric and calendar conventions of any native language and locale,
creating a truly “global” database.

This chapter provides a quick overview of Globalisation Support with Oracle and expands this
to encompass the equivalent SQL Server options.

NOTE – Oracle refers to locale as the “national language and the region in which the
language is spoken” (11). This consists of language (national language of the user) and territory
(region in which the language is spoken). We do not cover timezone specifics in Oracle.

196
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Oracle Architecture

A simplified overview of the Oracle 9i globalisation support architecture is shown below:

Loaded locale-specific data (eg. French, German etc)

Create database
statement we define..
character set – used to Multilingual Oracle Database
store data (OS (Unicode all or select columns)* Locale specific server behaviour
NLS Are via DB init parameters (NLS_)
dependent default
value or defined),
national character set NLS Runtime
(to manage nchar, Library (NLSRTL) Client environment variables (NLS_)
nclob, nvarchar2 etc)

Alter session parameters..

ORA_NLS33 env variable,


lxlboot.nlb server boot file and SQL statement parameters..
custom edited *.nlb and *.nlt
language definition files. This
allows the DBA to control Locale
language, territory, character Builder
set (how characters are (GUI)
mapping to their binary values) Locale specific controlled behaviour at
and linguistic sort options the client as shown above. Client
(collations) available to the applications can utilise API’s to
oracle database on start-up manipulate NLS parameters.
(boot) of the instance.

* Unicode is required for ”true” globalisation and rendering of a content to many languages rather than a select few.

The NLS_LANG parameter allows the DBA and client to specify:


a) Language – for messages, sort order, day and month names
b) Territory – default date, monetary and numeric formats
c) Character set – the languages character set to be used (eg. US7ASCII)

The DBA can check NLS parameters via the following dictionary objects:
NLS_SESSION_PARAMETER
NLS_INSTANCE_PARAMETER
NLS_DATABASE_PARAMETER
V$NLS_VALID_VALUES
SYS.PROPS$

In order for an Oracle database to be “global” (multi-lingual applications rendering content in the
countries native language), the database is created to encode stored data as Unicode (unique
character for any character regardless of platform/OS/language etc). The Oracle database is
encoded with a Unicode v3.1 UTF-8 compatible character set such as on its creation:

197
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

• UTF8 (Unicode v3.0)


• ALU16UTF16, AL32UTF8 (Unicode v3.1)
• UTFE (EBCDIC formats)

If the DBA does not want to encode the entire database with the Unicode character set (for
whatever reason), the table column data type NCHAR (or NVARCHAR2) can be used to store
exclusively Unicode characters. As shown in the architecture diagram, the client and server
can alter NLS_ parameters accordingly to utilise different cultural settings shared over a single
database and rendered appropriately.

NOTE – NCHAR is stored as UTF-16.

To manage sort (collation) options, Oracle caters for:

Binary – sort sequence based on numeric value of characters defined by the encoding
scheme.

Linguistic – each character has a numeric value representing the characters position in
proper linguistic order, the kinds of include:
monolingual (eg. generic_m, thai_m, japanese_m)
multilingual (eg. Arabic, latin, ASCII7)

Multi-lingual indexes can be created to speed linguistic sort performance.

SQL Server Architecture


The SQL Server architecture, in some respects, encapsulates many of the features of Oracle but
with significantly less control over the internals of collation(s) and associated parameter settings at
the client and database level. This is the model SQL Server has opted for in many areas within the
DBMS and is evident here with SQL Server 2000’s version of Globalisation Support.

NOTE - There are significant differences between earlier versions of SQL Server Collation and
Sort Order. This chapter will not cover them but the DBA should be fully aware that it might
not be a straightforward task moving to SS2k.

First of all, SQL Server uses the term Collation rather than the “Globalisation Support” or
“National Language Support” (NLS). Even so, the related concepts are similar in meaning to
that of Oracle’s in most respects as all are based on ISO standards.

Collation is the rules governing the proper use of characters for a language or character set. This
includes the following three properties

• Sort Order for Unicode Data Types


• Sort Order for Non-Unicode Data Types
• Code Page used to store Non-Unicode Data
o Uni-code data has a fixed storage structure for string data
o Code page is sort order independent

198
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The sort order under SS2k is identical for both uni-code and non-unicode string data, the DBA can
not specify different sort orders (unlike previous SQL Server versions) for such string data. The
sort order defines rules for the interpretation, comparison and presentation of string data, this
includes case, accent, kana sensitivity or simple binary order.

NOTE – Unicode can be encoded as UCS-2, UTF-8 or UTF-16 (and others). UCS-2 is used by
NT v4.0 , SQL Server v7 and 2000, UTF-16 is used by Windows 2k. SQL Server 2k uses the
Unicode 2.0 standard.

The collation (language) of SQL Server exists at a numbers of levels:

a) On installation of the SQL Server Instance (named or default)


a. This sets the collation of the master, msdb, model and tempdb system
databases
b) On creation of a User (non-system) Database
a. If not specified, uses the collation of the model system database. Use the alter
database command to alter the tempdb collation for subsequent user database
creations if need be.
c) At a column level within a table object
a. For string data types columns only (not using Unicode data types of course)
d) Within expressions

Altering the collation of a database does not automatically rebuild existing string data to the new
collation (and possibly code-page), therefore, the DBA must BCP (or use DTS for import/export) out
the data and reimport to take up the new collation (remember - the DBA may need to alter the
collation for all table string columns individually).

Before we drill too deeply into SQL Server Collation, let us diagram the architecture. The
architecture is closely associated with the underlying operating system (known as Windows Locale)
as shown below:

199
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Server / PC

Windows Operating System

SQL Server language and its


Windows Locale (regional settings) code-page associated with
an equivalent Windows
Collation (locale)

SQL Server Database Instance


(Collation and Sort Order – used by all system DB’s)

master model msdb tempdb TEMPDB collation used for


temp tables/sorts etc unless
specified by programmers.

User DB (collation)
MODEL DB collation used if
not specified for user
TABLE databases on creation.
String-Column (collation)

SS2k
Server Defines the interpretation of
Network character data, keyboard
Utility locale, date/time, numeric,
(listener) currency etc..
Data access method defines
the rules for text
manipulation. SQLOLEDB
for example data is
converted to Unicode using Client
Internationally
the collation of the actual WINDOWS
aware app
data. LOCALE

Some of the many key issues related to this diagram include:

• Collation & sort order on installation of the instance affects all system databases. The
model database collation is used for all users databases that don’t explicitly use a
collation on its creation, this can be altered if need be.
• Temporary objects created in TEMPDB will use this system databases collation. The
database is re-created on start-up from the model database, therefore, to alter simply
change the collation on the model database and re-start the SQL Server instance.
• The DBA cannot alter sort order after the installation of the SQL Server instance.
• SQL Server can support only code pages that are supported by the underlying
operating system.
• Multiple collations can use the same code page for non-Unicode data

200
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

• Code page is a character encoding system used when storing string data (char,
varchar, text) for different alphabets (non-unicode), it defines the bit-pattern for each
character.
• Client uses the code pages associated with the OS locale to interpret the character bit
stream from the database. An international aware application may include further
resource files to provide a truly international application without recoding.
• International system should utilise Unicode data to ensure all computers perform the
correct translation when interfacing to the OS code page.

A SQL Server collation is associated with one and only one code-page (which defines string data’s
physical storage), for each code page, one or more Windows Locates (identified by the LCID or
locale ID) are associated with it, and therefore, supports the code page translation. For example:

SS2k Collation SS2k Code Page Windows Locale


Latin1_General Æ 1252 Æ Afrikaans
Basque
Dutch(Standard)
Italian
<..etc..>
Code Page
SQL Server (non-unicode) Windows
Collation or Collation
Raw storage (locale)
(Unicode)

IMPORTANT - SQL Server can support only code pages that are supported by the
underlying operating system. SQL Server will give an error if there are compatibility issues.

The “Collation Name” is specified via a unique string, this is representative (to some degree)
to language and the sort-order and sometimes the code page for the language that forms the
colation, for example:

CP[code-page] Code Page


BIN Binary
CI Case Insensitive
CS Case Sensitive
AI Accent Insensitive
AS Accent Sensitive
WS Width Sensitive (blank for insensitive, Unicode, full&half)
KA Kana Sensitive (blank for insensitive)

Just to be totally confusing, don’t rely on these coding to accurately reflect the actual collation. To
get a list of valid collations:

SELECT *
FROM ::fn_helpcollations()

201
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

NB - fn_helpcollations() is a function in the master database.


The :: must be used for the function to be included in the FROM
clause of a SQL statement.

Example:

SQL_Scandinavian_CP850_CS_AS
Finnish-Swedish,
case-sensitive,
accent-sensitive,
kanatype-insensitive,
width-insensitive for Unicode Data,
SQL Server Sort Order 59 on Code Page 850 for non-Unicode Data

When we say “SQL Server Collation”, we mean all collations valid within SQL Server. Note that SQL
Server does present us with two key language designators, they being SQL and Windows, where
the SQL designators are provided for backward compatibility to previous SQL Server versions.
Some example SQL-specific code pages (also known as sort order) are:

SQL_Latin1_GeneralCP850

SQL_Ukrainian_SP1251

SQL_Polish_CP1250

All unicode strings utilise the SQL-92 standard N'' literal prefix, for example:

DECLARE @mystring NVARCHAR(50)

set @mystring = N'mystring'

All system table string data uses unicode data types.

Collation – Installation (Server Level)


In many cases the DBA will utilise the default collation during the installation of the instance.
In my particular case its Latin1_General_CI_AS. Always use the windows collations listed,
rather than the backward compatible _SQL collations. The installation screen is simple and
requires not further explanation.

To retrieve the server (instance) collation:

select convert(char, SERVERPROPERTY('collation'))

The instance collation will affect the language for all system databases, including the model
database. As new user databases are created they will, by default, get the model databases
collation. To alter the instance collation you need to use rebuildm.exe on the installation CD.
This is not a simplistic task, read the books online carefully and review the chapter on backup
and recovery.

202
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Collation – Database
Specifying the collation when creating a new database in EM is very simply and will not be
covered. To specify the collation at a SQL statement level:

CREATE DATABASE [mydb]


ON PRIMARY
(NAME = N'mydb_Data',
FILENAME = N'C:\mydb\data\mydb_Data.MDF' ,
SIZE = 1,
FILEGROWTH = 10%)
LOG ON
(NAME = N'mydb_Log',
FILENAME = N'C:\mydb\log\bb_Log.LDF' ,
SIZE = 1,
FILEGROWTH = 10%)
COLLATE Albanian_BIN

The default database collation is sourced from the model database. All table columns (string
data only of course) will take on by default the databases collation setting.

You can alter the database collation via:

ALTER DATABASE mydb COLLATE Latin1_General_CI_AS

This will not magically alter and port all subsequent column collation data to the new database
value.

Do not rely on selecting properties of the database via EM and get the databases collation.
Typically, the collation is shown under the maintenance section of the property dialog. In the
example below it is blank where we have used veitnamise over the Windows default for our
installation, that being latin general (latin1_general_ci_as).

The routine:
select DATABASEPROPERTYEX( 'mydb , 'Collation' ) -- returns NULL

This may be a bug under XP? Use the following command instead:
exec sp_helpdb

Some important notes:


a) all users must be disconnected before attempting the alteration
Server: Msg 5072, Level 16, State 1, Line 1
ALTER DATABASE failed. The default collation of database 'pubs' cannot be set to Vietnamese_CI_AS_KS.

b) no schema bound object can be dependent on the instance collation

203
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ materialised views

ƒ check constraints

ƒ computed columns

ƒ table level functions

-- Materisised view, created with the option WITH SCHEMABINDING


Server: Msg 5075, Level 16, State 1, Line 1
The object 'myview' is dependent on database collation.

-- Check constraint
Server: Msg 5075, Level 16, State 1, Line 1
The object 'CK_emp_id' is dependent on database collation.

Collation – Table Column


Column collation can be specified for all character data types. In most cases, consider using
Enterprise Manager when editing or creating table to see how the collation is specified and the SQL
syntax used. When scripting tables from Enterprise manager the default collation (which comes
from the databases collation setting) is also specified.

The collation value for the column within EM is shown as a property of the column. The following
dialog is shown when altering the column. Remember that the databases collation is used by
default.

The databases collation is used by


default and affects the dialog value
shown. “Windows Collation” and SQL
Server designators are the options for
the DBA.

The DBA can alter the collation via SQL as the examples show below:

CREATE TABLE dbo.mytable


(
mycol char(10) COLLATE Vietnamese_CI_AS_KS NULL

204
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

) ON [PRIMARY]
GO

ALTER TABLE mytable ALTER COLUMN


mycol char(10) COLLATE Latin1_General_CI_AS
GO

Multi-lingual columns are not supported. The database collation is used if the column collation
is not specified.

Collation – Expressions and Variables


Variables, stored procedure parameters and string literals can also utilise the COLLATE option as
shown in the examples below.

DECLARE @mystring varchar(100) COLLATE SQL_Latin1_General_Cp1_CI_AS

SELECT 'hello world ' COLLATE Vietnamese_CI_AS_KS

CREATE PROCEDURE MyProc @myvar varchar(10) COLLATE SQL_Latin1_General_Cp1_CS_AS


AS
<..etc..>

select * from authors order by au_lname COLLATE Czech_CI_AI

select * from authors


where au_lname = au_fname COLLATE Czech_CI_AI

205
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Internationally Aware Applications


This is a DBA book, not an application development one, so we will not spend too long discussing
the numerous issues to do with building international applications. Some of the many items to be
considered include:

a) Language
a. Printing documentation
b. Grammar
c. String data in UI (menu’s, dialogs, other GUI controls)

b) Locale Specifics
a. Date/time format
b. Numeric
c. Currency
d. Sort order / string comparison

The application architecture needs to divide UI (user interface) away from the application
components (code block or business logic) in order to produce a localised product that is
internationally aware.

International Enabled Application

User Interface Application Localised


Component Component Product
(UI) (Code Block) Installation

The resource file (*.res, *.rc or *.resx) is the key for the UI, a separate resource file exists for all
supported languages and assists in localising the installation for the client in terms on string data
interpretation, bitmaps, icons and its link to the clients OS locale.

Any further discussion on this topic is out of scope , suffice to say that initial design is everything
and some first hand experience is required on the team to ensure a successful design an
subsequent implementation.

206
9
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

OLAP

F
rom SQL Server v7, Microsoft bundled OLAP Services with its DBMS and was their first
(and reasonably good) attempt at a move into the OLAP market space. In SQL Server
2000 the product has been renamed to Analysis Services and provides a range of
enhancements that no-doubt pleased the OLAP gurus amongst us. In this chapter we
will cover some of the basics to get the DBA up to speed with its administration. I say basics,
as I am far from being an expert in this field, which I truly believe is a distinct skill in its own
right, therefore, I do very little comparison to Oracle and only skim the surface of the Microsoft
products capabilities. Do not let this put you off though as we cover a range of great tips and
tricks.

Terminology
It is assumed that the reader has some previous Oracle experience with OLAP. To be honest, I
have had little involvement with OLAP technologies under Oracle so will rely on you to draw the
necessary comparisons between the two companies implementations.

Terminology Summary
OLAP Online Analytical Processing
Microsoft have separated its OLAP technology away from the DBMS and
wrappered it into what they call Analysis Services (or OLAP Services in
v7 of the DBMS). The product includes
Star Schema Microsoft utilises a star schema for their cubes. A cube in such a
schema is based on a single fact table (or view) and 1 or more reference
data (dimension) tables connected to it.
Virtual Cube Is a view or 1 or more cubes. Basically we can build a variety of
physical cubes, and from there, create virtual cubes were we their fact
table and associated shared dimensions can work together for form a
single virtual cube. To the end-user there is no difference to standard
cubes.
Dimension Organised hierarchy of categories or levels that links to data within the
fact table of the cube. The dimension hierarchy (i.e. tree) is divided into
levels and each data element of the dimension is called a member.
Analysis services support regular, unbalanced and ragged dimension
hierarchies.
MDX Multiple dimension expression.
Calculated member Calculated field within a cube that is not physically part (calculated at
runtime) of the underlying tables/views feeding the cube. They are
written via MDX statements.

207
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Cell level security A cell is the smallest element of a cube, typically being the unique
element in which all dimensions (where applicable) intersect.

Administration
Installation
The installation options are very basic, we are simply asked:
a) what options we would like to install
a. note that Analysis Manager requires decision support objects (dso) and client
components.
b) where our OLAP data directory (cubes and their meta-data bases) are to be stored
(single directory location).

and installation continues.

On completion, analysis services are installed with the SQL Server group as shown below. The
MDX (multi-dimensional expression) example VB application is a good place to trial MDX queries
used in OLAP, which you will soon find out are very different from standard SQL.

Always reboot after the installation, you may get some strange errors and it’s not worth the trouble
dealing with them.

The directory structure is as follows, the OLAP repository is, by default, a series of Microsoft
Access databases the core files being msmdrep.mdb and msmdqlog.mdb. The DBA should
ensure that these files and associated cube directories are regularly backed up.

A share is automatically created called


MsOLAPRepository$ and is explained in
more detail later. Core repository
database files are stored here.

In order to administer the OLAP repository and its cubes, you must be part of the olap
administrators NT group that is installed with Analysis Services. Of course, if the server is not

208
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

part of your typical login domain then you need to create a trust and ask the server
administrators to add your login to this group. Once this is done you can connect and
administer the cubes from your PC.

NOTE - Analysis Services does not have the same concept of multiple named instances,
therefore, multiple analysis servers running on the same box. Within a single analysis server
(single service) we run one or more OLAP databases.

The following Access databases are used to manage analysis services:

Database Name Purpose


msmdrep.mdb Analysis Services repository to store meta data of the servers
objects. Can be migrated to SQL Server.
msmdqlog.mdb Analysis Services query log. Also used during cube processing.
Cannot be migrated to SQL Server. The documentation states
that this log is only used when querying cubes, even so, I have
received errors when processing cubes are not having read/write
access to this database when managing the OLAP server remotely.

NOTE - Reinstalling analysis services will not destroy or reconfigure your repository although
you must re-process all cubes in the repository. You may loose your sample OLAP database
(foodmart) on re-installation.

To allow Analysis Services to use over 3Gb (assuming the typical /3GB and other settings have
been set in the boot.ini), edit the HighMemoryLimit registry string under KEY Local
Machine\Software\Microsoft\Olap Server\Current Version and specify its decimal value
accordingly. Once done, from within the Analysis Services GUI, select properties for the server
and you can alter the minimum allocated memory settings.

Look through the properties of the server carefully. From here, you can administer the OLAP logs,
active directory registration, cube processing configuration and other general properties.

WARNING – Interestingly enough, I completely removed Analysis Services, rebooted and


re-installed. Before the removal the repository was migrated to one of my SQL Server
instances. On reinstallation the repository was retained and naturally continued re-using the
SQL Server instance. This may be a problem for you. Always re-check the registry after an
uninstall and clear as required. The root is \Hkey_local_machine\ software\Microsoft\olap
server.

209
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Administering from your client PC


After you have installed analysis service on the server, the DBA will typically install the developer
edition on their desktop and administer the cubes remotely rather that at the server. If you are not
too particular, use all the default installation settings and apply the appropriate service packs to
bring the client up with the server you will remotely administer. Once done, we need to make
some server changes to allow the client to connect and process cubes and dimensions.

The first problem you may be presented with is this:

The first key change is adding your windows networking domain login name to the olap
administrator domain group on the server in which we installed analysis services. The network
administrator may need to create a 1-way read-only trust to your server if its not a member server
of the domain you are logging into and/or is running in a different windows domain.

Edit the group, select members tab and


add your domain login name to this NT
group. The Administrator is naturally part
of this group. In the example below we
have added two domain users from a
different domain (via trust) and the
SQLServer user in which SQL Server runs.

Once done, we need to repeat a similar operation with the MsOLAPRepository$ share that is
automatically created on the bin directory holding the Analysis Services binaries. This is very
important as you will get a variety of errors when attempting to edit and process cube data
structures. By default though, the OLAP Administrators group has permissions to the share so
changes directly to the share are rare.

NOTE – Clients using MDX via OLE-DB (includes Excel Pivot control, Office 2k web
components, ADOMD, etc) do not require access to the MSOLAPRepository$ share.

210
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The registry entries for OLAP include the remote access properties to manage your cubes, such
as:

There is apparently a bug (Microsoft support doc# Q293782) regarding the administration of
the cubes. Even with access to the OLAP Administrators group and the share, you may still
have problems and will require Administrator group access. I have not come across this
particular problem. Remember that cross domain access will require a trust between the
domains.

Migrating the repository


If you are like me, the thought of using Microsoft Access databases for anything ‘business critical’ is
like skydiving without a parachute. The migration process is very basic, simply right click the
registered analysis server you wish to migrate, select migrate repository and following the prompts.
It assumes that you already have a SQL Server database created. When asked, select the
appropriate database authentication scheme (if installing under the NT account SQL Server is
running in then uses this.

211
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

In the GUI dialog shown, it tends to “highly recommend” a straight migration to a SQL Server
database rather than utilising SQL Server’s meta-data services. The two types of migration are
essentially the same in terms of database objects that are created, they being the tables server
and olapobjects. The meta-data repository install option defaults to the MSDB database, which of
course you can change.

Personally, I am quite impressed with the SQL Server meta-data repository as it adds another
reporting element to the repository. The model utilises the XML nature of the olapobjects table.
Within EM we see something like the following (right click virtually anywhere in the tree and select
browse options to get a custom view of the many properties):

212
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

If, after migrating you have connection problems to the database and have altered SQL Server
login privileges accordingly, then go to the registry (regedit.exe) to fix the connectivity properties:

If, after you migrate the repository you can no longer administer the cubes from your PC, even
though you are part of the OLAP administrators NT group; then create a SQL Server login for each
user (or create a NT group at map the SQL Server login to it instead; whatever is easier) using
Windows Authentication, and allocate the database privilege db_owner to the user in the
OLAPRepository database you created. I believe db_writer and db_reader are also suitable if you
are not keen on allocating db_owner.

NOTE – Once you migrate away from the Access databases, there is no going back unless
you re-install.

Storage Models and Connectivity


From a DBA perspective, the actual involvement will vary from simple administrative tasks in a
production environment (i.e. set-up, backup/recovery, processing cubes and dimensions and their
associated schedules etc) to full blown development via the Analysis Services Manager and possible
Visual Basic or C++ utilising DSO and ADOMD. We will provide a simple walkthrough in this section
and no more.

OLAP Databases

You can only have one installed Analysis Server installed at any one time. Running inside of this we
have zero or more OLAP databases. When created, the databases are logical entities stored within
the OLAP repository (i.e. meta-data framework). For each database we define one or more data
sources (virtually any OLE-DB compatible source or ODBC link) in which we source data from for
cubes and/or dimensions.

213
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Cubes and Cube Storage Models

We have three different cube storage models in SQL Server:


a) MOLAP – data and aggregations stored in multi-dimensional structures on disk (data
directory)
b) HOLAP – leaves data at the data source and stores aggregations in multi-dimensional
structures on disk
c) ROLAP (dimension ROLAP stored only for Enterprise Ed) - leaves data at the data
source and also stores aggregations within the source database in which the fact table
resides.

OLAP Connectivity

Connectivity to analysis services varies, but is typically via is OLAP data provider or

In order for a client to task to analysis services, the MSSQLServerOLAPService must be running on
the server, this serves as the listener for the OLAP server. Connectivity is via the MSOLAPXX.dll
OLEDB provider from the client, as a connection string, this corresponds to the OLEDB provider
“Provider=msolap;”.

NOTE – Using the OLAP provider installed with SQL Server v7 OLAP services will not work
against Analysis Services cubes. This is especially evident when using Microsoft Excel and its
pivot control (Office 2000 web component), where virtual cubes (discussed later) are not
shown.

Search for msolap.dll to get versioning information. Be aware that in Excel, to connection to an
Analysis Servcies cube (SQL Server 2000 OLAP or OLAP v2.0), you need to use:

Security

We will not be going into any depth with programming OLAP, but even so, its worth spending a
little time exploring cell level security.

214
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

As with most things Microsoft, the fundamental security framework revolves around the Windows
Domain, its users and their NTFS and Domain (group-policy) privileges to determine what the
network user can and can not do. This flows into OLAP which only supports Windows
Authentication (can be very unfortunate for some installations). For the well-established Windows
Network, this allows seamless single-sign on to not only your databases (depending on the
application of course) but also to your OLAP cubes.

As a basic element of security, access to cubes and virtual cubes is via roles within OLAP. The role
can have any number of NT users or NT groups associated with it. On top of this, when allocated to
a cube, we can control a variety of security properties to further restrict the group’s users.

We manage cubes roles via the Cube Role Manager dialog that pops up when selecting role
properties for the cube. Note that you will get a different set of options if you select roles at the
cube level vs the entire analysis services database level.

IMPORTANT - remember that analysis services is a huge jump from OLAP Services released
with SQL Server v7, and as such, many of the options simply don’t exist or are only accessible
via ADO-MD API calls using VB or C++.

Security at the role level is very straight forward, but their comes a time where people will be
asking you to secure your cube at the cell level. A classic example that we will use is the
organisational chart, where we want staff members to only view their portion of data related to a
specific division/branch/section combination that the user selects from the cubes “organisational-
chart” dimension.

Example – Cell Level Security

The user can select a specific Division, Branch or Section to get their current financial position
in terms of budget and expenditure. It is critical to the business that people can only view
data based on their position within the organisation, therefore, the CEO can see all divisions,
the General Managers can see all data related to their specific Division, Directors are restricted
at the Branch level and Managers at the section level.

In our SQL Server data warehouse, we have linked over to the HR system and extracted the
current organisation chart to populate the org-chart dimension for the cube, and have also
extracted out information related to all staff members and their position within the chart. These

215
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

have been mapped (magically) to their Windows NT logins for single sign-on to the OLAP cubes.
So, with all that done, we know exactly what data “User A” can view in the cube and what they
cannot.

Within the analysis services, we select the cube of concern and edit their roles we have allocated to
the cube. The roles are actually programmically created (shown later), and have a poor naming
convention, but you get the idea:

In this case, role EISHROrg_012 has been created with one member. This has allowed to user to
access the entire cube and all its data. Clicking on the lock, we can drill into cell security to further
restrict the users access to the cubes underlying data.

Click on cell to edit and


manage cell security, or
move one level up and
restrict users to specific
dimensions.

Read Restriction Cell Security String (in MDX):

IIF ((
ancestor([HR Complete Org Chart].CurrentMember,
[Org Chart Division Name]).Name = "DivisionA")
AND (
ancestor([HR Complete Org Chart].CurrentMember,
[Org Chart Branch Name]).Name = "BranchB"
), 1, 0)

Read Contingent: Unrestricted

216
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Read/Write: Unrestricted

where [HR Complete Org Chart] is the dimension name, and [Org Chart Division Name] and
[Org Chart Branch Name] two of the three levels within the dimension that the user can filter
on to view cube data.

In this case, we are saying that if the user wants to read the data in BranchB which is part of
DivisionA, then they must be a member of this role, otherwise a value of 0 (false) is returned
and access is denied (no data shown to user).

IMPORTANT – Before testing the security for yourself, remove your NT login from the olap
administrators NT group, if you don’t the cell security will seem as though its not working for
you when it actually is.

In this particular example, we have generated the roles and applied the security strings to the
cubes via a chunk of VB code. The class has been implemented as a COM (dll) and it is called
via a scheduled DTS.

The next section looks at the DSO routines to do this.

ADO MD & DSO


To programmatically manipulate and query OLAP cube data (apart from using the Excel Pivot
Control and other 3rd party tools) the programmer can utilise ADO-MD (Active Data Objects – Multi-
dimensional). It essentially uses an underlying OLE-DB provider that is MDP (multi-dimension
provider) compatible for OLAP data access and manipulation.

To programmatically manipulate Analysis Services, the programmer needs to utilise the DSO
(decision support library) of COM objects. With these and ADO-MD, you can basically re-create the
Analysis Service Manager GUI if you like, just as using SQL-DMO you can rebuild Enterprise
Manager for SQL Server.

From the example for cell-security, we utilise DSO code (the DSO objects are installed on
installation of Analysis Services) within a small VB COM to remove existing roles, then re-create
them from information stored in our data warehouse. The code below as been simplified to show
the essential DSO commands used:

Dim sNewRole As String


Dim dsoServer As DSO.Server
Dim dsoDatabase As DSO.MDStore
Dim dsoCube As DSO.MDStore
Dim dsoRole As Role
Dim dsoCubeRole As Role
Dim varOLAPDatabase

varServer = "151.122.12.1"
varOLAPDatabase = "MyOLAPDB”

217
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

'Set up the connection to the OLAP server (not the DB)

Set dsoServer = New DSO.Server


dsoServer.Connect (varServer)

'Does the OLAP DB Exist on the server?


If dsoServer.MDStores.Find(varOLAPDatabase) Then

'Connect to the OLAP DB


Set dsoDatabase = dsoServer.MDStores(varOLAPDatabase)

'create the OLAP role, remove if it exists


sRole = "EISOrg_001”
If Not dsoDatabase.Roles.Find(sRole) Then
dsoDatabase.Roles.AddNew (sRole)
Else
dsoDatabase.Roles.Remove (sRole)

dsoDatabase.Roles.AddNew (sRole)
End If

'add the user to the role


strUser = "MYDOMAIN\myuser" ' NT security only
dsoRole.UsersList = strUser
dsoRole.Update

'add cell security string to this role


Set dsoCubeRole = dsoCube.Roles(sRole)

dsoCubeRole.SetPermissions "CellRead", _
"IIF ((ancestor([HR Complete Org Chart].CurrentMember, [Org Chart Division
Name]).Name = "DivisionA") AND (ancestor([HR Complete Org
Chart].CurrentMember, [Org Chart Branch Name]).Name = " & Chr$(34) & "
BranchB" & Chr$(34) & "), 1, 0)"

dsoCube.Update

End If

dsoServer.CloseServer

A thorough overview of the ADO-MD API can be found on MSDN.

http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/ado270/htm/ammscadoapireference.asp

Programming Analysis Services can also be found on MSDN.

http://msdn.microsoft.com/library/en-us/olapdmpr/prabout_84a4.asp

218
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Backup
To backup Analysis Services, the DBA must:

a) Backup the Registry (\Microsoft\OLAP Server)

b) Backup the repository data files, even if you migrate the repository to SQL Server you
should backup the bin directory to ensure maximum recoverability. This includes the
msmdrep.mdb database (unless you have migrated the repository to SQL Server).

c) Backup the OLAP data-files

If you select a ROLAP storage model for your OLAP cubes, this can complicate your backup as the
aggregations will be stored in the data-source in which your cube is utilising to source its fact data.
This is not a major concern as the cubes storage structure can be rebuilt, but this may be
problematic with very large cubes.

Within Analysis Service manager you can export your cube database, this is the primary method for
backup that is probably the most reliable. This will export the aggregations, security privileges, not
the actual processed cubes with their data. On restoring the OLAP database you will need to do a
complete re-process of the OLAP database (repository).

Look at the command line executable msmdarch.exe to archive a specific database into a single
.cab file. The DBA should extend this backup to include the items discussed above.

219
10
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Scripts & Scheduled Jobs

U
nder UNIX, the Oracle DBA writes numerous scripts for managing database backups,
instance re-starts, statistic collections, space management, the list goes on. These are
Typically scheduled tasks via cron (AT in Windows) and are written in a variety of
languages, including Unix scripting (whatever shell the DBA prefers), C, Perl etc. In
the SQL Server environment, the DBA has a range of methods to use that typically benefit the DBA
with a good knowledge of VB-Script and VB programming, these methods include:

a) Creating and scheduling DTS packages (run via SQL*Agent) that call T-SQL stored
procedures, VB-Script and any other COM or defined task they like to call.

b) Custom written COM, COM+ or standard executables routines that utilise SQL-DMO,
called via a scheduled VB-Script file scheduled via at from the command line or within a
DTS.

c) Simple VB-Script (.vbs files) scheduled via at from the command line.

d) Consider Perl and other scripting languages, so long as they communicate via OLE-DB,
ADO, ODBC etc.

e) For those “ill die without my grep” Unix phreaks, seriously consider downloading a unix-
toolkit for DOS (NT), there are some excellent ports and offer all the functionality
required to re-produce some great scripts under Windows. Lets face it, you cant beat
Unix for scripting.

As I am not a VB programmer by any means, I tend to use DTS packages calling T-SQL stored
procedures that I store in the master database. I then schedule them and SQL*Agent does the
rest. To enhance them, I may opt for some simple vb-script or callouts to existing DLL classes.
This is very simple to implement and with SQL*Agent it allows me to utilise its inbuilt notification
service on failure and to historically track its progress.

Some find that T-SQL procedures lack the features they require for more complex tasks. In this
case, I would recommend writing COM classes that utilise the SQL-DMO API calls to interact with
SQL Server. A range of examples are shown throughout this chapter.

NOTE – Consider 3rd party scheduling software if you are not utilising SQL*Agent and
associated jobs, as the OS scheduler’s smallest granularity for running jobs is daily.

220
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

T-SQL Routines
With the power of the sysadmin server privilege (system or sys account in Oracle), the DBA
can code some powerful T-SQL routines to assist with ongoing administrative tasks. Some of
the key commands of interest:
a) master..xp_cmdshell (to call out to an OS command)
b) master..sp_OA* procedures - call external COM and COM+ components
c) using temporary tables (table datatype and the create table #mytab statements)
d) using dynamic SQL (sp_executesql and exec())
e) using SQL*Agent and Jobs

XP_CMDSHELL Example

Here are a couple of simple examples of using xp_cmdshell to perform file OS file manipulation and
get a directory listing into a database table:

-- Move Unzipped files

set @v_commandline = 'move /y ' + @v_ftpdest + '*.unl ' + @v_processeddest


exec @result = master..xp_cmdshell @v_commandline

-- Get File list from directory for further processing (like unzipping them)

set @v_commandline = 'dir /B ' + @v_processeddest + '*.unl'

insert into infile_list


exec @result = master..xp_cmdshell @v_commandline

DTS
To call your DTS package you can:

a) schedule the package to run at some predefined date/time

b) review the command sp_start_job to force the running of a scheduled DTS package

c) review the executable dtsrun.exe

d) see the “execute package task” within the DTS package designer for cross calling of
between separate DTS packages (is version dependent on each save of the package, so be
warned).

Remember that scheduled jobs are managed by SQL*Agent which utilities the MSDB database as
its repository.

There can be issues with a packaged jobs not running when scheduled. Some of the areas to try:

a) the user in which the SQL*Agent service is running has insufficient database access

221
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

b) calling xp_cmdshell? And the user is not part of the sysadmin role? If so, if you fail to get
up the proxy account the step will fail. This “may” have flow on effects resulting in this
error.

c) Try forcing the first schedule to run, and see if SQL Server will correctly set the data/time
for the next scheduled run

d) Check the error log (obvious enough).

ISQL / OSQL

The DBA can utilise the command line equivalents to query analyser (SQL*Plus GUI) to run scripts
and pipe the results to a standard ASCII file. An example is shown below:

cd g:\scripts
osql -S SECA\MYINSTANCE -Usa -Pking /Q "EXIT(dbcc checkalloc('mydb1'))" -og:\scripts\mydb1_dbcc.txt
osql -S SECA\MYINSTANCE -Usa -Pking /Q "EXIT(dbcc checkalloc('mydb2'))" -og:\scripts\mydb2_dbcc.txt
osql -S SECA\MYINSTANCE -Usa -Pking /Q "EXIT(dbcc checkcatalog('master'))" -og:\scripts\master_catalog.txt
osql -S SECA\MYINSTANCE -Usa -Pking /Q "EXIT(dbcc checkcatalog('msdb'))" -og:\scripts\msdb_catalog.txt

Here we run a variety of DBCC commands and pipe the results to associated text files. Utilising
the sa account is not recommended in such a way and where possible, always opt for Windows
authentication for sysadmin access. From here, we can do a variety of things, such as using
Perl to extract and massage data from the file and produce appropriate reports, do a call to
some visual basic script or call an emailer to send the results directly to the DBA. In the
example below, we are utilising a command line emailer called smtpsend.exe to email the file
direct to the DBA:
cd g:\scripts
smtpsend.exe -fMyDBServer -tckempster@amcon.com.au -h163.232.x.xxx -s"PROD DB LOGSPACE STATS" -
ag:\scripts\dblogspace.txt

VB Script
With a VBS file (*.vbs) or VB Script within a DTS, the DBA can utilise many of the classic VB
commands, the key one being the file system objects library for OS file manipulation. I will leave it
up to the internet to give you a large range of examples, even so, here are some handy commands
to start you going.

NOTE – Variable declarations in VBScript are not explicitly typed (i.e. integer, float etc).
’ This is a comment, below is a CONSTANT
Const SUCCESS = 0

’ declare variables
Dim WshShell
Dim FSO
Dim oMsg
Dim lSMTPServer

222
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

’ Strings require double quotes


lSMTPServer = "163.231.4.128"

’ Example of using the date function


logfile = "myfile_" & Day(Date()) & "Jan" & Year(Date()) & ".txt"

‘ Example of a case statement and message box

Select case Month(Date())


Case 1 : msgbox “Month 1”
Case 12 : msgbox “Month 1”
End select

‘ Calling a OS command, in this case, running a SQL (script) file

retcode = WshShell.Run("isql -S myinstance -d mydb -U userA -P password -i myscript.sql", WSNORMAL, true)

‘ Moving a file

Set FSO = CreateObject("Scripting.FileSystemObject")


Call FSO.MoveFile("myfile.txt", processed_file)

‘ Log a message in the NT event log

WshShell.LogEvent SUCCESS, "Example Complete."

The .vbs file can be called directly via AT. If you have issues with running it then try using the
wscript or script commands, for example:

call %SystemRoot%\system32\cscript.exe //Nologo //E:VBScript


"%SamplesDirectory%\myfile.vbs" "MYExample"

VB / COM Example
The example below is not really related to a specific SQL Server problem, but gives you an idea of
the possibilities. We have written a small DLL that copies a series of files from one destination to
another with a date-stamp, and is called via a small VBS that we schedule via AT.

The key item here is that the experienced VB or C++ developer in the Microsoft realm can basically
do anything they like in terms of “scripted” programming. Most will argue that this is going a little
to far but offers a lot of functionality. Personally, the DBA will find that they can resolve most
problems elegantly with T-SQL routines / DTS package scheduled via SQL*Agent.

-- INI File
[database_backup]
database_location="C:\database\MyDB.mdb"
destination_folder="C:\database\backup\"

-- VBS File Source

Dim oDBBackup As dblib.DatabaseBackup


Dim lngReturn As Long

set oDBBackup = CreateObject("dblib.DatabaseBackup")


lngReturn = oDBBackup.BackupDatabase()

223
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

set oDBBackup = Nothing

-- COM+ Source File

VERSION 1.0 CLASS


BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 2 'RequiresTransaction
END

Attribute VB_Name = "DatabaseBackup"


Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True

Option Explicit

Implements COMSVCSLib.ObjectControl

Public Function BackupDatabase() As Long

Dim lngError As Long


Dim oFSO As Scripting.FileSystemObject
Dim oGen As dbutility.General -- another COM+ package of general utility functions
Dim strDBFile As String
Dim strDestination As String

On Error GoTo ERR_HANDLER


Set oGen = CreateObject("dbutility.General")

'Extract information from INI file.


strDBFile = oGen.GetINIFileSetting("database_backup", "database_location")
strDestination = oGen.GetINIFileSetting("database_backup", "destination_folder")

'Backup the database.


Set oFSO = CreateObject("Scripting.FileSystemObject")

If Not oFSO.FolderExists(strDestination) Then Call oFSO.CreateFolder(strDestination)


oFSO.CopyFile strDBFile, strDestination & Format(Now, "ddmmmyyyyhhmmss") & ".mdb", False

FUNCTION_RETURN:

'Vote on transaction.
If lngError = 0 Then
If Not GetObjectContext Is Nothing Then Call GetObjectContext.SetComplete
Else
If Not GetObjectContext Is Nothing Then Call GetObjectContext.SetAbort
End If

Set oGen = Nothing


Set oFSO = Nothing

BackupDatabase = lngError

Exit Function
ERR_HANDLER:

224
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

lngError = Err.Number
'Call off to a custom emailer or log to NT event log or text file…
-- Call SendEmail("Database backup failed.", Err.Description)
GoTo FUNCTION_RETURN

End Function

'********************************************************************
' COM PLUS METHODS
'********************************************************************
Private Function ObjectControl_CanBePooled() As Boolean
ObjectControl_CanBePooled = False
End Function
Private Sub ObjectControl_Activate()
'
End Sub
Private Sub ObjectControl_Deactivate()
'
End Sub

225
11
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Managing Databases

T
hroughout this chapter we discuss a wide variety of topics related to everyday
database management. Where appropriate we will draw comparisons with Oracle but
will not discuss in depth the differences, preferring to focus on practical SQL Server
examples.

Database Checking Routines


The DBA has a variety of options in Oracle, including:
a) DBMS_REPAIR
b) DBVERIFY
c) DB_BLOCK_CHECKING
d) DB_BLOCK_CHECKSUM
e) RMAN
f) ANALYSE TABLE VALIDATE STRUCTURE CASCADE

In SQL Server the DBA utilises one or more of the database consistency checking (DBCC)
routines, some of the commonly used ones are:
a) DBCC CHECKALLOC -- check disk space integrity for a database
b) DBCC CHECKCATALOG -- check consistency of system tables in a database
c) DBCC CHECKCONSTRAINTS -- check constraint integrity
d) DBCC CHECKTABLE -- check table page integrity
e) DBCC CHECKDB – check allocation and structural integrity
f) DBCC DBREINDEX -- rebuild table indexes
g) DBCC INDEXDEFRAG -- defragment clustered and heaps indexes for a table
h) DBCC OPENTRAN -- oldest open transaction dump
i) DBCC SHOWCONTIG -- get fragmentation information of a table
j) DBCC PINTABLE -- mark table as pinned in buffer cache
k) DBCC UPDATEUSAGE – update storage statistics

Other DBCC commands have been discussed throughout this e-book. See books online for
good coverage of these commands.

226
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Log Files (UDUMP, BDUMP)


The Oracle alert log is found at the backupground_dump_dest parameter destination. In SQL
Server this is called the error log and its destination is defined by the –e startup parameter.
This is also stored within the registry during instance start-up:

From within EM, we can right click the instance for global properties and view the start-up
parameters rather then searching the registry:

The management folder in EM allows the DBA to view the contents of the log files. I say files
because SQL Server will cycle through six different log files (default setting), the cycling of the files
will occur on each re-start of the SQL Server instance, or via exec sp_cycle_errorlog.

The DBA can control the number of cycled logs via a registry change, this change can be done
within Query analyser if you like or via EM by right click for properties in the SQL Server Logs
item under the Management folder.

Exec xp_instance_regwrite
N'HKEY_LOCAL_MACHINE',
N'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer',
N'NumErrorlogs', REG_DWORD, 6

The DBA can view error logs within query analyser using:

exec sp_readerrorlog [number of log file, values 0 to 6]

The valid list can be retrieved via:

227
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

exec sp_enumerrorlogs

Archive# Date Log File Size (Byte)


0 06/15/2002 23:59 3646
1 06/14/2002 21:25 21214
2 06/03/2002 21:36 3063
3 06/03/2002 10:29 49852
4 05/26/2002 14:25 31441
5 05/12/2002 16:27 5414
6 05/11/2002 15:54 2600

There is no equivalent destination for user traces as defined by the user_dump_dest parameter.

The error log for SQL*Agent is best managed via EM. With SQL*Agent shutdown, select its
properties and you can control a range of log settings:

Location & filename of the error log.

Include full error trace with log entries

Use non-unicode file format

228
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Linked Servers (Database Links)


The equivalent to the database link in Oracle is the Linked Server. The GUI interface for it is
located under the security folder within Enterprise Manager, which like all GUI’s executes a variety
of commands to create the database link.

The linked server supports any valid OLE-DB provider; this includes a variety of bundled providers
such as Oracle and OLE-DB and standard ODBC drivers (therefore, any source supporting ODBC
connectivity drivers). An example of Oracle vs. SQL Server db link creation:

CREATE DATABASE LINK mylink


CONNECT TO myuserid IDENTIFIED BY mypassword
USING 'sqlnetentry' -- entry points to instance “ZEN”

exec sp_addlinkedserver
N'MYORACLEDB' ,
@srvproduct = N'' ,
@provider = N'mylink' ,
@datasrc = N'ZEN' ,
@provstr = N'ZEN'

NOTE – Don’t assume that creating the link without error means the link actually works.

The SQL Server link includes a host of additional properties the DBA can manipulate. One of the
key benefits is the mapping of user accounts over the database link. In Oracle, the database link is
user centric, where we identified the CONNECT TO myuserid IDENTIFIED BY mypassword
properties in which the connection is established. In SQL Server, we can map one or more
accounts over the linked server; this allows the DBA to specify the local database user accounts
that can utilise the linked server and define how this user account is mapped to the remote system
over the link. An example is shown below later.

SQL Server supports the three part convention for referencing database objects in SQL, namely
[database].[owner].[objectname]. A linked server query requires four parts to be listed and we
cant create synonyms for them either (although we can create local views that refer to the linked
objects). So the convention now changes to
[linkedserver].[remotedatabase].[owner].[objectname]. Oracle DBA’s will hate this. Even worse,
it can restrict you in SQL queries and other DML operations, for example:

select mydb.dbo.mytable.col1
from mydb.dbo.mytable -- this is OK

select mylinkedserver.mydb.dbo.mytable.col1
from mylinkedserver.mydb.dbo.mytable -- this is NOT

Server: Msg 117, Level 15, State 2, Line 2


The number name 'mylinkedserver.mydb.dbo.mytable' contains more than the maximum number of prefixes. The
maximum is 3.

229
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

This presents some issues with inserts/delete/updates or complex recursive queries over the same
tables and column names where aliasing tables is not possible.

NOTE – If creating a linked server to another SQL Server instance and you are still having
connectivity problems, try: using the servers IP rather than the hostname, check remote
server listener is configured, try using the source service client network utility to configure an
alias to the remote server, ping or trace route to the server, verify providers.

The registry entry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC provides the hook to the


associated Oracle driver when linking to an Oracle DBMS:

To get a list of linked servers, use:


exec sp_linkedservers

From there, you can get a list of databases over the linked server by using:

exec sp_catalogs @server_name = 'mylinkedserver'

You can go another step further and get a list of tables over the linked server via:

exec sp_tables_ex @table_server = 'mylinkedserver'

to get a list of privileges:

exec sp_table_privileges_ex @table_server = 'mylinkedserver'

To improve linked server performance, consider the following:

exec sp_serveroption 'MYSERVER\MYINSTANCE', 'collation compatible', 'TRUE'


exec sp_serveroption 'MYSERVER\MYINSTANCE', 'lazy schema validation', 'TRUE'

Read the BOL for further information, and like all things, test for your installation:
exec sp_serveroption 'SECA\MY2NDINSTANCE', 'lazy schema validation', 'true'
The 'lazy schema validation' option is ignored in this edition of SQL Server.

230
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Example - Databases in the same Instance


You do not need to create a linked server to establish connectivity between databases in the
same SQL Server instance. If the login has database access to the other database (i.e. is a
user in the source and destination databases within the instance) with the necessary object
privileges, then we use the three part object lookup syntax to access the other database. For
example:

select * from myotherdb.dbo.mytable


or
select * from myotherdb..mytable -- current user or dbo assumed

Example - Connecting to an SQL Server Instance


Connecting to another SQL Server instance is relatively straight forward (and you would hope so
too!). The only trick here are those instances whose listener ports are very different from the
defaults, therefore, we may need to create an alias via the Client Network Configuration utilities at
the source server and set the appropriate settings in order to complete the connection to the
remote server.

SQL Server provider

EIS-NT is the hostname, or we could


have used the IP address.

This is the database name, we do


NOT include the [ ] as we would
normally do for database names with
spaces.

231
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Map our local users logins to remote


ones.

Security contextual information can


be passed between servers. This is
especially handy integrated security
logins.

Take care with these options; you can


open up the linked server to all logins
if you are not careful.

IMPORTANT - In the above example we map the SA account, don’t assume that just
because we listed the database in the linked servers creation that its only database we can
access. Since SA on the remote server as sysadmin access and access to all other databases,
we can utilise the linked server to access any remote database.

Example - Connecting to an Oracle Instance

IMPORTANT – There may be issues with manipulating BLOB objects from Oracle with the
Provider. Query the Microsoft support website for the latest information when resolving these
issues.

In this example we have a SQL Server 2k SP2 database and a Oracle 8.1.5 database installed on
the same server. We are creating a database link via the standard OLE-DB Oracle provider from
the SQL instance to the Oracle database.

232
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL*Net Connection string as entered in the


tnsnames.ora file

ZEN =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)
(HOST = seca)
(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = ZEN)
)
)

-- return list of valid OLE-DB providers


exec sp_enum_oledb_providers

-- create the linked server


exec sp_addlinkedserver
N'MYORACLEDB' ,
@srvproduct = N'' ,
@provider = N'MSDAORA' ,
@datasrc = N'ZEN' ,
@provstr = N'ZEN'

-- set linked server options as need be


exec sp_serveroption N'MYORACLEDB', N'connect timeout', 0

The provider has specific properties are set in the registry:

\SOFTWARE\Microsoft\MSSQLServer\Providers\MSDAORA

In order to establish the connection between the two servers, we need to enter the login
mappings via the security tab:

233
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

If the “sa” login is used to connect to SQL


Server, this will map to the scott/tiger user
in the Oracle instance and inherit this users
security privileges if we query over the
linked server.

For any other SQL Server user not listed


above, we can define other connectivity
properties. This can be treated as a catch all
for all other connections.

NOTE – You cannot profile (trace SQL via profiler) the addition of logins (linked servers or
local users) to the instance.

-- shows the linked server login server mappings we have created


exec sp_helplinkedsrvlogin N'MYORACLEDB'

-- attempt to get a list of tables on remote server via the linked server
exec master..sp_tables_ex N'MYORACLEDB' , null, null, null, '''SYSTEM TABLE'''

The following options should be set for your SQL Server session to ensure SQL-92
compatibility:

SET ANSI_NULLS ON
SET CURSOR_CLOSE_ON_COMMIT ON
SET ANSI_NULL_DFLT_ON ON
SET IMPLICIT_TRANSACTIONS ON
SET ANSI_PADDING ON
SET QUOTED_IDENTIFIER ON
SET ANSI_WARNINGS ON
SET XACT_ABORT ON -- auto rollback current trans on runtime failure

The SQL Server books online covers these options very well.

234
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

OPENQUERY, OPENROWSET, OPENDATASOURCE


Use OPENROWSET for once off, ad-hoc connections via OLE-DB to a remove server. In all cases, it
is very similar to that of a permanent linked server connection. I have seen a good 2 to 3 fold
increase in speed via OPENROWSET vs Linked Server lookup, but it does have a range of issues,
one being security.

An example is shown below from one linked instance to another on the same server:

SELECT aa.*
FROM
OPENROWSET('MSDASQL','DRIVER={SQL Server};
SERVER=SECA\MY3RDINSTANCE;
UID=sa;PWD=king', select * from pubs.dbo.authors) AS aa
ORDER BY a.au_lname, a.au_fname

We can specify a query, table name or view name within the OPENROWSET command. On the
source and destination instance we see the following:

-- Source instance
Execution Tree
Sort(ORDER BY:([a].[au_lname] ASC, [a].[au_fname] ASC))
|--Remote Query(SOURCE:(<UNKNOWN>), QUERY:(SELECT a."au_id" Col1013,a."au_lname"
Col1014,a."au_fname" Col1015,a."phone" Col1016,a."address" Col1017,a."city" Col1018,a."state" Col1019,a."zip"
Col1020,a."contract" Col1021 FROM "pubs"."dbo"."authors" a))

-- Remote instance
Execution Tree
Clustered Index Scan(OBJECT:([pubs].[dbo].[authors].[UPKCL_auidind] AS [a]))

declare @P1 int


set @P1=2
exec sp_prepexec @P1 output, NULL, N'SELECT a."au_id" Col1013,a."au_lname" Col1014,a."au_fname"
Col1015,a."phone" Col1016,a."address" Col1017,a."city" Col1018,a."state" Col1019,a."zip" Col1020,a."contract"
Col1021 FROM "pubs"."dbo"."authors" a'
select @P1

When compared to a linked server connection, we see the following, it is essentionally the same
with additional schema locking on the remote server.

-- Source instance
Execution Tree
Remote Query(SOURCE:(MyLinkedServer), QUERY:(SELECT a."au_id" Col1002,a."au_lname"
Col1003,a."au_fname" Col1004,a."phone" Col1005,a."address" Col1006,a."city" Col1007,a."state" Col1008,a."zip"
Col1009,a."contract" Col1010 FROM "pubs"."dbo"."authors" a))

-- Remote instance
RPC:Starting declare @P1 int
set @P1=NULL
declare @P2 bigint
set @P2=NULL
exec sp_getschemalock @P1 output, @P2 output, N'"pubs"."dbo"."authors"'
select @P1, @P2 Microsoft SQL Server sa 3736 51
2002-06-30 20:29:09.640

declare @P1 int


set @P1=1
declare @P2 bigint

235
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

set @P2=8670987119726518
exec sp_getschemalock @P1 output, @P2 output, N'"pubs"."dbo"."authors"'
select @P1, @P2

declare @P1 int


set @P1=-1
exec sp_prepexec @P1 output, NULL, N'SELECT a."au_id" Col1002,a."au_lname" Col1003,a."au_fname"
Col1004,a."phone" Col1005,a."address" Col1006,a."city" Col1007,a."state" Col1008,a."zip" Col1009,a."contract"
Col1010 FROM "pubs"."dbo"."authors" a'
select @P1

exec sp_unprepare 3
exec sp_releaseschemalock 1

We also have OPENQUERY. This takes a pre-created linked server and a SQL string (if more than 1
query it used in the query string, only the first is actually returned). An example is shown below:

SELECT AA.*
FROM OPENQUERY(LinkServer, 'SELECT * FROM pubs.dbo.authors') as AA

The first thing you will notice on tracing this command, is that no schema locking is done on the
remote server which doesn’t occur using a traditional 4-part query via the linked server.

Finally, we have OPENDATASOURCE. Do not use this command, but rather create a proper linked
server or utilise OPENROWSET. This command will execute a range of remote calls on the remote
server that will affect overall performance. As an example:

SELECT *
FROM OPENDATASOURCE(
'SQLOLEDB',
'Data Source=SECA\MY3RDINSTANCE;User ID=sa;Password=king').Pubs.dbo.authors

Will execute a range of calls such as:

exec [Pubs]..sp_tables_info_rowset N'authors', N'dbo', NULL


exec [Pubs]..sp_columns_rowset N'authors', N'dbo', NULL
exec [Pubs]..sp_indexes_rowset N'authors', NULL, N'dbo'
exec [Pubs]..sp_check_constbytable_rowset N'authors', N'dbo', NULL, NULL
exec sp_getschemalock @P1 output, @P2 output, N'"Pubs"."dbo"."authors"'
<etc>

With this simple query, total execution time doubled verses linked servers and open row source
alternatives.

In virtually all cases, use linked servers.

Remote Servers
The remote server option is a form of Linked Server but is SQL Server to SQL Server only and you
can only execute stored procedures over the link. In most cases, utilise linked servers rather than
remote servers.

236
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

DTS Packages
Data transformation service (DTS) is a fantastic feature of SQL Server. The books online gives a
overall description, that being “an organized collection of connections, DTS tasks, DTS
transformations, and workflow constraints assembled either with a DTS tool or programmatically
and saved to Microsoft® SQL Server™, SQL Server 2000 Meta Data Services, a structured storage
file, or a Microsoft Visual Basic® file”. We will drill into them throughout this section.

The product is composed of:


a) MSDB system database tables and views
b) GUI management and editing utility that is embedded in Enterprise Manager
c) Command line utilities to run saved packages (dtsrun.exe or the GUI version
dtsrunui.exe)
d) DTS Object Model (API)
e) DTS Information Model (to store meta-data information about the running of a package
and its transforms)
f) DTS import/export wizard

At the lowest level, a single DTS “package” is a range of record entries in the MSDB database table
sysdtspackages, the schema is shown below:

sysdtspackages
sysdtspackagelog sysdtssteplog
(the actual
package code)

sysdtscategories sysdtstasklog
(DB storage type)

NOTE – The above tables are not applicable to meta-data services packages. They are
stored in the MSDB database within the table prefixed with RTbl.

The key tool for managing (i.e. creating, deleting, updating) DTS packages is Enterprise Manager.
The GUI is not hard to understand and simply requires you to experiment with its variety of
supplied active-x controls that, via their interactive dialogs, utilise SQL-DMO and the DTS object
model to graphically present zero or more steps of programming logic. This may include any
variety of tasks (packagedata column in sysdtspackages), such as loading data from a spreadsheet
or another database, or processing a OLAP cube, calling an OS command, calling a VB COM we
previously created or running some VB-Script, the possibilities are endless.

237
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

We will discuss meta-data services later in this section, suffice to say that a majority of packages
will be local packages and if you need to generate meta-data about the running of a package, it
must be stored as a meta-data services package (it is not an actual service in NT speak).

Right click local packages and select the new package option. The designer is shown and exposes
many of the underlying DTS object model calls to the end-user through the supplied connection and
task active-x objects supplied, coupled with package properties etc. The DBA should simply
experiment with the GUI via right-clicking properties, trying the supplied active-x controls. An
example package is shown below.

Workflow (waiting, success, failure or


completion), can be controlled via DTS
API calls if need be to alter the
execution flow dynamically and code
execution “loops” for example.

Right click in white pane for a


variety of options, such as global
variables, logging, concurrency
control etc.

This is a transform(ation). Defining how data from the source is


placed into the destination, each field can be transformed as it
comes in, logging properties are error counts set and much more.

Standard OLE-DB connections, including Microsoft office


products, ODBC to Oracle, Dbase5 etc. A transform can-not
be created unless its “to” a connection.

A variety of tasks, one being an active-x (vb or j-script) task, command line call-out to
an OS command, OLAP cube refresh, FTP (cant FTP from the server, only too it
unfortunately), SQL Mail mailer and a variety of others.

IMPORTANT – Check the properties of all objects very carefully, especially the
transformation task as it includes items such as automatic connection closing after data
transformation.

It is not until you save a package with actual package content will the packagedata column in
sysdtspackages will be populated. Each save will create a new “version” of the package in the
same sysdtspackages table, see the version id column (which is a unique-identity data type). You
are presented with the dialog on save:

238
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL Server (local package)


Meta Data Services (data
warehouse and linage tracking
repository)Generate VB source of
the package (very handy for
learning the DTS object model) or
proprietary DTS structured file
format.
Meta data can only be collected for
meta data packages.

To get the packages version (and go back versions!), right click the package and select version.
This will run the following using the unique-identity column value within sysdtspackages:

exec msdb..sp_enum_dtspackages "%","%",NULL, 0x04,"AAB0B84F-7F4F-4432-BFDD-44FD8754801E"

NOTE – To transfer a package to another server, consider save-as and entering the remote
host-name and security information (if you have trouble connecting, use the client networking
utility and create an alias then try again). Another option is saving the package as a
structured file, to restore, right click properties of the “Data Transformation Services” folder in
Enterprise Manager and select Open Package. Another unsupported method is simply bulk-
copying the contents of the sysdts tables over to the new server, good luck with this one. I
rare use the meta data services option so I wouldn’t even consider direct system table
transfers at that level.

As the data model describes, there is a variety of log information associated with each package.
This is very handy for drilling into runtime errors at each step within the DTS. Occasionally I have
experienced flow control problems where steps run when they are not supposed to, the logs are
handy when identifying such problems (re-create the workflow and/or transformation as need be).
The package logging will not be activated until you enable it within the package designer, right
clicking on the blank pane and selecting properties:

239
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

You can send log information to


another server/instance, be
warned that it can be very
difficult to work out (at the
remote server) where the log
data is coming from. Name
your packages carefully to
assist with identification.

Click properties of the package


to view the runtime log error
information. If logging to a
remote server or instance, you
will NOT see the package listed,
select properties as per normal
and use the drop down list to
pick the package name.

Some of the key stored procedure for DTS manipulation are, including viewing the log are:

exec sp_MShelpcolumns N'dbo.sysdtspackages', NULL


exec msdb..sp_get_dtspackage
exec msdb..sp_add_dtspackage
exec msdb..sp_drop_dtspackage
exec msdb..sp_enum_dtspackages
exec msdb..sp_enum_dtspackagelog

To lock down DTS, the DBA can revoke execute access to these to prevent DTS creation and
viewing. The security paradigm for DTS packages is crazy and Microsoft really need to this one up.
For example, if User1 created a DTS package called “user1 package”, then any other user can run
and schedule the package. The user can assign a password to the package that will prevent other
users from running, scheduling and editing the package. Note that SQL Sever is not smart enough
to associate this with your login and/or security group and it will also ask the creator of the package
for the password.

240
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The save-as dialog allows the user to enter the appropriate password information. User password
allows scheduling and execution, owner password allows editing.

If you want, say, user1 and user2 to edit the same package, then SQL Server takes a dive for the
worst. Unfortunately, no matter what you do in terms on the passwords above or playing with
windows or SQL Server authentication properties on the DTS package save, user2 will get the
error:

On saving the package, SQL Server does a lookup using SUSER_SID (owner_sid column in
sysdtspackages) and SUSER_SNAME (owner column in sysdtspackages), returning the security ID
for the DB login name, no matter your authentication (trusted or not) to the instance via EM, this
ID is entered in the owner column in msdb..sysdtspackages and is used as a lookup for users
attempting to save the package. If the name is not the same then saving will fail.

User1 SUSER_SID:
0x680298C78C5ABC47B0216F035B3ED9CC

User2 SUSER_SID:
0xF1C954D9C9524C41A9ED3EA6E4EA82F4

Under EM, the owner of the package is represented by the users windows login DOMAIN/username.

The DBA can “turn-off” the check to allow many users to work on the same package by
uncomment’ing the following code from a system stored proc:

Source : msdb..sp_add_dtspackage

IF (@owner_sid <> SUSER_SID() AND (ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0) <> 1))


BEGIN
RAISERROR (14586, -1, -1, @name)
RETURN(1) -- Failure
END

Of course, this is somewhat risky and Microsoft Support will not help you out with further MSDB
issues. To “switch” security, try to run the following with sysadmin privileges:

241
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

-- user1 get SID and Owner name


select SUSER_SNAME() -- Owner Name
select SUSER_SID() -- SID

-- user2 get SID and Owner name


select SUSER_SNAME() -- Owner Name
select SUSER_SID() -- SID

-- In this case, make user2 the new owner of the package(s)


update msdb..sysdtspackages
set owner = ‘user2’, owner_sid = 0x680298C78C5ABC47B0216F035B3ED9CC -- user2
where owner_sid = 0xF1C954D9C9524C41A9ED3EA6E4EA82F4 -- user1

There is an undocumented procedure that can change the owner as well, the syntax is:

sp_reassign_dtspackageowner [@name =] 'name',


[@id =] 'id',
[@newloginname =] 'newloginname'

See www.sqldts.com for more information specific to DTS.

NOTE – If you restore a MSDB database from another server, be warned that the jobs will
need to be re-created and that each DTS package entry in msdb..sysjobs may also present
errors related to MSX (remote server management). Try altering the originating_server
column in sysjobs to get around the error.

A scheduled package will run under the security context defined by the users system privileges. If
the user does not have sysadmin fixed server role access, the package will execute via the
sqlagentcmdexec proxy account (as per calls to xp_cmdshell). The proxy setup can be managed
via EM by selecting properties of SQL Agent and going to the Job System tab.

To kill off a running package, the user must have the process administrator fixed server role or
sysadmin access.

242
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Diagrams (Data Model Diagrams)

All user databases include the ability to create “diagrams”, which are stored in the system
table dtproperties. The diagram editor in Enterprise Manager allows the DBA to create
physical data models, maintain tables, indexes and constraints (but not security privileges).
From there, SQL Server can generate SQL scripts based on your changes to be saved and run
later or to be applied immediately. A screen shot is shown below:

System table holds diagrams

Manage tables,
indexes, add
annotations,
different views
etc. Some
classic Microsoft
Access GUI feel
in places.

NOTE – Before printing diagrams, double check the printer and page size match’s what you
set within the diagrammer, it has this ability to revert back to A4 when you were actually after
a completely different setting.

I found this tool to be an excellent feature, and although it is far from being a full featured
modelling tool, it can generate scripts that are reliable time after time. This is particularly helpful
when managing large data models and saves time when creating database alteration scripts. It
should be noted that the scripts, are not optimal in terms of locking/blocking and the statement
being used; the experienced DBA may be shocked what they see. This can have adverse effects for
heavily used 24x7 databases.

243
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Transferring Diagrams
a) Identify the diagrams to be transferred

select id, objectid, property, value


from sourcedb.dbo.dtproperties
order by 2 desc,1

Each diagram consists of 7 records, the DtgSchemaNAME property has the name of the
diagram, use this in conjunction with the objectid column to locate the diagram. We
need to transfer all 7 rows.

b) Check the destination dtproperties table before transfer

The objectid column of the source table is the most critical. We need to maintain its
value to successfully complete the transfer. From the query above, check that the
destination dtproperties does not already have the objectid. If it does, get the
maximum id from the destination table and use it within your select statement.

c) Transfer the diagram (from sourcedb to the destdb)

The key here is the objectid column, it must be unique, the id column is an identity and
does not need to be specified. If it is not, then editing one diagram will alter the other
that shared the same objectid and dropping one will drop the other ! you don’t want
this sort of trouble.

We wont risk this and will specify objectid value 2 as we are 100% sure its unique
within the dtproperties table in the destination database.

insert into destdb.dbo.dtproperties


(objectid, property, value, uvalue, lvalue, version)
select
2 /* we know the object id 2 is unique in the destination table */,
property, value, uvalue, lvalue, version
from
sourcedb.dbo.dtproperties
where objectid = 12 -- this is the diagram we want to transfer

d) Same Name diagram?

Then rename it with a simple update statement before or after the insertion is made.

244
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Row Chaining & Migration


You cannot have row chaining in SQL Server, if a row cannot fit in a free page allocated to the
object, then another is allocated. This also means that, unless binary text blobs are used, a
maximum row size is 8037 bytes.

Row Migration is known as Page Splitting, and will primarily occur when an existing row is updated
but can not fit in its current page.

Tablespace (File-group) Management

As the Oracle DBA can move tablespaces, so the SQL Server DBA can move and manage
filegroups.

To get filegroup information for your database, run the command:

exec sp_helpfile

This will return all necessary information to manage your filegroup and its associated datafiles. The
examples below we will use the following database structure (as reported by sp_helpfile):

To alter a filegroups status:

alter database fgexample modify filegroup fg1 readwrite


alter database fgexample modify filegroup fg1 read-only

select FILEGROUPPROPERTY ('fg1', 'IsReadOnly')


returns 1 or 0

You cannot place the PRIMARY filegroup into read-only (and other) mode; the entire database must
be set if the primary filegroup is to change as its initial data file houses the sys files for the
database. Also remember that the transaction log files have no concept of file groups.

NOTE – If you attempt to create a new database via EM and have query analyser open with
the Model database set in context, you will get an unable to obtain exclusive lock error.

To move a filegroups database files:

245
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

You need to use the sp_attach and sp_deattach commands to keep the entire instance up.
Of course, the database will be down during this period and will invalidate logins to this
database for the cutover period.

To create a table or indexes in a filegroup:

create table ourtest (col1 int) on fg1

To view the tables in a filegroup:

select o.name as TableName, s.groupname as FileGroup, u.name as Owner


from sysobjects o, sysindexes i, sysfilegroups s, sysusers u
where o.id = object_id(N'dbo.ourtest')
and o.type in ('S','U')
and o.id = i.id
and i.indid in (0,1)
and o.uid = u.uid
and i.groupid = s.groupid
-- and s.groupname = 'yourfilterhere'
order by 1 desc

To shift a table or index between filegroups:

Tables must be re-created, use EM to alter the table and see the generated code. For
indexes, use the DROP_EXISTING clause, for example:

CREATE
INDEX [myindex] ON [dbo].[ourtest] ([col1])
WITH
DROP_EXISTING
ON [FG2] -- the new filegroup

To drop a filegroup:

alter database fgexample remove filegroup fg1

Server: Msg 5042, Level 16, State 7, Line 1


The filegroup 'fg1' cannot be removed because it is not empty.

246
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Pinning Tables
As with Oracle, we can pin tables into the buffer cache and reduce the possibility of pages being
aged out and adding to the IO round trips to the database files.

An example is shown below:

USE mydb

DECLARE @dbid INTEGER


DECLARE @obid INTEGER

SET @dbid = DB_ID('mydb')


SET @obid = OBJECT_ID('dbo.mytable')

DBCC PINTABLE (@dbid,@obid)

or
EXEC sp_tableoption 'mydb', 'mytable', 1

Check if table is pinned:

-- returns 1 (yes) or 0 (no)


select OBJECTPROPERTY ( object_id(‘mydb’),'TableIsPinned')

Take care when moving databases between servers where tables have been pinned. I have come
across a variety of examples where, on servers with less RAM, the pinning can result in buffer
cache errors and subsequent cache trashing (resulting in a reboot!).

Triggers
Some general information on triggers in SQL Server:

a) SQL Server supports the following trigger types:

a. INSTEAD OF [INSERT, DELETE, UPDATE], only one per action and as the name
states, replaces the normal processing, can support text,ntext, image column data.

b. AFTER [INSERT, DELETE, UPDATE], can have multiple per action, can specify order
of action, trigger code cant refer to text,ntext,image column data.

b) Set trigger firing order via sp_settriggerorder

c) Run sp_helptrigger to view trigger information for a table

d) You can enable and disable triggers, either named or ALL for a table, for example:
alter table dbo.mytest disable trigger all

e) An error in the trigger will rollback the entire transaction. Transactions in triggers are
actually nested transactions to its parent. Cursors are also closed and deallocated in

247
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

context to the parent transaction. Consider the SAVE TRANSACTION (marked transactions)
to do a partial rollback.

f) Mutated triggers are supported – where the trigger fires DML against its own table

Constraints

In SQL Server constraints are implemented for:

a) primary keys

b) foreign keys

c) column check constraints

d) default column values

e) implement UNIQUE constraints

We can alter constraints via:

ALTER TABLE dbo.mytest [CHECK, NOCHECK] CONSTRAINT DF_mytest_col1

To check data integrity in term of foreign key constraint consistency, consider the command:

DBCC CHECKCONSTRAINTS

NOTE – Always name your constraints. As with Oracle and its system naming convention,
SQL Server’s equivalent is no better and can result in major problems when attempting to run
so called “common” scripts over many servers.

Long Running Transactions


Use the DBCC OPENTRAN command to view the longest open transaction. This command requires
sysadmin access and the db_owner database role.

DBCC OPENTRAN (‘northwind’)

Transaction information for database 'Northwind'.

Oldest active transaction:


SPID (server process ID) : 53
UID (user ID) : 1
Name : user_transaction
LSN : (27:380:2)
Start time : Jul 24 2002 10:28:32:867AM

248
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

From here, use sp_who2, sp_lock or trace the session to determine the ongoing activity for the
session. Consider the dbcc inputbuffer command for a dump of the SPID.

SQL Timeouts
A client timeout may be the result of:

a) Dead-locking and/or blocking problems


a. Isolation level settings from client connection
b. Use of begin/end transaction in code (locks held for long periods of time)
c. Unexpected lock escalation
b) Incorrect SQL statement (missing join condition)
c) Poor or inappropriate use of hints
d) General connection properties
a. Again, isolation level
b. Lock timeout value (also see COM+ timeout setting)
c. Close cursor on commit
e) Using QUERY GOVENER within your application to restrict resource usage of a SQL
statement(s).
f) ASP session timeout as defined in IIS
g) Database query timeout value
a. @@LOCK_TIMEOUT set
b. query wait (instance level) expiring due to held resources

Rename Database
Use the command master..sp_renamedb. Be aware that logins whose default database was
set may also change, this can be a problem for the DBA when renaming to only replace with
another version of the same database for testing purposes (or other reason). Check logins
and verify that you do not need to alter their default database property. After renaming, it is
a good idea to set the DBO only property if it is not to be used by end-users, this can assist
with debugging login issues.

249
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

User Management
Login vs User

In SQL Server 2000, a single login maps to a single user in one or more databases within the
instance. The login defines a basic set of properties for the connection to the instance, the EM
screens encapsulate these options as shown in the screen shot below:

The core items of interest are:

a) allocation of instance level system privileges (server roles)

b) define the default database instance and language

c) determine the method of authentication (mixed or integrated)

a. authenticating domain must be available (via trust or the server is a member of the
domain)

d) define database access

Defining database access will create a user entry in the sysusers table for the database. The
syslogins table in the master database is loosely coupled to the databases sysusers table via the
SID column. See orphaned logins next for more information.

All security for the user should be granted by database roles to simplify overall privilege
administration.

250
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Orphaned Logins
At times, the DBA will restore a database from one instance to another, in doing so, even
though the login exists for the instance, the SID (varbinary security ID) for the login is
different to that in the other instance. This effectively “orphans” the database user from the
database login due to this relationship between master..syslogins and mydb..sysusers.

master database user database

syslogins sysusers

SELECT SUSER_SID('user1')

0x65B613CE2A01B04FB5E2C5310427D5D5 -- SID of user1 login, instance A


0x680298C78C5ABC47B0216F035B3ED9CC -- SID of user1 login, instance B

In most cases, simply running the command below will fix the relationship and allow the login to
access the user database (must run against every database in which to login is valid against).

exec sp_change_users_login <see books online>

This will only work for SQL logins and not fully integrated logins (which is a down right pain). Write
your own script (or search the web) to resolve this problem.

If you are still getting errors, consider removing the user from the sysusers table in the restored
database, and re-add the user to the

The DBA can validate NT login accounts via the command:

EXEC sp_validatelogins

NOTE – Do not use ALIASES; this allowed the DBA to map a single login to many database
user.

Microsoft released a great support document related to the scripting of logins, including the original
password. The script is not complete in terms of all possible options, but is very handy:

Example: (http://support.microsoft.com/default.aspx?scid=kb;[LN];Q246133)

/* sp_help_revlogin script
** Generated Nov 17 2002 12:14PM on SECA\MY2NDINSTANCE */

DECLARE @pwd sysname

-- Login: BUILTIN\Administrators
EXEC master..sp_grantlogin 'BUILTIN\Administrators'

-- Login: user1

251
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SET @pwd = CONVERT (varbinary(256),


0x0100420A7B5781CB9B7808100781ECAC953CB1F115839B9248C3D489AC69FA8D5C4BE3B11B1ED1A30154D955B8
DB)
EXEC master..sp_addlogin 'user1', @pwd, @sid = 0x680298C78C5ABC47B0216F035B3ED9CC, @encryptopt =
'skip_encryption'

-- Login: user2
SET @pwd = CONVERT (varbinary(256),
0x01006411A2058599E4BE5A57528F64B63A2D50991BC14CC59DB0D429A9E9A24CA5606353B317F4D4CA10D19A2E
82)
EXEC master..sp_addlogin 'user2', @pwd, @sid = 0xF1C954D9C9524C41A9ED3EA6E4EA82F4, @encryptopt =
'skip_encryption'

Change DB Owner

You can change the database owner with the command:

USE MyDatabase
EXEC sp_changedbowner 'MyUser'
GO

This requires the sysadmin instance privilege, and the user will logically replace the dbo user. You
cannot run this command against the system databases. In 99% of cases, this command should
not be used.

User Quotas & Account Expiry

SQL Server has no concept of user quotas or resource allocation restrictions as in Oracle. The best
bet is to restrict the growth of the entire database. There is also no concept of account expiry,
forcing password changes, account locking etc.

The DBA should consider QUERY GOVENER, read up the books online for a good overview. This can
only be set via the client on connection to the instance (we have no on-login triggers).

The DBA can deny and grant login via:

exec sp_grantlogin
exec sp_denylogin
exec sp_revokelogin

Unfortunately this only works for Windows NT logins and/or associated groups:

EXEC sp_denylogin 'user2'

Server: Msg 15407, Level 11, State 1, Procedure sp_revokelogin, Line 31


'user2' is not a valid Windows NT name. Give the complete name: <domain\username>.

OPS$ Logins (OS Authentication)

The equivalent to the OPS$ login for SQL Server is a fully integrated windows login.

252
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Change Object Owner

Unless you are the dbo (have db_owner or db_ddladmin privileges), you cannot create objects as
another user, for example, if I am logged in as user1 cant issue the statement create table
user2.mytable (col1 int). As its best practice to have all objects owned by DBO, the DBA may
from time to time change the objects owner, we do this via the command:

exec sp_changeobjectowner ‘user1.mytable’, ‘dbo’

After running the command, refresh enterprise manager and check the object and its privileges. If
it’s a stored procedure, make sure that the actual create statement is not referring to the old user.
This is a classic problem that will ruin you plans for faultless scripting of the object.

Check object ownership

To check if a user owns objects, run the command:

-- Get user ID
DECLARE @userid smallint
SET @userid = (SELECT uid FROM sysusers WHERE name = 'myuser')

-- Check ownership
exec dbo.sp_MScheck_uid_owns_anything @userid

User Lock Timeouts

As there are no “on login” triggers and very few login properties that can be automatically set for a
new connection, the DBA has to rely on the developer to do the work. One of these properties is
LOCK_TIMEOUT. The value is in milliseconds and zero represents no wait time for locks. A timeout
will cancel the SQL statement being executed and must be trapped by the developer:

SET LOCK_TIMEOUT 5000 -- 5 second timeout


SELECT @@LOCK_TIMEOUT -- retrieve current value

I recommend that you do not use this setting as standard practice; it does not take into
considerating a heavily worked instance or “once off” locking issues that can result in a ripple effect
of application errors if the property was set. If you are in a multi-tier environment (i.e. asp,
com+), in which their own timeouts can be set, then consider making the DBMS connection timeout
the lowest to capture the DBMS error rather than at a higher level.

Transfer Logins between Servers

To transfer logins between servers and retain the logins password (SQL Logins), consider utilising
the DTS task to transfer logins between servers, or the following SQL statements:

select 'sp_addlogin @loginame = ' + name + ', @passwd = "' + password + '",
@encryptopt = skip_encryption, @deflanguage = "' + language + '"' + char(13) +
'go' from syslogins
where name in ('user1', 'user2')

253
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The key to this script is the skip encryption option. Note that we still need to:

a) setup the login Æ database user relationship (sp_adduser)

b) assign database user privileges

Change a Users Password

Use the command sp_password for SQL logins only (not applicable for NT logins of course), for
example:

exec sp_password NULL, ‘newpassword’, ‘mylogin’

Rename a Login

You cannot rename logins in SQL Server. Actually, you can, but this means changing some entries
in the sys tables so good luck with that one. The process involves:

a) altering server configuration to allow adhoc changes to system tables

b) update user login name in master..sysxlogins

c) update databases in which the user exists for dbo.sysusers

Killing Sessions
Within Oracle the DBA can kill user sessions via looking up v$session for the particular user or
other status, and issuing the command (just examples of syntax):

alter system kill session ‘<sid>, <serial#>’ immediate;


alter system disconnect session ‘<sid>, <serial#>’ POST_TRANSACTION;

At the OS level for rouge Oracle processes, the Oracle DBA on Unix can issue the “kill”
command or on NT can use orakill.exe.

Within SQL Server, each connections is allocated a spid (system server process identifier and
worker thread). To identify them we can execute the system stored procedures:

exec sp_who
or
exec sp_who2

The DBA can also use the current activity option under the Management Group folder and
select Process Info.

254
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

NOTE - Be warned, I have experienced major performance problems when forcing the
refresh of current activity via Enterprise Manager to a point where the CPU’s hit a solid 50%
for 5 minutes before returning back to me. This is not funny when running against a hard
working production system.

Once the SPID has been identified, we use the KILL command to remove the session. For
example:

select @@spid -- get my sessions SPID, in this case its 51


exec sp_who2 -- from output, determine SPID to be killed
Kill 55 -- issue kill request to DBMS
Kill 55 with statusonly -- get status of the request

SPID 55: transaction rollback in progress. Estimated rollback completion: 100%.


Estimated time remaining: 0 seconds.

The DBA should reissue sp_who2 to monitor the SPID after the kill to ensure success. Also
consider looking at and joining over the tables:
• sysprocesses
• syslock
• syslockinfo

You cannot kill your own processes. Be very careful you do not kill system processes. The
processadmin fixed system role will allow a user to kill SQL Server sessions.

NOTE - Killing SPID’s running extended stored procedures or did a call-out to a user created
DLL may take some time to kill and, in some cases, seem to have stopped but remain as a
running process.

There is no POST_TRANSACTION option as in Oracle’s alter session statement. Basically SQL


Server will do an IMMEDIATE (disconnect and recover session without waiting for ongoing
transactions) disconnect.

To get further information about a session, consider the command:

DBCC PSS (suid, spid, print-option)

For example:

--Trace flag 3604 must be on


DBCC TRACEON (3604)

--Show all SPIDs


DBCC PSS

DBCC TRACEOFF (3604)


GO

This is an undocumented command. For a good coverage consider see reference (46).

255
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Orphaned “Sessions”

An orphaned session has a SPID of –2, this may be caused by a variety of things (though rarely)
and is typically linked to the distributed transaction coordinator (DTC). A DTC related problem will
show up in the SQL Server log files with an error such as “SQL Server detected a DTC in-doubt
transaction for UOW <value>”. If the transaction issue can not be resolved, then a kill statement
can be issued over the UOW code. For example:

Kill 'FD499C76-F345-11DA-CD7E-DD8F16748CE'

The table syslockinfo has the UOW column.

NOTE – Use Component Services when appropriate to drill into COM+ classes and their
instantiations to locate UOW to assist with killing the correct SPID at the database.

TEMPDB
The tempdb is utilised for a variety of reasons, such as:

a) using create table #mytable ( clause to create temporary tables

a. consider the table datatype over # temp tables.

b) by the optimiser to complete a statement where necessary, typically shown as worktables

c) many of the DBCC commands utilise temporary tables

d) large sort and group by operations

The DBA can manage all tempdb functions through EM, even so, here are some important
commands to remember

Task Command
Check DB Size exec sp_spaceused
Shrink DB DBCC shrinkdatabase(N'tempdb')
Move files alter database tempdb
modify file (name=tempdev,filename = 'c:\dbdata\tempdb\tempdb.mdf')
go
alter database tempdb modify file
(name=templog, filename=' c:\dblog\tempdb\templog.ldf')
go
Space Usage exec sp_tempdbspace (undocumented command)
Size of Using the alter command with the SIZE option
Usage of Consider querying sysobjects in the tempdb database to monitor the creation of
# and ## temporary table objects. Also condsider the SQLServer:Databases
performance monitor counter and also profiler (filtering out the database by ID).

You should keep the standard database options with tempdb. You may want to pre-empt the
increase of the database size and alter growth rates as you feel appropriate. As a very general

256
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

indicator, my production DB with 800 online users, 4Gb data with lots of OLTP activity and standard
DBCC functions at night, see’s tempdb growing to a maximum of 800Mb.

It is not recommended that you run DBCC commands (like CHECKDB) against tempdb. There is a
good chance that errors will be returned depending on what is happening at the time. Remember
that tempdb is rebuilt on instance restart, if you do suspect errors, it may be reported on instance
startup or further investigation of the underlying file system.

The Backup and Recovery section covers the movement of the tempdb datafiles.

Instance UPTIME
There is not specific function to get the uptime of your instance. Consider the query as the next
best thing:

select datediff(day, login_time, getdate()) as DaysUptime


from master..sysprocesses
where spid = 1

Or check your SQL Server Logs.

Re-creating & Auto-Starting Services


To view the configuration of services running (and therefore assist with re-creating them), run
regedit.exe and goto /HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services. There will be
one entry per service, drilling through to our SQL Server instance service we see:

Consider exporting this portion of the registry after installation.

To manually restart the SQL Server NT services, use the NET STOP/START command, for example:

NET STOP SQLSERVERAGENT


NET STOP MSSQLSERVER

NET START MSSQLSERVER


NET START SQLSERVERAGENT

257
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Put this in a batch file and schedule via NT’s AT command.

Raw Partitions
I hate raw partitions, they are difficult to use and are restrictive in terms of the underlying NT
commands (copy, move, delete etc are not possible) and backups you can perform. I also
question the real performance benefits you are getting and have yet to read any white paper that
justifies the associated management issues.

I am not covering raw partitions and ask you to spend more time with application performance
instead.

NOTE – Raw partitions are unavoidable in Oracle RAC.

SQL*Mail
The SQL*Mail service utilises a MAPI compliant client to send and receive email. The client is
typically Microsoft Outlook (not Outlook Express), and configuring “Mail” (profile) in control panel to
setup either an SMTP mail account or hook into Exchange.

MAPI SQL
Interface Server 2k
(xp_sendmail, sp_processmail,
xp_deletemail, xp_findnextmsg etc..)

I have had varied success with SQL*Mail, and at the end of the day, I opt not to use it, but have
written a small COM component (DLL) and a stored procedure to call a SMTP send email method.
There are numerous articles on the internet and at Microsoft for configuring sql*mail and not using
it at all. Have a good read before progressing any further.

NOTE – This may sound like a contradiction, but I have read a variety of forum posts from
DBA’s regarding the real need for a MAPI client. To get the low down from Microsoft check
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306962

Auto-growth and Space Management Tracking


Automatic data file growth

Automatic data and log file growth are default options via Enterprise Manager when creating a
database. The default growth is by 10% with an unrestricted maximum size.

Space Tracking

Space management tracking is simple enough. The core commands for tracking database space
usage are:

258
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

-- return log utilisation for all instance database

dbcc sqlperf(logspace) with no_infomsgs

-- get basic summary of database space usage

exec sp_spaceused

To encapsulate the DBCC command in a table for subsequent querying and historical tracking,
utilise the T-SQL command below:

create table #logsize


(db_name varchar(30) not null primary key clustered,
logsize float,
logused float,
status integer)

insert #logsize ( db_name, logsize, logused, status )


exec ('dbcc sqlperf(logspace) with no_infomsgs')

select * from #logsize

At an object level for each database, lookup a variety of sys tables and apply the following logic:

Reserved space (sysindexes) = sum(reserved) where indid in (0, 1, 255)


Data space used (sysindexes) = sum(dpages) where indid < 2 + sum(used) where indid = 255 (text)
Index space used (sysindexes) = sum(used) where indid in (0, 1, 255) - data
Unused (sysindexes) = sum(reserved) - sum(used) where indid in (0, 1, 255)

To get broad file growth data, do not forget master..sysfiles and DBCC SHOWFILESTATS.

Statistics and Histograms


When we select the cost based analyser in Oracle (which should be your only option), the DBA has
core responsibility of collecting statistics to ensure optimal and appropriate execution plan
generation. In SQL Server, cost based analysis is the only option for the optimiser and there is no
concept of rule-based optimisation.

Unlike Oracle, statistics collection is fully automated by default at the database level. This is
configured via the GUI or command line as shown below:

exec sp_dboption ‘mydb’, ‘auto create statistics’, ‘on’


exec sp_dboption ‘mydb’, ‘auto update statistics’, ‘on’

or via Enterprise Manager by selecting properties whilst selecting the database.

A statistics collection is synonymous with histograms in Oracle. This is different to physical indexes
which naturally have statistical properties (updated on the creation of the index and automatically
thereafter based on DB settings). Indexes and statistics collections are critical in enabling the
query optimiser to best determine the execution plan.

259
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

At the database level, the auto create statistics option is an interesting one. This tells SQL Server
to create a statistics collection (stored in the databases sysindexes table) for SQL predicates not
already indexed. For example:

CREATE TABLE [bb] ( The following statistics


[col1] [int] IDENTITY (1, 1) collection was created in
NOT NULL , sysindex on execution of the
[col2] [int] NULL , query: (name field in
[col3] [int] NULL , sysindexes)
CONSTRAINT [PK_bb] select *
PRIMARY KEY CLUSTERED from bb _WA_Sys_col2_29572725
([col1]) ON [PRIMARY] where col2 = 2
) ON [PRIMARY]
GO
select * from bb _WA_Sys_col3_29572725
where col2 = 2
and col3 = 2

Note that running exec sp_statistics ’bb’ will return a list of all indexes and statistics for our
table in the example. I personally find this procedure useless for statistic collections as you may
find with its output. Use exec sp_helpstats 'bb' to get a listing of statistics for the table, pass
this into dbcc show_statistics ('bb', '_WA_Sys_col2_29572725') for example to get a
further analysis of the collection. Note that the collection can be replaced with the index name of
the table if need be as we will see later.

NOTE – Statistics cannot be created for text, ntext and image column datatyes.

Both indexes and collections include histogram (distribution) statistical information in the statblob
column within the sysindexes column.

Throughout in this chapter we will cover both the autocreation and autoupdate statistics options,
along with analysing the statistical data collected.

Building and Maintaining Histograms


Within Oracle, the DBA can create histograms via the command:

EXECUTE DBMS_STATS.GATHER_TABLE_STATS
('myuser','mytable', METHOD_OPT => 'FOR COLUMNS SIZE 10 mycol');

Funny enough, Oracle state that histograms must be carefully chosen as they can impact
performance, and should, generally, only be used on columns with highly skewed data so as the
cost-based optimiser can make well formed decisions over uniformity of the data.

In SQL Server this thinking is somewhat different and statistics are used widely throughout the
database instances with little impact. These statistics (especially if auto-stats option is on) can
occur over uniformly distributed data for example and in most cases, seem to help the perhaps less
complex optimiser compared in SQL Server.

260
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

In Oracle, the histogram min/max values and distribution data is stored in “buckets” that the DBA
specifies. In SQL Server the histogram and associated density group is stored in the statblob
column that is an image blob datatype.

CREATE STATISTICS usrstat_mytable_col1


ON mytable (col1)
WITH FULLSCAN

The DBA can utilise the WITH NORECOMPUTE option to prevent SQL Server from subsequent
updates to the statistics. This is not recommended.

NOTE – A statistics collection is regarded as an index against the table although its not a
physically one, therefore, query sysindexes where locating statistic collections.

As the Oracle DBA will quickly realise, the SQL Server histogram is very simplistic when compared
to Oracle.

Import and Export Statistics


There is no ability to export or import statistics as found within Oracle. The DBA may find an
unsupported method, but there are no utilities, extended stored procedures or otherwise to
cater for this. Moving or copying a database will of course bring with it all statistics.

Re-collecting Statistics & Monitoring Auto-Statistics Collection


Updating Statistics

The DBA can manually update statistics via:

UPDATE STATISTICS mytable (col1) WITH SAMPLE 70 PERCENT


UPDATE STATISTICS mytable (col1) WITH RESAMPLE
UPDATE STATISTICS mytable (col1) WITH FULLSCAN

use mydb
exec master..sp_updatestats -- update statistics for all objects in mydb

Such statistical information can be recollected for the entire table or index, the DBA can also
selectively re-sample a specific index or collection within the object.

The DBA can also create a Database Maintenance Plan to schedule the update statistics of statistics.
Most DBA’s will opt for this as it’s simple and works very well. Those requiring finer control will use
a custom t-sql.

Monitoring Statistics

The most effective way to monitor the automatic updating of statistics is via Profiler. Select the
following (not definitive by any means but a good start):

Events Æ Objects, Auto-Stats


Data Columns Æ Event Class, Duration, Database ID, ObjectID, StartTime, EndTime, TextData

An example screen shot is shown below. The update runs asynchronously to the users execution of

261
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

the query. After some testing I still find it difficult to predict the actual logic being used, as a large
row count change doesn’t necessarily cause a stats update but different queries against the table
with different predicates does. Keep an eye on regularity, associated locking (if any) and its impact
on CPU time.

Here is an example output, use OBJECT_NAME to get the actual table name:

Controlling Stats Collection at the Object Level


The DBA can turn off statistics collection at the object level if need be. There may be a variety of
reasons why this is done, but it would be a rare occasion. On creation of an index the DBA can use
the option below:

CREATE UNIQUE CLUSTERED


INDEX [PK_mytab] ON [dbo].[mytab] ([col1], [col2])
WITH
FILLFACTOR = 90, STATISTICS_NORECOMPUTE
ON [PRIMARY]

CREATE STATISTICS mytab_stats


ON mytab (col3)
WITH
FULLSCAN, NORECOMPUTE

This option is available within Enterprise Manager when editing your indexes and statistic
collections. Be careful, as any manual or automatic statistic collection will skip these objects, which
can be a problem when debugging performance issue or strange execution plans.

Analysing Indexes & Histograms (collections)


The DBA can analyse the distribution statistics for indexes or via:

DBCC SHOW_STATISTICS (mytable, mytableindex)


-- sysadmin, db_owner or db_ddladmin fixed role users only

The command is very helpful when drilling down through and index to determine its selectivity and
subsequently its usefulness. Classic examples are comparing existing non-clustered (heap) and
clustered indexes to determine wether another index is better suited to range scans and therefore
clustering.

The results are divided into 4 sections,we discuss via an example:

DBCC SHOW_STATISTICS (address, ix_address_locality)

The core purpose of the command is to display information about index density. Providing the DBA
with an insight into the key distribution within the index, and therefore its selectivity.

262
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Updated length Rows Rows Sampled Steps Density Average key


-------------------- -------------------- -------------------- ------ ------------------------ --------------
May 12 2002 4:17PM 117798 117798 200 2.3193457E-4 12.565909

All density Average Length Columns


------------------------ ------------------------ ---------------------------------------------
1.0090817E-3 8.5659094 addr_locality
8.489108E-6 12.565909 addr_locality, addr_id

Use the formula all-density * rows = key selectivity to calculate wether the key combination is
highly selective. In the case above, we have a composite index over addr_locality and addr_id, we
are shown the two sets of figures for us to calculate the density for each combination of index
lookup. In this case the values are:

addr_locality = 118 rows (very poor)


addr_locality, addr_id = 9 rows (ok)

of course, perfect selectivity is a value of 1. This is still no substitute for a thorough understanding
of your applications demographics and associated indexing requirements, but is still a very good
guide.

The other columns are self-explanatory. The next part of the statistics shows the sampled
histogram, each representing a step. The columns of interest are:

a) range high key (upper value of histogram step)

b) eq rows (number of rows in sample with this value)

c) avg range rows (avg duplicate values within the step range)

RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS


----------------------- ------------------------ ------------------------ -------------------- --------------
AJANA 0.0 6.0 0 0.0
ALBANY 0.0 1574.0 0 0.0
ALEXANDER HEIGHTS 10.0 150.0 1 10.0
APPLECROSS 148.0 541.0 8 18.5
ARMADALE 219.0 853.0 3 73.0
ATTADALE 127.0 235.0 5 25.4
AUSTRALIND 179.0 218.0 2 89.5
BALCATTA 99.0 1364.0 6 14.142858
BALGA 123.0 199.0 1 123.0
BALLAJURA 51.0 457.0 3 17.0

I use a tool call Diagnostics Manager from NetIQ, a great management tool for drilling into such
statistics, here is a screen shot (versions will undoubtly differ):

263
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Please read the chapter on performance tuning and indexing issues to better understand and leaver
off the statistics presented above.

Synonyms
There are no synonyms in SQL Server, the best you can do is (perhaps) use views. In all
cases the owner of all user database objects should be dbo, then use roles to manage security.

Shrinking Database Files


The shrinking of database files is relatively common for SQL Server DBA’s. The DBA should keep
auto-growth parameters on for their database files but think carefully about the growth parameters
to reduce unnecessary IO and huge jumps in un-used space. Anyhow, back to shrinking; the first
option that should be turned off is the auto shrink database option (via EM, properties for the
database):

ALTER DATABASE pubs SET AUTO_SHRINK OFF

So long as the DBA understands the application(s) running against the database, its growth “spurt”
periods and that a database running with a full recovery model requires log backups to occur (or
your transaction log file will keep growing), then a nightly, weekly or monthly database shrink is
more than enough.

264
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Examples:

-- 2 is the % max free space after shrink


-- truncate free space only
DBCC shrinkdatabase(N'pubs', 2, TRUNCATEONLY )

-- will move pages to beginning before shrink


-- same as “compress and truncate”
DBCC shrinkdatabase(N'pubs')

-- shrink primary data file in current db (pubs) to 2Mb


DBCC SHRINKFILE (N'pubs', 2)

-- truncate free space only (no page movement)


DBCC SHRINKFILE (N'pubs',TRUNCATEONLY)

WARNING – If you shrink specific files, DO NOT press the OK button to close the shrink
database dialog, if you do, it will run a shrink database for the entire database.

Under the FILES option of the shrink dialog, the empty filegroup option also exists. This option only
works for a single filegroup that has multiple data files. As you know, if you create an object on a
specific filegroup, SQL Server will distribute the objects storage over the group’s database files.
The EMPTYFILE option will move (migrate) all data from the specified file to the other file sharing
the same filegroup.

-- DB_DATA2 is the logical file name for my DB_DATA filegroup, all object data is move from this
-- database file to DB_DATA1, therefore allowing me to drop DB_DATA2

DBCC SHRINKFILE (N'DB_DATA2',EMPTYFILE)

To track shrinking, consider the DBCC EXTENTINFO (‘mydb’) command as discussed in the
Microsoft Support document Q324432. This support document provides a great script for viewing
object space allocation and fragmentation. I have adapted the end-query a little to suit my needs:

-- To hold DBCC command data for further analysis


create table extentinfo
(
[file_id] smallint,
page_id int,
pg_alloc int,
ext_size tinyint,
obj_id int,
index_id tinyint,
pfs_bytes varbinary(10)
)

-- Stored proc to run DBCC


create procedure import_extentinfo as
dbcc extentinfo(‘pubs’)

265
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

go

-- Populate the table


insert extentinfo exec import_extentinfo
go

-- Show possible fragmentation and reduction possibilities (run shrink later and compare the results)
select
FILE_NAME([file_id]) as DBFile,
OBJECT_NAME(obj_id) as ObjectName,
case index_id when 1 then 'ClusteredIndex'
when 255 then 'Text/Image'
else 'NonClustered' end as IndexType,
ext_size as ExtentSize,
'actual extent count'=count(*),
'actual page count'=sum(pg_alloc),
'possible extent count'=ceiling(sum(pg_alloc)*1.0/ext_size),
'possible extents / actual extents' = (ceiling(sum(pg_alloc)*1.00/ext_size)*100.00) / count(*)
from
extentinfo
where
ext_size != 1
group by
[file_id],obj_id, index_id, ext_size

266
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL DMO
SQL Distributed Management Objects (SQL-DMO) is a COM layer whose relationship to the SQL
Server engine is such that it is an in-process OLE Server (in other words OLE automation
compatible COM objects). As such, it exposes many of the core methods for SQL Server object and
replication manipulation, both local and remotely.

NOTE – SQL DMO is fundamental to Enterprise Managers’ functionality. The DLL is called
sqldmo.dll. Select properties of the DLL via the OS to get its version information.

The object model is very thorough, and will cover close to all of your requirements for database
manipulation. A simple search of www.google.com will provide you with more than enough
examples to get started, especially for those experienced with VB.

The DBA and/or developer can use SQL-DMO in a variety of ways as shown below. An excellent
resource can be found at:

http://www.sqlservercentral.com/columnists/sjones/sqlserverdmoresources.asp

VB Example
Dim oServer As SQLDMO.SQLServer

' mixed mode login example..


Set oServer = New SQLDMO.SQLServer
oServer.Connect vServer, "sa", "theSApassword"

' trusted connection


Set oServer = New SQLDMO.SQLServer
With oServer
.LoginSecure = True
.Connect
End With

VB Script Example (.vbs)


Dim oSQLServer
Set oSQLServer = CreateObject(“SQLDMO.SQLServer”)
oSQLServer.LoginSecure = True
oSQLServer.Connect

set oBackup = CreateObject("SQLDMO.Backup")


oBackup.Database = “northwind”

oBackup.Files = “c:\nothwind.bak”
oBackup.Action = 0

oBackup.SQLBackup oSQLServer
Set oBackup = Nothing

oSQLServer.Disconnect
Set oSQLServer = Nothing

267
12
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL & T-SQL

T
hroughout this chapter we will discuss transact SQL (equivalent to PL/SQL) and common
SQL commands with examples. I will not give too many direct comparisons to Oracle but
will attempt to focus on providing you with good overall coverage to speed your
introduction to SQL Server.

PL/SQL (T-SQL)
The core programming language comparable to PL/SQL is T-SQL (Transact-SQL). This will change
in future releases of SQL Server when the .Net framework becomes embedded in the DBMS. The
affect of this is that any .net compatible language can use used instead of T-SQL.

The following sections summarise some of the core elements of T-SQL with comparisons with
Oracle as required.

[ ] = Optional code segment


{} = One or more mandatory options

Comments and Statement End


Both Oracle and SQL Server use the same strings for comments.

-- this is a single line quote

/*
this is a
multi-line quote
*/

You cannot nest multi-line quotes, attempting to do so will result in error. The single line
quote can appear anywhere on the line, although once started all values after it until a newline
will be regarded as comment text.

T-SQL statements do not require the ; or any other character to denote the end of the
statement. If used at the end of a DML statement the command will not error.

268
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Understanding GO
The GO statement defines the end of a batch of T-SQL, although itself is not a T-SQL statement.
Using profiler (discussed later), we can see the affect that the GO statement has on batch
submission of SQL and T-SQL statements to the relational engine:

use pubs
declare @aa integer
set @aa = 1
print 'this is a test'
print @aa
GO

use pubs
GO
declare @aa integer
set @aa = 1
GO
print 'this is a test'
print @aa
GO

Of course, each of the statements between the GO are compiled as a single execution plan.

Take care, variables are not persistent between batches, the above actually gives us an error for
the below code, as @@aa is not declared within the batch.

print 'this is a test'


print @aa

Be careful using the GO statement in stored T-SQL code, the GO statement will define the end of
the code block so if you went a placed GO statements all through your stored procedure for
example and saved it successfully to the database, you may find that the rest of the code is missing
after the first GO statement. The entire stored procedure / UDF is a single block of code and you
cannot change this via GO’s.

269
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Block Structure
The Oracle block structure for functions, procedures, and anonymous blocks consists of the
format:

ORACLE SQL Server

[declare [begin]
-- variable declarations] -- declaration and body code can be
begin -- anywhere after the declaration
-- body code and other statements -- of the procedure/function/trigger
[exception -- there is no enforced syntax
-- handler code]
end; [end]
[GO]

It should be noted that although optional in this particular case, the BEGIN and END statement is
used to define a logical block. The begin/end combinations are mandatory for multi-line control
statements (2 or more lines, i.e. IF, loops) as we will see later. The begin cant be used without the
end statement.

The BEGIN and END statements do not affect a variables scope.

Declarations / Local Variables / Constants


The T-SQL variable or parameter must include the prefixed @ symbol to be valid. All
declaration require the DECLARE statement.

myvariable NUMBER; DECLARE @myvariable INT

You can declare multiple variables of the one DECLARE statement, for example:

DECLARE @myvariable INT, @mysecondvar CHAR(1)

You cannot set default (initial) values for the local variables:
DECLARE @error_count INTEGER = 0

Server: Msg 139, Level 15, State 1, Procedure myproc, Line 3


Cannot assign a default value to a local variable.

You cannot use all variable types for local variables:

Server: Msg 2739, Level 16, State 1, Procedure myproc, Line 3


The text, ntext, and image data types are invalid for local variables.

SQL Server T-SQL has no concept of constants, they are only string literals or other fixed values,
like 10, ‘Hello’ etc in code that is it.

Take care with declarations. If you do not initialise the variable the default value is NULL. This will
create adverse problems, for example:

270
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

DECLARE @error_count INTEGER


print @error_count + 1 -- will return NULL
set @error_count = 0 -- initialise first (basic good practice)
print @error_count + 1 -- will return 1

The BEGIN and END statements do not affect a variables scope. Therefore, once a variable is
declared ALL code below it (within the same batch of course, see the section on GO) can refer
to it. Nested calls to other stored procedures or UDF’s cannot use the variables declared.

Assigning values to variables & Create Table as


Oracle SQL Server
myvariable := 10; set @myvariable = 10
SELECT MAX(id) set @myvariable = (SELECT MAX(id)
INTO @myvariable FROM mytable)
FROM mytable;
select @myvariable = 10

SQL Server does support the INTO clause, but this is the same as the CREATE TABLE AS
<select-statement> clause in Oracle. The syntax is also a little back to front, for example:

-- create a new table mynewtable based on myexistingtable with all data


SELECT * INTO mynewtale FROM myexistingtable
-- as above but no data copied
SELECT * INTO mynewtale FROM myexistingtable WHERE 0 = 1

This is a bulk/insert command. The new table will not inherit:


a) primary or foreign keys
b) triggers
c) column formula and default properties
d) indexes
e) file-group, the table will be placed into the PRIMARY filegroup of the database
f) role level permissions and directly allocated user permissions

It will inherit:
a) identity property
b) table structure

271
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Exception Handling (error handling)


There is no exception handling in T-SQL, therefore it can be close to impossible to re-direct runtime
errors or other exceptions to custom written code blocks, or cascade up an error through nested
calls. The best we have is shown via examples below. In many cases we will use the optional
BEGIN/END statement.

NOTE – Remember, stored procedures can utilise the RETURN statement to stop code
execution at the point of the RETURN, it is not restricted to user-defined functions.
-- Example 1

<any DML statement here>


IF @@ERROR <> 0
BEGIN
PRINT “An error occurred with the previous statement”
END

-- Example 2

DECLARE @error_count INTEGER

<any DML statement here>


set @error_count = @error_count + @@ERROR
<any DML statement here>
set @error_count = @error_count + @@ERROR

IF @error_count <> 0
BEGIN
PRINT “An error occurred with the a range of statements”
END

-- Example 3

IF @@ERROR <> 0
BEGIN
RAISERROR (20067, 16, -1, ‘Critical Error’)
RETURN (1)
END

-- Example 4

IF @@ERROR <> 0
BEGIN
GOTO CriticalError
END
<other code>
RETURN 0 -- skip over labels below

CriticalError: -- place labels at the end of your stored procs for ease of maintainability
PRINT ‘Critical error message’
Rollback Transaction -- optional of course, implementation specific
RETURN 1

272
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

-- Example 5

declare @RowCount int, @ErrValue int


<DML statement>
select @RowCount = @@ROWCOUNT, @ErrValue = @@ERROR
IF @ErrValue <> 0
GOTO CriticalError
RETURN 0

CriticalError:
BEGIN
IF @@trancount <> 0
ROLLBACK TRAN

raiserror @ErrValue

set nocount off


RETURN @ErrValue
END

NOTE – Apparently the next version of SQL Server will bring with it exception handling for T-
SQL, similar to that used in VB.

If you have issues with checking @@ERROR directly in an IF statement, then immediately after the
command you are verifying, assign @@ERROR to a variable and use this for checking. Be warned
that not checking @@ERROR immediately and executing other statements may affect the value
returned from @@ERROR.

RAISEERROR and Error Messages


It is worth explaining raiserror and error messages in more detail. Within the master database we
have the table sysmessages, which includes over 3782 predefined error and warning messages of
varying severity.

select * from master..sysmessages

By passing in @@ERROR, we can translate and appropriate error code into its equivalent severity
and description. The severity levels are:

Severity Level RAISEERROR Summary


0 to 19 0 to 18 can be used 1 to 9 = warning and process errors
by any user. 19 to 10 = Status
25 require the NO 11 to 16 = warning errors
LOG. 17 = out of resource error
18 = non-fatal internal error
19 = internal sql setting exceeded
20 to 25 sysadmin users only. Fatal system error.

We can maintain our own user-defined messages via the following stored procedures in the master
database:

273
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ sp_addmessage

ƒ sp_dropmessage

ƒ sp_altermessage

Example:
exec master..sp_addmessage 50006, 16, 'My Error parameter 1:%d, parameter 2: %s.'
RAISERROR (50006, 16, 1, 100, 'MyTest')

Server: Msg 50006, Level 16, State 1, Line 1


My Error parameter 1:100, parameter 2: MyTest.

NOTE - Be warned though in stored procedures, if you were planning on using raiserror to
stop processing immediately you may be surprised, a classic example are foreign key errors
on an insert or update and the stored procedure continues to run. Always force the exit on
error via a RETURN statement and rollback otherwise the non-fatal error will be shown and the
code execution continues.

We can also log user–defined error messages to the SQL Server log and Windows NT event log
via the extended stored procedure xp_logevent.

Non-SQL Output
Calling DBCC commands and other system stored procedures (xp_ or sp_) , typically requires the
encapsulation of the result set into a temporary or static table for further manipulation. This
practice may also required when calling the stored procedure and returning the results to a record-
set from a VB or other application.

DECLARE @ExecStr varchar(50), @Qry nvarchar(255)

-- create the tempory table (stored in tempdb), also consider the TABLE datatype
CREATE TABLE #inputbuffer
(
EventType nvarchar(30),
Parameters int,
EventInfo nvarchar(255)
)

SET @ExecStr = 'DBCC INPUTBUFFER(' + STR(@@SPID) + ')'

INSERT INTO #inputbuffer


EXEC (@ExecStr)

SELECT EventInfo
FROM #inputbuffer

Take care with the EXEC[UTE] statement, which may result in the error:

Server: Msg 197, Level 15, State 1, Procedure mytest, Line 16


EXECUTE cannot be used as a source when inserting into a table variable.

This is a real pain for the new data type of TABLE.

274
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Cursors

As in Oracle, the cursor is pretty well standard for the modern DBMS. In terms of T-SQL, the
cursor type and associated command set has a large number of options that is better covered in
the books online.

A very basic example is show below, you will probably use this example in a majority of cases for
simple record processing:

Use PUBS
GO

DECLARE @empid varchar(20), @fname varchar(50)

DECLARE mycursor CURSOR FOR -- note the missing @ operator!


SELECT emp_id, fname
FROM employee

OPEN mycursor

FETCH NEXT FROM mycursor INTO @empid, @fname

WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @empid + ' : ' + @fname

FETCH NEXT FROM mycursor INTO @empid, @fname


END

CLOSE mycursor
DEALLOCATE mycursor

You will see this per FETCH NEXT statement:

If we altered data after the OPEN statement, the record will be reflected in the cursor. The cursor in
this particular case does not pre-fetch the data (as the plan shows above). Read carefully in the
books online about other options such as INSENSITIVE, STATIC and KEYSET that may change this,
for example, an INSENSITIVE cursor sees a single operation generated for the whole statement
rather than one for each fetch.

275
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

In the CURSOR example above, we see the following locks:

Those cursor options that utilise the TEMPDB are not recommended (see STATIC cursors next
though for an example where its required). On top of this, don’t use options where you update
through the cursor, use a standard SQL update/delete command. A simple test with the above
statement and the SCROLL option for example:

DECLARE mycursor SCROLL CURSOR FOR


SELECT emp_id, fname
FROM employee

Build the cursor


temporary table

Scan internal table


and return row set.

This sees the appropriate locks taken out on the new tempdb object and an increase in turn-around
time of about 30%, not great on the already slow standard (dynamic) cursor.

In the discussions above, I have made a point of highlighting locking. One of the big issues with
SQL Server performance is locking and blocking. Be very careful with cursors, especially options
such as SCROLL_LOCKS. Unintended locking and the flow on effects in terms of overall
performance and time spent tracing the problem is something you would rather avoid than deal
with later.

So long as you close and deallocate, there is no reason why you cant alter the cursors SQL
statement, open and continue with your new set of work. Failure to deallocate will result in the
error:

Server: Msg 16915, Level 16, State 1, Line 4


A cursor with the name 'mycursor' already exists.

276
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Be aware that many SET operations (such as setting dateformat) will result in error if a cursor has
been declared before it:

Server: Msg 16958, Level 16, State 1, Line 9


Could not complete cursor operation because the set options have changed since the cursor was declared.
Server: Msg 16917, Level 16, State 2, Line 11
Cursor is not open.

NOTE – Always opt for a bunch of DML statements if you can to do a bulk of the work.
Adversely, be careful trying out to completely “code out” cursors all together, depending on
the code, you may find a WHILE loop with multiple DML statements even slower ! test
carefully.

In terms of cursor functions, the equivalents between Oracle and SQL Server are:

Oracle SQL Server


%FOUND @@FETCH_STATUS
%NOTFOUND @@FETCH_STATUS
%ROWCOUNT @@CURSOR_ROWS
%ISOPEN @@CURSOR_ROWS - value of zero

STATIC Cursors

The DBA should spend some time reading up on the types of cursor. By default, all cursors are
dynamic, this means that each FETCH will retrieve the value from the database “as is”, not from
when the cursor was first opened. A classic example of where this can be a problem is when your
cursor SQL statement is using a not exists or not in clause. If on a fetch of one record, you alter
the data in the table that effectively cancels out the not exists/not in for subsequent records, then
unless you used s STATIC cursor, the next fetch may return no records. If you are experience this
sort of problem, consider STATIC cursors that pre-fetch the data into a temporary table.

UTL_FILE (File IO)


In SQL Server’s native T-SQL language, there is no native stored procedure or extended stored
procedures for file input/output. This will of course change with the release of .Net SQL Server
(possibly called Yukon). Alternatively, we can:

a) write an extended stored procedure in C++ or VB


b) use the sp_OA* stored procedures in the master database to call out to a COM
c) write a DTS and create an active-x step that utilises vb-script to call FSO (file-system
objects)
d) call out to the OS via xp_cmdshell
a. possibly using bcp.exe to dump data from table or view we have created
e) utilised a linked server (read only)

this is far from complete but gives you some ideas.

277
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The linked server e) above is an interesting one. In the SQL Server Magazine, June 2002, Brian
Moran showed that utilising sp_addlinkedserver, you could subsequently query an external file (this
is also in the BOL). Here is an example:

exec sp_addlinkedserver textfile, 'Jet 4.0', 'Microsoft.Jet.OLEDB.4.0', 'c:\', null, 'Text'

select count(*) from textfile...[cktest#txt] -- get line count, file is c:\cktest.txt


select * from textfile...[cktest#txt] -- get the data (first line assumes to be the column header in
-- query analyser
exec sp_dropserver txtsrv

Procedures/Functions/Packages
Lets be honest here, T-SQL is the poor mans PL/SQL and probably always will be. This of course
will all change when SQL Server Yukon is released and the power of VB, C++ and over 20+ other
languages that are embedded in the .Net framework, enter the SQL Server DBMS. Anyhow, back
to the topic, all we have in terms of code blocks in SQL Server are:

ƒ User Defined Functions (UDF)

ƒ Stored Procedures

ƒ System stored procedures

ƒ Extended stored procedures (wrappers to operating system DLL’s in master DB)

ƒ User defined stored procedures

There are no T-SQL packages or concepts of private and public routines (control security via roles),
so like I said, it’s the poor mans PL/SQL.

User Defined Functions (UDF)

As an Oracle DBA you will probably be surprised that the UDF is a new feature to SQL Server, I
would have thought this was a fundamental but apparently not. Anyhow, the concept and code is
very easy and there is no rocket science to it.

Basic Syntax

CREATE FUNCTION [owner.]function-name ([zero or more parameters])


RETURNS [data-type]
AS
[BEGIN]
[optional declarations]
[{other code}]

RETURN ([value or a select statement])


[END]
GO

Example

-- in this example, the begin and end must be removed


-- the columns returned must be named

278
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

CREATE FUNCTION mytest()


RETURNS table
AS
RETURN (select 'hello' as col1)
GO

Some examples when using the functions:

print myfunction(1)

select myfunction(col1) as newcol1, col2, col3 from mytable

create table mytable


(col1 int, col2 as (myfunction())) -- col2’s data type is that of the return value for the function.

There are a variety of issues to be aware of with functions:

a) cannot be indexed

b) must be deterministic

c) concerned with speed? I am, test this very carefully as even a stub call results in some
interesting speed issues.

d) cannot call extended stored procedures that return data directly from the function (must
encapsulate the returned data into a temporary table first)

e) has many restrictions, such as not being able to call dynamic SQL inside it, or creating
temporary tables, eg:
Server: Msg 2772, Level 16, State 1, Procedure mytest, Line 5
Cannot access temporary tables from within a function.

User defined Stored Procedures

The stored procedure is very common amongst SQL Server developers, and true for Oracle
database applications as well (but typically encapsulated in packages). The stored procedure is
the key for enhanced system performance and maintenance of DML that would otherwise be in the
COM+ tier (business layer).

Like UDF’s, the BOL provides thorough coverage of the syntax of the procedure. There are few
restrictions in the stored procedure unlike the UDF, and are relatively simple to implement and call
via VB. The basic syntax is:

create procedure [owner.]procedure-name [parameter-name datatype[,…]]


as
set nocount on -- stops INPROC returns, see performance tuning chapter

[all declarations here]

{procedure code}
go

By default all parameters are IN only (read-only), unless the OUTPUT clause is used, for example:

279
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

create procedure dbo.checkuser @username varchar(30), @isvalid INT OUTPUT


as
<etc>
go

Like variables, all parameters must include the prefixed @ symbol. To specify a default value for
parameters, use the syntax:

create procedure dbo.checkuser @username varchar(30), @isvalid INT = 0 OUTPUT


as
<etc>
go

Like the UDF, the stored procedure can return values, but only integers via the statement RETURN
[value].

The DBA can encrypt procedures (and functions) via the WITH ENCRYPTION option. This uses an
internal encryption routine and is further covered in the security chapter. This makes the
syscomments text column unreadable. Be warned that encrypted routines require script change
management as they can not be scripted from EM.

Finally, the last option worth mentioning is WITH RECOMPILE. This causes the recompilation of the
execution plan every time it is called. This is not normal practise and should be carefully
considered before using the option. To trace the recompilation, check for the event SP:CacheMiss,
this is the only indication followed by the SP:Starting (being the actual routine being called). These
events are found under the stored procedure group of events. An example trace:

I have had mixed success with the SP:Recompile event and I wouldn’t recommend it for tracing
recompiles.

Versioning Stored Procedures

It is possible to version procedures via:

create procedure mytest;1 as


{code}
go

To call, you must include ;1, therefore, it’s not really. You cannot overload stored procedures or
functions, which is another pain to deal with.

Security & Ownership Issues

The DBA can grant create procedure or function access at the database level for which the user is a
member of; but cannot deny/grant the alter statement. By default, unless the user is part of
db_owner or ddl_admin database fixed roles, the user can not create or alter objects owned by
different users (such as DBO).

280
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

It is very important that ALL objects in a database are owned by the dbo user before moving into
production. During development, the DBA should let the developers (using defined logins), create
procedures, functions and views freely. The DBA can then alter the owner via
sp_changeobjectowner to dbo and allocate privileges via database roles, moving the routines
through to test and then into production.

When creating procedures and functions, avoid explicitly prefixing the owner, eg:

create procedure myuser.mystoredproc <etc>

Doing so can be a nightmare for ongoing administration, where the textual definition of the
function/procedure is different to that defined in separate columns within sysobjects. The flow on
effect is that EM shows a procedure as owned by dbo for example, but when editing the procedure,
the create procedure statement has a different (original) user! not good when you rely on object
scripting to move between servers as the script will have the wrong user.

While all this is fine, there can be recompile and compile lock issues not prefixing calls to routines
with the owners name. I am not convinced this is a problem in terms of performance.

We cover these and other issues in the chapter on security.

Calling External Applications (command shell)


In the master database we have the extended stored procedure xp_cmdshell. This allows us to call
out to any operating system command (executable, batch file etc). As such, this can be a major
security risk that needs to be carefully controlled by the DBA.

Assuming that userA in their database userdb, wanted to use xp_cmdshell to compress some
files in some predefined directory. The programmer, of course, has a variety of methods but
in this particular case must use a T-SQL stored procedure call. To give the user access to
xp_cmdshell we:
a) Run Enterprise Manager and connect to the instance
b) Goto the user folder for the master database and chose the add user option
a. Make userA a user of the master database
b. Grant execute permission to xp_cmdshell for the user
i. Optionally use a role rather than granting the privilege direct

The user can then run:

exec master..xp_cmdshell ‘c:\scripts\gzip.exe *.dat’

By default, sysadmin users have xp_cmdshell execute access, and auto-proxies to the user running
the instance. For everyone else, you may need to set the "sqlagent" proxy via:

-- what the proxy is set at currently


EXEC master.dbo.xp_sqlagent_proxy_account N'GET'

-- setup the proxy


EXEC master.dbo.xp_sqlagent_proxy_account N'SET',
N'MYNTYDOMAIN', -- windows domain of NT user
N'SQLServer', -- agent NT username

281
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

N'password' -- agent NT password

Remember, this is completely different from the service account in which SQL*Agent is running,
selecting its properties via Enterprise Manager does not reflect the change above. Only setting this
if you are presented with a SQL error related to the SQL*Agent proxy account ("error at line
140 in xp_shell.cpp, no proxy").

A way to deal with security is to encapsulate the calls to xp_cmdshell in another stored
procedure that users are granted access to via the same paradigm mentioned above. Within
this we can audit user activity, encapsulate further validation to prevent certain actions from
occurring etc. In this way we only grant access to the wrappered stored procedure and not
xp_cmdshell direct.

exec master..RunOsCommand Create procedure RunOsCommand


‘gzip.exe c:\*.dat’ @cmdstring nvarchar(255) as

-- <do some auditing here>


exec master..xp_cmdshell @cmdstring
-- <return error messages etc>

GO

Granted execute privileges to


custom wrapped procedure. xp_cmdshell call

sysadmin system privilege


or
if non-sysadmin, will run via the proxy
account setup in SQL*Agent configuration.

DBMS_SQL
Please read the section on Dynamic SQL.

DBMS_RANDOM
In Oracle, the PL/SQL developer can use the DBMS_RAMDON package to generate random
numbers. This is installed via:
• utlraw.sql
• prvtrawb.plb
• dbmsoctk.sql
• prvtoctk.plb
• dbmsrand.sql
• or review $ORACLE_HOME/rdbms/admin/catoctk.sql.

To generate random numbers in SQL Server we use the pseudo-random number generator
function RAND with a optional single parameter being the seed.

select rand()

282
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

As described in the SQL Server documentation, if you decide to specify a seed, then consider
utilising getdate() to assist with randomising the seed. A fixed value will return the same
random value every time (of course).

DBMS_OUTPUT
The DBMS_OUTPUT package allows the DBA to write out messages to the console (i.e.
SQL*Plus etc) whilst our stored procedure or other PL/SQL code executes. This is typically
used when debugging large routines, tracking progress or even for character based reporting.

Out of all the procedure calls you can make with the DBMS_OUTPUT package, the only
equivalent in SQL Server is the print command. Which is not necessarily a bad thing.

Example:

CREATE PROCEDURE exampleofprint AS


print '===== This is an example ===='
print 'The time is ' + cast(getdate() as varchar)
GO

Each single print command has a maximum of 8000 characters. Also note that print does not
work in triggers.

DBMS_MAIL, UTL_SMTP
Within Oracle we can utilise the DBMS_MAIL package, or the UTL_SMTP package for sending
emails via a PL/SQL stored procedure. In SQL Server we can:
a) use SQL*Mail via a MAPI compliant emailer
b) write our own DLL and call out to it via the sp_OA procedures in the master database

Search contents page for SQL Mail.

DBMS_AQ

No packaged routines exist in SQL Server for queuing. Search on the web for MSMQ for more
information. The DBA can easily call its API if need be or talk to an MSMQ within the DTS pre-
packaged active-x controls for MSMQ.

PSP, PL/SQL Web Toolkit

There is no equivalent to the PSP and/or the PL/SQL web toolkit. The best we have is SQL Server
returning XML directly from a SQL statement (FOR XML clause). The MS development tools have
this area very well covered.

DBMS_METADATA
I rarely see DBA’s utilising this package in Oracle as most use their own custom scripts (many
sourced from web-sites) and typically provide all they require. Even so, this package provides high

283
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

level meta-data about the underlying database schemas rather than utilising the sys objects. In
SQL Server, we have a similar built-in) meta-data views called the information schema.

Listed below are a variety of information schema views available. The list is far from
comprehensive but does provide a general guide.

Information Schema Column Summary


information_schema.tables Catalog (database), Owner, Object name, Object type
(includes views)
information_schema.views Catalog (database), Owner, Object name, View Source
(if not encrypted), Check Option?, Is Updatable?
information_schema.columns Catalog (database), Owner, Table name, Col Name, Col
Position, Col Default, Is Nullable, Data Type, Char Min
Len, Char Octal Len, Numeric Prec <etc>
information_schema.schema Database Name, Schema Name, Schema Owner, Def
Char Set Catalog, Def Char Set Schema, Def Char Set
Name
information_schema.referential_constraints Catalog (database), Owner, Constraint Name, Unique
Constraint Database, Unique Constraint Owner, Unique
Constraint Name, Update Rule, Delete Rule

There are no special security restrictions for the views and they are accessible through the public
role. Be aware though that the schema views will only return data in which the user has access
too. This is determined within the views themselves via the permissions() function.

To view the code of any of the views:

use master
exec sp_helptext 'information_schema.Referential_Constraints'

For further examples see reference (44) for great coverage.

DBMS_JOB
The equivalent to DBMS_JOB for the scheduling of T-SQL stored procedures, is to use the
following MSDB stored procedures:
a) sp_add_job -- add defined job to be run by SQL Agent
b) sp_add_jobschedule -- creates a schedule for a job
c) sp_add_jobserver -- sets target server to run the job
d) sp_add_jobstep -- add step to the job (some work to be performed)
e) sp_update_job -- change job properties
f) sp_update_jobstep -- change job step properties
g) sp_update_schedule -- alter execution schedule for job
h) sp_delete_job -- remove job
i) sp_help_job -- get metadata about job
j) sp_help_jobhistory -- get execution history
k) sp_help_jobschedule -- get metadata about job schedule
l) sp_help_jobserver -- get metadata about job server
m) sp_help_jobstep -- get metadata about the job step
n) sp_add_category (optional) -- categorises the job
o) sp_update_category -- alter categorisation

284
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

These of course map to a range of MSDB system tables, the data model of which is shown
below:

sysjobservers sysjobs sysjobsteps


(+multi-server jobs)

sysservers
(linked servers) sysjobschedules sysjobhistory

An example of checking the existence, then scheduling a job is shown below. Remember that
the SQL*Agent service is responsible for the running on the job.

DECLARE @JobID BINARY(16)


DECLARE @ReturnCode INTEGER

-- get the ID of our custom job


SELECT @JobID = (select job_id FROM msdb.dbo.sysjobs WHERE (name = N'my custom job'))

IF @JobID IS NOT NULL


BEGIN
EXECUTE msdb.dbo.sp_delete_job @job_name = N'my custom job'
set @JobID = null
END

BEGIN
-- add the job

EXECUTE @ReturnCode = msdb.dbo.sp_add_job


@job_id = @JobID OUTPUT ,
@job_name = N'my custom job',
@owner_login_name = N'sa',
@description = N'our custom job example',
@enabled = 1,
@notify_level_eventlog = 2, -- log NT event on failure
@delete_level= 0 -- never delete, 2 means delete on failure, 1 is delete on success

IF (@@ERROR <> 0 OR @ReturnCode <> 0)


GOTO JobError

-- job step #1

EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep


@job_id = @JobID,
@step_id = 1, -- first step, dont use zero
@step_name = N'step 1',
@command = N'exec OurStoredProc_sp',
@database_name = N'pubs',
@database_user_name = N'', -- db user account to use when running step
@subsystem = N'TSQL', -- default
@cmdexec_success_code = 0, -- if OurStoredProc_sp returns 0 then OK
@retry_attempts = 1, -- 1 retry
@retry_interval = 1, -- wait 1 minute

285
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

@on_success_step_id = 0, -- default is zero


@on_success_action = 1, -- quit with success, 3 is goto next step
@on_fail_step_id = 0, -- default is zero
@on_fail_action = 2 -- quit with failure

IF (@@ERROR <> 0 OR @ReturnCode <> 0)


GOTO JobError

EXECUTE @ReturnCode = msdb.dbo.sp_update_job


@job_id = @JobID,
@start_step_id = 1 -- ensure step 1 is what we start off with

IF (@@ERROR <> 0 OR @ReturnCode <> 0)


GOTO JobError

-- schedule the job

EXECUTE @ReturnCode = msdb.dbo.sp_add_jobschedule


@job_id = @JobID,
@name = N'our example job',
@enabled = 1, -- enable it
@freq_type = 4, -- daily
@active_start_date = 20020713, -- 13 July 2002 start date
@active_start_time = 210000, -- 9pm
@freq_interval = 4, -- daily
@freq_subday_type = 1 -- run at set time
IF (@@ERROR <> 0 OR @ReturnCode <> 0)
GOTO JobError

-- Add the server to run job against

EXECUTE @ReturnCode = msdb.dbo.sp_add_jobserver


@job_id = @JobID,
@server_name = N'(local)'

IF (@@ERROR <> 0 OR @ReturnCode <> 0)


GOTO JobError
END

RETURN
JobError:
PRINT ‘Error with our job example’

286
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Here is a screen shot from Enterprise Manager regarding the scheduled job.

DBMS_LOB

There are no built-in routines similar to DBMS_LOB. The SQL Server binary objects have a variety
of restrictions in terms of SQL (cannot check equality in a SQL statement without using LIKE, T-SQL
does not support TEXT datatypes etc). See the help of your associated language about
reading/writing to SQL Server for more information about dealing with LOB’s.

BFILE
There is no equivalent option to the BFILE type in SQL Server.

Tables

The syntax of Oracle and SQL Server for table creation and alteration is significantly different,
primarily due to the large number of additional options included for space and concurrently
management in Oracle. The syntax itself for SQL Server is simplistic and requires no explanation
that cannot be covered in the books online.

The only syntax option worth mentioning is the FILEGROUP clause:

CREATE TABLE mytable


(col1 integer)
ON MYDB_DATA -- where MYDB_DATA is the filegroup name for the database

287
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The only issue here is when the table has a clustered index, where will the table reside? your index
or data filegroup?

When creating constraints (primary keys, foreign keys, defaults, unique, check), the DBA should
explicitly name them. The system generated name can create issues with scripting and make meta
data close to meaningless.

Finally, when querying sysobjects for user tables, consider the SQL statement:

select o.name as "Table",i.rows as "#rows"


from sysobjects o, sysindexes i
where i.id = o.id
and indid in(0,1)
and o.type = 'U'
and o.name <> 'dtproperties'
order by
o.name

User Defined (Inline) Functions

The user defined function is similar to that of Oracle in the respect that they are what they say they
are. Even so, in SQL Server we support:

a) Scalar functions – return a scalar data type (singular), such as INT, FLOAT etc.

b) in-line table functions – returns type TABLE, used when the function contains a single SELECT
statement for example, eg. RETURN(<select-statement>)

c) multi-statement table functions – as above but can contain a variety of other statements are we
explicitly define the structure of the returning table.

The function returning a table can be utilised in standard SQL statements such as:

select A.*
from dbo.myfunction() as A
-- can also be used in WHERE, HAVING, GROUP BY clauses

The DBA should be aware of the following UDF restrictions:

• restricted use of many non-deterministic functions (i.e. cannot use - getdate(), RAND etc).

• cannot use temporary tables, can declare table datatype though (cant index table types
although you can declare a primary key that will create an index anyhow, table types are
also not considered part of a transaction).

• cannot be used in a FOR XML clause

• does not support OUTPUT parameters

• if calling an extended stored procedure, it must not return a result set to the client that
cannot be captured by the trigger code.

288
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The UDF will support recursion.

Indexes

The performance and tuning chapter covers indexes. In broad terms, the indexing schemes in SQL
Server are very simple with few equivalents to Oracle:

Oracle SQL Server Equivalent


Function Based Index Indexed Views
Bitmap Index None
Reverse Key Index None
Partition Indexing No concept of partitions
Clustered Index None
Non-clustered index Heap (non-clustered index)
R-Tree indexing None (no equivalent or Oracle
Spatial in SQL Server)
Compress option for indexes None
ONLINE and OFFLINE indexes None
VALIDATE STRUCTURE option DBCC commands
Index organised table Clustered Index

Sequences
In SQL Server, the sequence is called an identity. There are no similarities what so ever
between sequences in Oracle and identities as we will explore throughout this section.

In Oracle, the sequence is a separate data structure in which the developer or DBA can select
unique values from within PL/SQL code or DML statement. When given the privilege, many
database users can concurrently select unique values from the sequence and as such, can service
more than one database object. The Oracle sequence is much more feature rich as shown below:

Oracle parameter SQL Server equivalent


Increment by Increment
Start with Seed
Maxvalue <based on datatype maximum>
Nomaxvalue N/A
Minvalue <based on datatype maximum>
Nominvalue N/A
Cycle N/A
Nocycle N/A
Cache N/A
Nocache N/A
Order N/A
Noorder N/A

The first key difference is that a sequence in SQL Server is not its own database object as in
Oracle. The identity is an extended property of a table column, and only one column can
enable it. The valid data types for the column to include the identity property include tinyint,
smallint, int,and bigint, therefore defining the maximum and minimum values for the column.
Here is an example:

289
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

CREATE TABLE dbo.MyTable


(
col1 int NOT NULL IDENTITY (1, 1) PRIMARY KEY,
col2 char(10) NULL
) ON [PRIMARY]
GO

NOTE – The column using the identity property does not need to be a primary key but must
be non-nullable.

The DBMS will automatically populate the columns value, the programmer does not code a
trigger or use the .NEXTVAL or .CURRVAL clauses as in Oracle to populate the tables column.
When inserting data into the table, we simply do not specify the column in which the identity
property has been applied and the DBMS will do the rest, ensuring a unique value is inserted.

We can retrieve the identity value inserted using a couple of methods:

SELECT @@IDENTITY
SELECT SCOPE_IDENTITY()

The difference is very important as shown in the example below:

CREATE TABLE [mytab] (


[col1] [int] IDENTITY (1, 1) NOT NULL primary key,
[col2] [char] (10) NULL
) ON [PRIMARY]
GO

CREATE TABLE [mytabaudit] (


[auditid] [int] IDENTITY (100, 1) NOT NULL primary key,
[col1] [int] NOT NULL ,
[col2] [char] (10) NULL
) ON [PRIMARY]
GO

CREATE TRIGGER [auditinsert] ON [dbo].[mytab]


FOR INSERT
AS
insert into dbo.mytabaudit (col1, col2)
select col1, col2 from inserted
GO

-- at this point, the trigger will audit insertions into mytab into the mytabaudit table
insert into mytab (col2) values ('A')

select @@IDENTITY value is 100


select SCOPE_IDENTITY() value is 1

As you can see, scope is vitally important to ensure consistency and data accuracy.

290
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The DBA can reseed, check the current value or reset the identity column value as need be via the
command:

dbcc checkident (<table-name> [, NORESEED | RESEED [, <newvalue>]])

eg: DBCC CHECKIDENT ('mytable’, RESEED, 1)

NOTE – DO NOT assume that re-seeding will force SQL Server to magically “fill in” skipped
sequences. If for example you had a table whose primary key is an identity, and you
removed record 4 and then decided to re-seed back to 3, the new insert will do as you wanted
to insert the new record with identity value 4. Unfortunately for you the next insert will fail
with a primary key error as 5 is already taken.

This command requires sysadmin or db_owner or db_ddladmin privileges. To view the current seed
value for a table, use:

SELECT IDENT_SEED(‘mytab’)

or use EM.

To override SQL Server and force your own value into the column with the identity property set,
you need to use the SET IDENTITY command before and after the insertion. For example:

SET IDENTITY_INSERT mytab ON


insert into mytab (col1, col2) values (122, 'Hello')
SET IDENTITY_INSERT mytab OFF

You MUST specify the column list for the insertion to work. SQL Server will continue on from the
value you inserted, in this case 123. This option can only be set for one table at a time for the
current session at any one time.

Finally, there is a function called IDENTITY that can be utilised in SQL statements to generate 1 or
more seeded sequence values from an initial seed and increment. Its very restrictive though as it
can only be used when creating new tables via a SQL statement (create table as in Oracle). Here is
an example:

select col2, identity(smallint, 1, 2) as newcol


into newtab
from mytab

If you try and use the SQL statement only without INTO, you will get:

Server: Msg 177, Level 15, State 1, Line 2


The IDENTITY function can only be used when the SELECT statement has an INTO clause.

To find all tables utilising the identity property, try this SQL statement:

SELECT
u.[name] AS Owner,

291
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

o.[name] AS [Table],
c.[name] AS [Column]
FROM
syscolumns c
INNER JOIN sysobjects o ON o.Id = c.Id
INNER JOIN sysusers u ON o.uid = u.uid
WHERE
c.status & 128 = 128 -- apply bitmap mask for identity property

What about UNIQUE IDENTIFIER?


Another option over IDENTITY is to use the unique identifier data type, which is actually stored
as a 16-byte binary value. The mechanics of the data type and its associated functions are
very different from identities and for 95% of cases, you will have no need for them.

Another name for unique identifiers is GUID (global unique identifier) that is guaranteed to be
unique no matter the server and/or location/time. The value is a large HEX string represented by
the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, in which only no arithmetic functions are
allowed against it. To allocate a value to a GUID variable, you need to use the NEWID() function as
shown in the examples below:

DECLARE @myvar UNIQUEIDENTIFIER


SET @myvar = NEWID()
SELECT @myvar

-- of course, different every time we run it


304DFB66-55D9-4BF3-A0A7-F2EDC7A04550

CREATE TABLE mytable


(
mypkeycol UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY
mycol2 VARCHAR(20)
)

Note one of the key differences is that we have no magic function to select the allocated
NEWID value as we can with identities using @@IDENTITY.

NOTE - Classic uses of GUID are with replication, uniquely identifying rows and to assist with
conflict resolution.

292
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Built in Functions
Numeric Functions
Some of these are not strictly numerical functions but have been listed due to their context of
usage.

SQL Server Oracle


Function Equivalent
% MOD
(modules operator)
@@ERROR SQLCODE
@@SPID UID
ABS ABS
ACOS ACOS
ASIN ASIN
ATAN ATAN
ATN2 ATAN2
CEILING CEIL
COL_LENGTH VSIZE
LEN
DATALENGTH
COS COS
COT COSH
COUNT COUNT
COUNT_BIG N/A
DEGREES N/A
EXP EXP
FLOOR FLOOR
ISNULL NVL
ISNUMERIC N/A
LOG LN
LOG10 LOG(10)
N/A DUMP
N/A GREATEST
N/A LEAST
N/A COSH
N/A TANH
N/A TRUNC
N/A SINH
N/A TANH
N/A BITAND
PI N/A
POWER POWER
RADIANS N/A
RAND*
ROUND ROUND
SIGN SIGN
SIN SIN
SQRT SQRT

293
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQUARE N/A
sysmessages SQLERRM
TAN TAN
TOP N/A
USER_NAME USER

* random numbers are discussed later in this chapter.

In Oracle we can use TO_CHAR (numeric to a varchar2) and TO_NUMBER (varchar2 to numeric)
functions for translation and formatting of numerical data. The TO_CHAR function offers a wide
variety of number format masks for the resultant string value, this includes such things as
currency, suffix and prefix minis signs, commas, scientific notation and much more. We have no
equivalent functions in T-SQL for SQL Server, and are typically resolved via the application utilising
VB or C++. The DBA should consider CAST and CONVERT functions where applicable.

String Functions

Some of the core string functions:

SQL Server Function Oracle Equivalent


REPLACE REPLACE
LOWER, UPPER LOWER,UPPER
SUBSTRING SUBSTR
STR N/A
CHARINDEX INSTR
PATINDEX N/A
REVERSE N/A
REPLICATE N/A
LEN LENGTH
LEFT, RIGHT N/A
ASCII ASCII
STUFF TRANSLATE
LTRIM, RTRIM LTRIM, RTRIM
SPACE (no direct equivalent) LPAD, RPAD
SOUNDEX SOUNDEX
QUOTENAME N/A
N/A INITCAP
DIFFERENCE N/A

294
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Date Functions
The SQL Server DBMS includes two datatypes for date/time data storage:
a) Datetime – accuracy of one three hundreds of a second – Jan 1 1753 to
b) Smalldatetime – accuracy to nearest minute – Jan 1990 to June 6 2079

IMPORTANT – SQL Server has no equivalent to the TIMESTAMP or TIMESTAMP WITH TIME
ZONE datatypes, do not confuse the SQL Server timestamp datatype with these. The closest
option you have is the datetime datatype.

As with oracle, the time component is embedded with the datatype and there is no specific
time datatype.

SQL Server Oracle Summary


Function Equivalent(s)
@@datefirst N/A See set datefirst above, retrieves current set value.
convert TO_CHAR This is not strictly for dates only, but is one of the core
cast ROUND functions for formatting and converting datetime values.
TO_DATE Note the covert function for dates returns the formatted
string value, style 103 is DD/MM/YYYY.

select CONVERT(varchar, getdate(), 103)

set dateformat dmy


print cast(‘07/01/2001’ as datetime)
dateadd ADD_MONTHS Add some specified internal to an existing date.

datediff MONTHS_BETWEEN Returns that date difference between two dates, we can
choose wether the date part is year, month etc.

select datediff(mm, getdate(), getdate() + 100)


datename TO_CHAR Returns the string representation of a date part. In
some cases there is no difference to datepart.

select datename(month, getdate())


datepart TO_CHAR Returns a specified portion of a datetime value.
EXTRACT
print datepart(yyyy, getdate())
print datepart(ms, getdate())
day EXTRACT DAY returns the integer value of the day for a specified
date. Also see DATEPART.
getdate Sysdate Returns current local datetime. Formats are:
2002-07-22 09:39:34.057 or
Jul 22 2002 9:42AM
Not affected by logins language setting.
getutcdate NEW_TIME Returns current local datetime in terms of GMT
timezone.
isdate N/A Returns zero or one if value is a valid date.
month EXTRACT MONTH simply returns the integer value of the month for
the specified date. Also see DATEPART.
N/A NEXT_DAY In Oracle this returns the date of the first weekday
specified that is later than the date.
N/A LAST_DAY In Oracle this returns the last day of the month.

295
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

See Reference (41) for an example user defined


function.
N/A NEW_TIME In Oracle, this returns the clients datetime value, not the
value of the server (which sysdate does). There is not
equivalent in SQL Server. This function can also convert
from one timezone to another in Oracle.
set datefirst N/A Sets the fist day of the week. Default is 1 (Monday).
set dateformat NLS_DATE_FORMAT Alters the interpretation of a string literal date format.
Is affected by the language setting of the login.

-- lang is ENGLISH, which is mdy, need to set it


-- to prevent out-of-range errors
declare @aa datetime
set dateformat dmy
set @aa = '31/07/2002'

Be careful with setting these constants, they will


invalidate a cursor declaration if its run after the cursor
declaration and are set globally for the session
(connection).
Year EXTRACT YEAR simply returns the integer value of the month for
the specified date. Also see DATEPART.

Date formats used by most of the functions above include:

Date Part Format String


Year yyyy, yy
Month mm, m
Day dd, d
Hour Hh
Minute Mi
Second ss, s
Millisecond ms
Week wk, ww
Quarter qq, q
Century N/A
Standard ISO Year N/A
First day of ISO Year N/A

There is no TRUNC() function is SQL Server, therefore, date comparisons over equality may require
the use of datepart or cast functions to trim the time component.

NOTE – SQL Server has no concept of JULIAN dates, i.e. the number of days since Jan 1,
4712 BC, for continuous dating from a common reference point. There is no format string (J)
for julian date conversion.

In Oracle we can utilise, amongst other things, the NEW_TIME function to assist it converting
datetime values between timezones. The closest we have in SQL Server is the getutcdate function,
that returns the current datetime in terms of GMT (greenwich mean time). The servers local-time
and the zone setting of the operating system can affect the value returned. Therefore, the
timezone of the server will influence the result set. Apart from this, there is not magical
NEW_TIME function available for time-zone conversions.

296
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL Examples with Oracle Comparisons


It is important to note that Oracle supports the ANSI and SQL-92 for its join syntax, with a move to
ANSI where possible. The following table provides some examples in SQL Server with notes on
Oracle as need be.

Syntax SQL Server Example Notes


Type
CROSS JOIN SELECT Combines ALL rows from the left the
(cartisan FROM dept, emp right tables.
product)
INNER JOIN SELECT dept.* The inner join is identical to the
(equi-join) FROM dept INNER JOIN emp ON equi-join with standard where clause
dept.dept_id = emp.dept_id predicates.
same as
SELECT dept.*
FROM dept, emp
WHERE dept.dept_id = emp.dept_id
LEFT OUTER SELECT dept.* All rows in left table (dept) even
FROM dept LEFT OUTER JOIN emp ON when keys don’t match.
dept.dept_id = emp.dept_id In SQL-92, this would be
represented via:
dept.dept_id(+) = emp.dept_id in
the where clause.
RIGHT OUTER SELECT dept.* All rows in right table (emp) even
FROM dept RIGHT OUTER JOIN emp ON when keys don’t match.
dept.dept_id = emp.dept_id In SQL-92, this would be
represented via:
dept.dept_id = emp.dept_id(+) in
the where clause.
FULL SELECT dept.* This is a RIGHT AND LEFT OUTER
FROM dept FULL OUTER JOIN emp ON join merged into one.
dept.dept_id = emp.dept_id
START WITH The DBA will need to consider additional SQL Server has no equivalent syntax
CONNECT BY columns to support the hierarchy, such as to Oracle’s connect-by-prior for
the parent record, optional depth of the hierarchies. Have fun coding your
record in the hierarchy etc. own.
Collelated Sub- SELECT dept.* As per Oracle, all standard
Queries FROM dept correlations are support in the
WHERE EXISTS ( WHERE clause, the user needs to
SELECT ‘X’ alias tables as need be to remove
FROM emp any ambiguity.
WHERE dept.dept_id = emp.dept_id) The sub-query can be used in the
SELECT, FROM and WHERE clauses
and most other DML.
EXISTS, NOT As per Oracle, no restrictions or differences These are standard operations and
EXISTS, IN, in use. are identical in SQL Server.
NOT IN
FOR UPDATE -- Row locks hint In Oracle, FOR UPDATE locks rows
based on the join clauses used.
-- For update in cursor In SQL Server we have little control
DECLARE mycursor CURSOR FOR over such locking due to SQL

297
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

select col1, col2 from mytable Server’s lock escalation, even so, we
FOR UPDATE OF col1, col2 can get those via SQL Hints.

In SQL Servers cursors,


TABLE -- table data type In SQL Server we can create 3
collections DECLARE @myvar TABLE (col1 int, col2 int) different types of table. The first
Insert into @myvar (col1, col2) values (1,2) being the TABLE data type (in
memory complex memory structure)
-- local temporary table , the second type is local temporary
create table #mylocaltab (col1 int, col2 int) tables (and finally global temporary
tables (session wide). Such table
-- global temporary table structure support constraints like
create table ##mylocaltab (col1 int, col2 int) physical tables but not foreign key
constraints.
The table data type is preferable as
local and global tables use the
tempdb database, therefore result in
physical IO.
Virtual/Derived SELECT deptname, totalemps The virtual table (also known as
Tables FROM dept as DD, derived tables) must be aliased as
(SELECT deptid, count(empid) totalemps shown in the example. Any valid
FROM deptemps SQL statement is allowed.
GROUP BY deptid) as AA
WHERE
AA.deptid = DD.deptid
No FROM --get my SPID number A valid SQL statement in Oracle
clause SELECT @@SPID requires, at a minimum, the SELECT
-- get SS2k version .. FROM clauses. In SQL Server you
SELECT @@VERSION can skip the FROM clause where you
are selecting data not from a table
or view.
DISTINCT No example required. As per Oracle, no example required.
GROUP BY No example required. As per Oracle, no example required.
ORDER BY As per Oracle in virtually all cases, it also As per Oracle, no example required.
supports dynamic ordering, ie:

SET @myvar = 2

SELECT COL1, COL2, COL3


FROM MYTABLE
ORDER BY
CASE WHEN @myvar = 1 THEN
MYTABLE.COL1
CASE WHEN @myvar = 2 THEN
MYTABLE.COL2
ELSE
MYTABLE.COL3
END

To randomly order records, consider the


following code:
ORDER BY NEWID()
HAVING No example required. As per Oracle, no example required.
CUBE select item, salesman, sum(total) In SQL Server, the CUBE operator
from sales create a data set that is a result of

298
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

group by item, salesman with cube all possible values based on the
WITH CUBE columns specified (call
Item Sales Person Total dimensions).
----------------- ----------------- -------
15" Monitor Veronica 350.0 In the example, we can see that the
15" Monitor NULL 350.0 CUBE expression has pivoted over
Arm Chair Carl 120.0 the sum(total) column and produced
Arm Chair Chris 120.0 a result set that covers all valid
Arm Chair NULL 240.0 combinations of item and salesmen
Desk Carl 450.0 where data exists.
Desk Veronica 450.0
Desk NULL 900.0 The GROUPING clause can use used
Foot Stool Carl 25.0 to determine if a NULL will be
Foot Stool Chris 25.0 returned so the user can alter this
Foot Stool NULL 50.0 value and return something easier to
NULL NULL 1540.0 understand.
NULL Carl 595.0
NULL Chris 145.0
NULL Veronica 800.0
ROLLUP select item, salesman, sum(total) When compared to the query above
from sales and the with c8be option, the rollup
group by item, salesman with rollup clauses uses the same paradigm but
rolls up the summarised totals.
Item Sales Person Total
----------------- ----------------- -------
15" Monitor Veronica 350.0
15" Monitor NULL 350.0
Arm Chair Carl 120.0
Arm Chair Chris 120.0
Arm Chair NULL 240.0
Desk Carl 450.0
Desk Veronica 450.0
Desk NULL 900.0
Foot Stool Carl 25.0
Foot Stool Chris 25.0
Foot Stool NULL 50.0
NULL NULL 1540.0
UNION No example required. As per Oracle.
UNION ALL No example required. As per Oracle.
INTERSECT N/A There is no equivalent in SQL
Server.
MINUS N/A There is no equivalent in SQL
Server.
ASC, DESC No example required. Sorting conditions for order by
clause are as per Oracle, no example
required.
AS OF N/A Oracle – The FROM <list> AS OF
[SCN, TIMESTAMP] clause is used to
query data as it existed back in time,
this is done via Oracle’s automatic
undo tablespace and its settings to
control Oracle flash-back. There is
no equivalent in SQL Server. No SQL
Server equivalent.
SAMPLE N/A Oracle – can return a sampled

299
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

subset of data from a table. Does


not support joins. No SQL Server
equivalent.
INSERT No example required. As per Oracle, no example required.
DELETE No example required. As per Oracle, no example required.
UPDATE update emp SQL Server adds a fantastic little
set salary = 200000 feature that Oracle does not. This is
from dept shown in the example. As per
where dept..empid = emp..empid Oracle though, the table being
updated can not be aliased.
TRUNCATE TRUNCATE TABLE mytable In Oracle, the truncate command
covers the specification of table or
cluster (clustered table and its
indexes), wether to preserve or
purge materialised view data and
wether the already allocated storage
will also be dropped or reused. The
table can be truncated if
relationships exist, but you still need
to truncate in order of the key
values.

In SQL Server the command set is


simple truncate <table>, as the DBA
has no control over storage, and the
DBA cant truncate whilst foreign
keys exists. SQL server is much
more restrictive on its use, requiring
table owner or db_owner or
sysadmin or db_ddladmin privs.
TOP and SELECT TOP 10 * Will return the top n records or top n
TOP PERCENT FROM MYTABLE percent of records of 100. Use the
[with ties] TOP clause in views if you want to
also use an ORDER BY. If Order by is
used the entire result set is sorted
and the top n records are then
selected.

The set ROWCOUNT N constant can


also be used to simulate a TOP n
clause but will remain in effect until
set to zero or the connection is lost.

COALESCE SELECT COALESCE (col1, col2, col3) Returns the first non-null value from
FROM MYTABLE a list of values.

If col1 was null, but col2 was not, then the


value of col2 would be returned. This
continues for all records in MYTABLE. All
values must be of the same data type.

300
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Partitioned Tables

There is no concept in SQL Server of partitioning; there seems to be no plans from Microsoft to
support this great Oracle option in the next release of SQL Server

Parallel Query

Unlike Oracle, the parallel options in SQL Server seems to be a half hearted effort for
multiprocessor machines. There is only one hint available (DOP), and from a lot of work with
parallel queries, I have been a little disappointed with performance overall. But don’t let me
discourage you, I am not backing up my statement so you will need to try it yourself.

At an instance level, the DBA can “turn on and off” the CPU’s utilised by SQL Server. This is easily
managed via Enterprise Manager by right clicking properties at the instance level:

From here, the DBA can control basic instance parallelism options:

Degree of parallelism (DOP, plan generation) Threshold for Parallelism (seconds)

EXEC sp_configure ‘max degree of parallelism', 1 EXEC sp_configure


RECONFIGURE WITH OVERRIDE 'cost threshold for parallelism', 5

Contol what CPUs can be used by SS2k threads

EXEC sp_configure ‘affinity mask', 0x00000003


RECONFIGURE WITH OVERRIDE

The cost estimate or threshold parameter is somewhat vague, its like the recovery interval, you
don’t really know what its doing under the covers. This value is in seconds and is used by the
optimiser to predicate a plans execution time; if it is greater than 5 seconds for example, it will
consider utilising intra-query parallelism.

301
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

To control parallelism at a SQL level, use the MAXDOP (DOP = degree of parallelism) hint, for
example:

select *
from products
option (maxdop 3)

Take care to monitor CPU utilisation along with logical and physical reads. You may find a
significant increase in CPU utilisation and with large, frequent queries you may see a reduction in
buffer cache hit ratios if the queries are large and adhoc.

Utilise the trace flag 8687 to disable parallelism globally for the DBMS on instance startup. Also
note that many internal DBCC commands will utilise parallel operations where possible; consider
the trace flag 2508 and 2528 to turning it off selected DBCC calls.

Parallel IO
With the installation of SQL Server 2k SP1 and above, the parallel affinity option has been
enhanced to include to specify what CPU’s are dedicated to run SQL Server IO operations. Without
the option, SQL Server disk IO will be scheduled to any of the eligible CPU’s as specified by the
affinity mask option.

The parameter is specified on instance startup:

sqlservr.exe –I0x00FF0000

Remember that this option goes hand in hand with the affinity mask option to split away CPU’s
dedicated to disk IO verses other thread tasks for the rest of the instance.

SQL Hints

As a general rule, do not use HINTS unless there is a real need too. They are hard to
administer and at times understand, and if not used correctly, can create adverse performance
problems due to changes in the underlying schema or row counts. This rules tends to flow
between both RDBMS’s.

In Oracle, the hint applies at the start of the select, insert, delete or update statement.

Select /*+ hint [text] */


Select --+ hint [text]

where [text] are one or more additional options for the actual hint.

There can be one or more hints specified that can work over any views/tables used in the from
clause of the statement. In all cases, the cost based optimiser will be used (except of course
when the RULE hint is used).

302
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

In SQL Server the optimiser is COST BASED (there is no other option) and as one would also
expect, the range and type of hints vary significantly between two DBMS’s. The SQL Server
hint categories are:

a) index hints
a. INDEX
b) join hints
a. LOOP
b. HASH
c. MERGE
d. REMOTE
c) locking & isolation level hints
a. granularity (one per table)
i. PAGLOCK
ii. NOLOCK
iii. ROWLOCK
iv. TABLOCK
v. TABLOCKX
vi. LOCKX
vii. UPDLOCKX
viii. READPAST
b. Isolation (can be mixed with selected granularity hints)
i. HOLDLOCK
ii. NOLOCK
iii. READCOMMITTED
iv. REPEATABLEREAD
v. SERIALIZABLE
d) query hints (affects all operators in the statement)
a. HASH GROUP
b. HASH ORDER
c. ROBUST PLAN
d. FORCE ORDER
e. MERGE UNION
f. HASH UNION
g. CONCAT UNION
e) table hints (one per table)
a. FASTFIRSTROW
b. + index hints
c. + granularity hints
f) view hints
a. EXPAND VIEWS
b. NOEXPAND
c. Selected index hints also apply
g) other hints
a. FAST n-rows
b. MAXDOP degree-of-parallelism
c. KEEP PLAN
d. KEEPFIXED PLAN

The syntax for specifying hints:

303
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

-- TABLE HINT
SELECT <columns>
FROM mytable WITH (<hint>)
[WHERE <predicate>]

-- QUERY HINT
SELECT <columns>
FROM mytable
[WHERE <predicate>]
OPTION (<option hint>)

-- JOIN HINT
SELECT *
FROM orders LEFT OUTER <hint> JOIN customers
ON orders.customerid = customers.customerid

From the syntax above, we see that the hints themselves are broken down into two styles:

1) WITH
i. Can be specified for each table referred to in the DML, within the
brackets of the WITH statement we can specify multiple hints. SQL
Server will report syntax errors but will not report on un-used hints
unless you carefully check the execution plan.
2) OPTION
i. Can only be specified once for each whole SQL statement, meaning that
the option applied to the entire statement and any sub-queries specified.
If a UNION is used, then the last statement can only include the option.
3) Join Hint
i. Will enforce the join strategy between two tables. The CROSS JOIN will
require the hint to be wrappered in brackets.

NOTE - Using hints for remote queries (queries over linked servers, otherwise known as
database links) are not supported in SQL Server 2k, you will get the error: Server: Msg 7377,
Level 16, State 1, Line 1 Cannot specify an index or locking hint for a remote data source.

Comparing HINTS is very difficult; the list below is by far complete and will require a significant
amount of testing when porting SQL statements from one DBMS to another. It is recommended
that hints are stripped when porting SQL and evaluate the need for a SQL Server equivalent as
performance or locking issues dictate. We will only list Oracle hints where I believe there is a vague
resemblance to an equivalent SQL Server one.

Oracle SQL Server


FIRST_ROWS(n) FASTFIRSTROW
OPTION(FAST n)
CLUSTER INDEX(0) – if the cluster index exists for the table
HASH INDEX(0) – if the cluster index exists for the table
INDEX_JOIN INDEX(n) – or consider the join hints to provide
some control over index usage
HASH Consider the HASH join hint
FULL None, you cannot force a full table scan unless of

304
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

course you have no indexes or statistics are out of


date and the optimiser chooses not to use them.
QUERY TRANSFORMATION hints No equivalents in SQL Server, perhaps one could
argue that the query hints such as FORCE ORDER,
ROBUST PLAN etc are similar, but there are vague
resemblances at best.
ORDERED FORCE ORDER
USE_NL LOOP – join hint
USE_MERGE MERGE – join hint
USE_HASH HASH – join hint
PARALLELISM hints OPTION(MAXDOP n) – at query level
And instance level parameters
CACHE No hint, the lazywriter will manage the procedure
cache and age plans as required. See books online
for aging execution plans.
NOCACHE Consider the recompile option, apart from that
there are no specific hints.
Locking Hints There are no equivalent options in Oracle for the
SQL Server locking hints listed previously.

NOTE - The NOLOCK, READUNCOMMITTED, and READPAST table hints are not allowed for
tables that are targets of delete, insert, or update operations. Microsoft Support Doc Q235880
describes issues with NOLOCK and READ UNCOMMITTED hints and the generation of transient
error messages to do with the processes reading data that is being moved or altered by
another user (dirty read).

Example Hint

BEGIN TRANSACTION

SELECT *
FROM PRODUCTS WITH (HOLDLOCK, ROWLOCK)
WHERE PRODUCTID = 1

COMMIT TRANSACTION

305
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Data Types Compared

See table below, to review data types in SQL Server also consider this query:

select * from master..systypes

SQL Server Oracle Oracle Notes SQL Server Notes


Character Equivalent
types
Char Char Max 2000 bytes/row Max 8000
Varchar Varchar2 Max 4000 bytes/row
Text CLOB or Up to 232 - 1 bytes, or 4
Ntext gigabytes.
LONG Up to 2Gb data for LONG.
Nchar Nchar Fixed for every row in the table
(with trailing blanks). Column
size is the number of
characters. (The number of
bytes is 2 times this number for
the AL16UTF16 encoding and 3
times this number for the UTF8
encoding.) The upper limit is
2000 bytes per row. Default is
1 character.
Nvarchar Nvarchar2 Variable for each row. Column
size is the number of
characters. (The number of
bytes may be up to 2 times this
number for a the AL16UTF16
encoding and 3 times this
number for the UTF8 encoding.)
The upper limit is 4000 bytes
per row. Default is 1 character.

SQL Server Oracle Oracle Notes SQL Server Notes


Datetime Equivalent
types
Datetime Date Fixed-length date and time Date and time data from
data, ranging from Jan. 1, 4712 January 1, 1753, through
B.C.E. to Dec. 31, 4712 C.E. December 31, 9999, with an
accuracy of three-hundredths
of a second, or 3.33
milliseconds
Smalldatetime Date N/A – on conversion the DBA Date and time data from
will need to consider the loss of January 1, 1900, through June
accuracy 6, 2079, with an accuracy of
one minute.

306
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQL Server Oracle Oracle Notes SQL Server Notes


Numeric Equivalent
types
Bit NUMBER(1,0)
Tinyint NUMBER(p,s)
Smallint NUMBER(p,s)
Int NUMBER(p,s)
Bigint NUMBER(p,s) Big Int - 8 bytes in size versus
its 4 byte int. whole numbers
between
-9,223,372,036,854,775,807
and 9,223,372,036,854,775,807
Decimal NUMBER(p,s)
Numeric NUMBER(p,s)
Smallmoney NUMBER(p,s)
Money NUMBER(p,s)
Real Float
Float Float

SQL Server Oracle Oracle Notes SQL Server Notes


Binary Equivalent
Types
Image BLOB Up to 232 – 1 bytes, or 4
Or gigabytes.
LONG RAW?
Varbinary BLOB Up to 232 – 1 bytes, or 4 Variable-length binary data
gigabytes. with a maximum length of
8,000 bytes.
Binary BLOB Up to 232 – 1 bytes, or 4 Variable-length binary data
Or gigabytes. with a maximum length of
LONG RAW? 2up31 – 1 (2,147,483,647)
bytes.

SQL Server Oracle Oracle Notes SQL Server Notes


Other Equivalent
Types
Timestamp Timestamp
or
RAW
N/A %TYPE Not really a data type as such No equivalent in T-SQL.
but allows the pl/sql
programmer to declare
variables that have the same
type of a tables column.
SQL_VARIANT N/A
Sysname
TABLE TYPE is of
TABLE
N/A %ROWTYPE No equivalent in T-SQL.
N/A TYPE <name> No equivalent in T-SQL.
IS RECORD

307
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

The text data type can be very restrictive in terms of SQL and T-SQL. You can not declare data
types of type text (or other binary types), LEN and other functions will not work:

Server: Msg 8116, Level 16, State 2, Line 1


Argument data type ntext is invalid for argument 1 of len function.

To get around this error, use the command:

SELECT MAX (DATALENGTH (MyTextColumn))


FROM mytable

Moving data from a ntext to a varchar will give an error:

Server: Msg 260, Level 16, State 1, Line 2


Disallowed implicit conversion from data type ntext to data type varchar, table 'mydb.dbo.mytablet', column
'mycolumn'. Use the CONVERT function to run this query.

When used in predicates, you may also face this error:

Server: Msg 306, Level 16, State 1, Line 1


The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE
operator.

All fun for the developer and DBA alike.

308
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Dynamic SQL
It is very rare that the modern DBMS does not support dynamic SQL statements in some form,
within Oracle we have a choice of two methods:

DBMS_SQL package

mysqlstr varchar2(100);
numrows NUMBER;
cursorhandle NUMBER;

mysqlstr := 'INSERT INTO mytable VALUES(:col1,:col2)';


cursorhandle := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cursorhandle, mysqlstr, DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(cursorhandle,':col1',10);
DBMS_SQL.BIND_VARIABLE(cursorhandle,':col2', 'This is an example');

numrows := dbms_sql.execute(cursorhandle);

DBMS_SQL.CLOSE_CURSOR(cursorhandle);

Native Dynamic SQL (requires compatible parameter set to 8.1.0 or higher)

mysqlstr varchar2(100);

mysqlstr := 'INSERT INTO mytable VALUES(:col1, :col2)';


EXECUTE IMMEDIATE mysqlstr USING 10, 'This is an example';

These statements support all forms of DDL, DML and anonymous PL/SQL blocks. In SQL Server we
also have a choice of two methods:

EXECUTE

declare @mysqlstr nvarchar(100);

set @mysqlstr = N'INSERT INTO mytable VALUES(10,' + '''This is an example''' + ')'


exec(@mysqlstr)

SP_EXECUTESQL (recommended over EXECUTE)

declare @mysqlstr nvarchar(100);

execute sp_executesql
N'INSERT INTO mytable VALUES(@col1, @col2)',
N'@col1 int',
N'@col2 varchar(50)',
@col1 = 10,
@col2 = 'This is an example'

The SQL in both cases are not parsed until the command is executed. It is also important to
remember that if the database context is altered via a dynamic SQL statement, then it will only
persist whilst the dynamic routine is run, for example:

309
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

USE master Å goto master database for subsequent commands


EXEC ("USE nothwind") Å goto northwind database
SELECT * FROM mytable Å this will run under master, not northwind

The sp_executesql system stored procedure has a number of benefits over EXECUTE:

ƒ supports parameter substitution

ƒ generates procedure cache plans that will more likely benefit from reuse due to its
parameterisation (when part of a loop condition or the stored procedure is called often with
different values, then sp_executesql with parameters will benefit tremendously).

In terms of transaction context, the following example shows that both calls will retain their context
in terms of the current open transaction. Note that a Unicode string is required for both dynamic
procedures.

CREATE PROCEDURE DynamicSQL AS

DECLARE @mysql nvarchar(100)

BEGIN TRANSACTION

insert into mytable values (1)

set @mysql =
N'insert into mytable values (2)'

exec sp_executesql @mysql We will try the two dynamic SQL


exec(@mysql) routines.

insert into mytable values (3)


select * from mytable Values 1,2,2,3 inserted as
part of the single transaction
ROLLBACK TRANSACTION

select * from mytable


All values successfully rolled
GO back (table is empty)

310
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

T-SQL (pl/sql) Overview


Throughout this book we have provided numerous examples of SQL Server functionality and
discussion of the Oracle equivalents as need be. Comparing T-SQL and PL/SQL is summarised
below; be aware that PL/SQL is 100% more comprehensive in terms of a language and a 1;1
comparison is simply not particle. Here are some key points to remember either way:

Oracle SQL Server


Variable <variablename> <type> DECLARE @<variable> <type> [DEFAULT
Declaration [DEFAULT <value>]; <value>]

mystring VARCHAR2(100);
DECLARE @mystring VARCHAR(100)
Dynamic DBMS_SQL sp_execute_sql
SQL EXECUTE IMMEDIATE EXECUTE
Stored CREATE OR REPLACE PROCEDURE CREATE PROCEDURE
Procedure myprod [(<parameters>)] [owner].myproc[;version] <parameters>
[WITH <options>]
[FOR REPLICATION]
IS AS
[<local variables>] [<local variables>]
BEGIN
<body code>; <body code>
[EXCEPTION GO
WHEN <code>;
THEN <code>; ALTER PROCEDURE myproc[;version]
[WHEN OTHERS] <parameters>
END; [WITH <options>]
[FOR REPLICATION]
AS
[<local variables>]

<body code>
GO
User Defined CREATE FUNCTION [owner].myfunc
Function (<parameters>) RETURNS <datatype>
AS
[<local variables>]
<body code>
RETURN (<variable or statement>)
GO
Set current N/A SET <dbname>, eg: SET master
database
Precompiler PRAGMA <instruction> N/A
Statement
IF IF <expression> THEN IF <expression>
<code> [BEGIN]
[ELSIF] <code>
END IF; [END]
[ELSE]
LOOP LOOP -- No FOR loops in SQL Server, only the
<code> -- WHILE loop

311
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

END LOOP;
WHILE <condition>
WHILE <condition> LOOP BEGIN
<code> <code>
END LOOP; END

FOR <index> IN <statement>


LOOP
<code>
END LOOP;
GOTO GOTO <label>; -- get scoping rules for both languages
-- before porting code.
GOTO <label>
LABELS <<mylabel>> mylabel:
PACKAGE See Oracle Documentation. N/A

312
14
Chapter
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Networking SQL Server

O
ne of the big topics discussed a lot within Oracle mailing lists and news groups
is SQL*Net and the Listener to manage DBMS connectivity. Throughout this
chapter we will cover the SQL Server equivalent and associated connectivity
issues the DBA may face from time to time.

Listener and ODS


As in Oracle, SQL Server has a listener which is managed per instance of SQL Server
(default or named). The database instance itself is an instantiation of the listener
(i.e. starting the instance will start the listener for the instance), which is very
different to Oracle. This dependency can mean that incorrect listener settings may
prevent the instance from starting. An example of the log entry for a starting
instance:

2002-11-29 16:36:32.27 server Using 'SSNETLIB.DLL' version '8.0.534'.


2002-11-29 16:36:32.37 server SQL Server listening on TCP, Shared Memory.
2002-11-29 16:36:32.87 server SQL Server is ready for client connections.
2002-11-29 16:36:32.91 server SQL server listening on 163.232.13.22: 2433.
2002-11-29 16:36:32.91 server SQL server listening on 127.0.0.1: 2433.

due to this, any changes in the server network utility require the instance to be re-
started (not great for 24x7 environments).

The instance listener is managed via the Server Network Utility found under the
Microsoft SQL Server group, this is installed once on the server. The utility allows
the DBA to specify what protocols are enabled for each instance and provides the
ability to alter various protocol specific settings (such as ports, encryption etc):

313
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Manage listener properties at a


instance level on the server

Enabled protocols the instance will


accept connections from

List of valid protocols the


instance can utilise
Get properties for selected
enable protocol
Global options for all
enabled protocols.

NOTE - If a protocol is not available, re-check your installation by re-running the


setup.

To view the underlying DLL for each protocol click on Network Libraries. The ss
prefix on the dll’s represents a server based network library; the ssnetlib.dll (super
socket) will also manage SSL encryption where appropriate (covered later in the
chapter).

The configuration and setup is very simple and requires little discussion. See the chapter
on security for information about protocol encryption. One point noting though about
TCP/IP connections, is the default port number of 1433. On installation this is setup
unless you entered a value explicitly, if another instance is using port 1433 it will auto
select another port on the first connection to the instance through that protocol. The
DBA should not use default port 1433 as it is a classic port for hackers.

NOTE – Take a careful look at the first few lines of your SQL Server instance log,
you will see information regarding the listener and the protocols and ports
supported.

314
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Multi-Protocol

The multi-protocol library is worth mentioning on its own. The library utilises the NT
remote procedure call (RPC) in addition to its network library. This protocol supports the
standard IPC calls supported by NT, namely tcp/ip (nacn_up_tcp), ipx/spx and named
pipes (nacn_np):

The enable encryption option is discussed later

On instance startup, we will see something like this in the SQL Server log:

The net library will utilise a random port making hacking a little harder but going through
a firewall can be problematic.

NOTE – Does not support named instances.

Registry Entries

To verify the last instance connection from the client, goto the register entry last connect
for either multiprotocol connections (rpcnetlib) or super sockets network library:

To get a good summary of registry entries related to the network library API, check out:

http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/dbnetlib/htm/dbnetlib.asp

315
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Client Network Utility


A client does not require the client network utility to be configured in order to connect to
a SQL Server instance. So long as the client has a SQL network library installed utilising a
protocol in which the instance is listening on (i.e. TCP/IP); the connectivity can be
established via a suitable provider (eg. OLEDB, ODBC driver, db-library clients). All of
which is installed with MDAC.

So, what is it used for then?

The client utility is used when:

a) underlying server does not have the appropriate network libraries installed to
facilitate communication with the server (installing the client will resolve the
issue)

b) to run SQL Server client tools (such as Query Analyser, Profiler, EM)

c) want finer control over dbnetlib.dll (which talks to the SQL Server equivalent
ssnetlib.dll – the server will return a packet via UDP port 1434 listing instances
and their listener protocols for the clients dbnetlib.dll to decide what to do with
the client request for connectivity).

A classic example of utilising the client utility is to specify an alias to a SQL Server
instance. If the server is hosting multiple instances (all of which will talk on different
ports for there defined listener protocols), you may need to create an entry clearly
specifying the protocol and its properties in order to successfully connect. If you have
issues connecting from your SQL Server client tools, then double check your client utility
alias and its protocol and port properties (or create one if you have not).

Another example is ODBC and the SQL Server driver. Without the client utility and an
alias, I have found that connecting to a named instance on a non-default port will not
work.

316
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ODS

The ODS (open data services) API manages connections and disconnections to SQL
Server as defined by the protocols enabled via the server network library utility for the
instance. The ODS talks using the TDS (tabular data stream) which is an application
level protocol; the TDS is encapsulated in the protocol stack as defined by the net library
listener.

Net-Lib Listener Client Application

Net library Native


Protocol(s) client
TDS (tabular data stream) packets library
encapsulated within the used to
ODS transmission protocol talk with
API
the
listener

SQL Server Instance

The ODS API can be used by C++ developers to build extended stored procedures
(discussed later) that talk natively to SQL Server and the client via TDS. The books
online cover the API reasonably well with code examples and the associated header
and object libraries.

Tracing TCP/IP port issues

Use the portqry.exe command line utility to assist in tracing issues with TCP/IP ports.
This tends to happen when other services are using default ports of SQL Server (namely
1433). The utility is available in the operating systems resource kit.

List of Running Instances

Use the command osql.exe –L or isql.exe –L the instances may not necessarily be
running.

There are some great SQL Server hacking tools to search the network for running
instances, such as sqlping, sqlscanner, sqlcracker, sqloverflowdata, sqldosstorm, freely
available on the internet.

SSL of SQL Server Connections


In terms of the SQL Server listener, the DBA can select any protocol and force encryption
that utilizes the SQL Server 2000 super socket network library extensions (ssnetlib.dll).
In order for this to work, a server certificate must be installed for the service account in
which SQL Server runs.

To manage server certificates:

317
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

a) run mcc.exe
b) Add/Remove snap-in
c) Add the certificates snapin
d) You will be prompted to manage certificates for
e) My user account
f) Service account
g) Computer account
h) Select the local computer when asked what server to manage
i) If you selected service account, you will be provided with a list of services to choose from
j) OK

If you have issues with installation and error related to opening a connection to the
server due to SSL security issues, then try and remove (via export then delete) all
computer account certificates and try again. Once installed, re-import the certificates
and re-start the instance (see Q309398). The installation and manage of certificates can
be subsequently managed through the snap-in screen:

NOTE – The certificate must be registered with the full DNS name of your server.

Attempting to force encryption without a certificate gives you an error like:

2002-11-29 16:26:23.65 server Encryption requested but no valid certificate


was found. SQL Server terminating.
2002-11-29 16:26:23.70 server Error: 17826, Severity: 18, State: 1
2002-11-29 16:26:23.70 server Could not set up Net-Library 'SSNETLIB'..
2002-11-29 16:26:23.70 server Unable to load any netlibs.
2002-11-29 16:26:23.70 server SQL Server could not spawn FRunCM thread.

and the instance fails to start.

NOTE - Only 40bit and 128bit certificates are supported. This may vary though
based on your SQL Server release and other government restrictions.

318
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

To enable encryption for the instance, open the server network utility and check the force
protocol encryption option. Be aware though, it affects all enabled protocols.

It is important to note that client encryption is enabled via the client network utility,
creating an alias and specifying encryption via the checkbox provided. This will encrypt
all incoming traffic from the specific client to the instance. When setup at the server
though, all inbound connections and data transfers to the server will be encrypted.

The only protocol that can be set up individually for encryption is multi-protocol by
selecting the properties button for the enabled protocol:

The multi-protocol encryption does not use SSL but the Windows RPC API and will not
work for named instances. In virtually all circumstances the DBA should use certificates.

SQLOLEDB
Virtually all connections to SQL Server are via SQLOLEDB, and it’s rare that other
providers are used, especially in the world of large scale VB development. The
connection sting is simple enough, but care must be taken based on the libraries being
exposed via the listener (Server Network Utility); this is especially relevant when different
protocols are being used or you are changing port numbers.

319
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Some of the key elements of the connection string are:

Provider=SQLOLEDB;
Data Source=server-name or IP-address or server-name\instance-name;
Network Library= see list below (optional)
Initial Catalog=database name;
User ID=username;
Password=password;

This information is typically stored in an INI file or within the registry by the developers.
An example reg file to add an entry into the registry is: (save with a .reg extension and
simply run it, Windows will prompt you to continue with the addition of the registry
item):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\AppName\DBConnStrings]
"MyApp"="Provider=SqlOleDb;Data Source=myserver;Initial Catalog=mydb;User
ID=myuser;Password=myuserpassword"

The network library parameter is very important when you need to hook into a specific
protocol enabled within the listener. If you do not specify it then you may be using a
protocol you did not intend to, or have difficultly connecting (specially when Multiprotocol
is the only one enabled on the listener). The position of the network library option is also
important within the connection string, I have had a range of issues with this and its a
down right pain to debug. Use the parameter immediately after the data course
parameter is used. The values for the parameter are:

Win32 Network Library Name for Summary


Library Network Lib parameter
(dll names)
Named Pipes dbnmpntw TCP 139, UDP 137,138 ports.
No encryption.
TCP/IP dbmssocn 1433 is the default port.
No encryption.
(can be forced in SQL Server 2k)
Multiprotocol dbmsrpcn NT RPC calls only.
(RPC) Uses random TCP ports (default).
Supports encryption.
IPX/SPX dbmsspxn 33854 default port
Apple Talk dbmsadsn
VINES dbmsvinn

A simple search on google.com for “oledb connection strings” or even better check out
www.connectionstrings.com (I didn’t believe it, but yes, one exists). To save you the
trouble of searching as I know you will be asking the question, to specify a specific port
use the parameter data source=xxx.xxx.xxx.xxx,2433.

Network Monitoring
Within SQL Server we can utilise the sp_monitor command to track packets received,
sent and in-error between now and its last execution. The results also translate to the
@@ equivalents as shown below:

320
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

select @@PACK_RECEIVED
select @@PACK_SENT
select @@PACKET_ERRORS

The default TDS packetsize is 4096 bytes and may be limited/altered by the network
library connection to the instance. The DBA can control this for the instance as a
configurable parameter (sp_configure):

Other command line utilities, such as BCP, include the –a switch to control packet size,
this can be handy when pumping through large amounts of data to the instance. Take
care with the parameter, and very large settings may degrade performance.

In terms of performance and monitoring, the DBA needs to have a clear understanding
of:

a) network card configuration and its throughout

b) throughput (bandwidth) of the LAN/WAN

c) OS configuration properties for the card

d) How a TDS packet is routed

e) What other applications are sharing the bandwidth

Careful consideration of this typically comes into play with replication and/or distributed
sites. The DBA may also need to check on the duplexing of backup files between servers
during the day and its associated impact on overall network performance.

The key to monitoring is via performance monitor (perfmon.exe). Some key areas to
watch for:

a) SQL Server Network reads/sec or writes/sec – high values measure how network
intensive the instance is. Match up values with user connections and network
queue lengths; and check application components being executed at the time to
try and drill through to the issues.

b) Utilise the Network Interface performance object and its associated counters
carefully. There are a variety of counters and all should be used with a thorough
understanding on the issues outlined above.

Consult with your network administrator on possible network settings (server and domain
controller configuration) to assist with further tuning. They usually have a host of utilities
to monitor traffic.

321
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

SQLDiag

Utilise SQLDiag.exe to retrieve information about your network libraries. An example


dump may include:

Registry Information
--------------------
SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo:
-----------------------------------------------
DSQUERY: DBNETLIB
163.232.xx.xx: DBMSSOCN,163.232.xx.xx
myserver: DBMSSOCN,163.232.xx.xx,1433
SOFTWARE\Microsoft\MSSQLServer\Client\DB-Lib:
--------------------------------------------
AutoAnsiToOem: ON
UseIntlSettings: ON

Version Information
-------------------
ntwdblib.dll: 8.00.194
ssmsad60.dll: N/A
ssmsde60.dll: N/A
ssmsrp60.dll: N/A
ssmsso60.dll: N/A
ssmssp60.dll: N/A
ssmsvi60.dll: N/A
ssnmpn60.dll: N/A
dbmsadsn.dll: 8.00.194
dbmsdecn.dll: N/A
dbmsrpcn.dll: 8.00.380
dbmssocn.dll: 7.00.819
dbmsspxn.dll: 7.00.819
dbmsvinn.dll: 8.00.194
dbnmpntw.dll: 8.00.194
sqlsrv32.dll: 3.80.0528.00
odbc32.dll: 03.52
odbc32 driver: 03.80.0528

MTS / Oracle Shared Server


There is no equivalent to MTS (Oracle Shared Server) in SQL Server.

322
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

15
Chapter

Security

T
he topic of security can be as simple or as complex as you like, and with any
DBMS, this tends to cover a whole range of issues. Throughout this chapter we
will provide a general overview of the issues within the SQL Server
environment and couple these with some best practice tips.

Secured Installation
How thorough the DBA is with installation is a tricky question. First of all, if you are new
to SQL Server, then install your instances under a user that is part of the Administrator
NT role. It is important to keep the installation user separate from other NT users as you
can tighten security later down the track.

For those still wanting more, then:

a) Create a new NT user to run the service for the instance(s)

b) Grant login as service rights

c) Grant administrator group privileges to this user

d) Create DB data and log file directories for database files to be created in

e) Login as this users and install the SQL Server instance

f) Once installed, shutdown the MSSQLServer service

g) Login as Administrator of the server and alter the new users rights as follows

a. Full control of SQL Server binaries (install directory)

b. Full control of all directories to store database files (mdf,ndf,ldf)

c. For the above directories, remove the "everyone" group privilege

d. Full control of the registry keys:

HKEY_LOCAL_MACHINE\Software\Microsoft\MSSQLServer

323
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

HKEY_LOCAL_MACHINE \System\CurrentCOntrolset\Services\MSSQLServer
or MSSQL$<INSTANCE> for named instances
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Perflib

And associated service registery keys for SQLAgent$InstanceName, MSSearch, and


MSDTC

h) Revoke administrative rights to the SQL Server user account

i) Login as the SQL Server user and attempt to re-start the database, debug as
required via the Windows Event viewer and the SQL Server and SQL Agent logs

Consider using EFS (encrypted file system) for the directories used by the instance whilst
logged in as the service user account. This NT feature will be discussed later.

The DBA should be using an NTFS file system in all cases to utilise its fine grained file
level security features. If the instance is partaking in replication, use a domain user
rather than a local user account. Note that EFS will only work for NTFS file systems.

324
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Logins and Users


In Oracle, the DBA creates users and then allocates appropriate statement and system
level privileges to control what they can run/execute or create/modify/store. In SQL
Server, the equivalent is the login account.

The DBA should be the only user ever creating/deleting/altering login accounts within the
instance, no matter what the reason, be it development, test and especially production
servers. As such, we should not have:

• logins with null or blank passwords

• the login and password matches 1:1

• should include a mix of numeric and characters of a reasonable minimum length

• should consider windows authenticated user vs sql authenticated

This is discussed throughout the book, but here is a summary:

Fixed Server (instance) Roles.

SQL Server Instance

DatabaseA (loginA maps to userA, recorded in sysusers)

DatabaseB (loginA maps to userA, recorded in sysusers)

DatabaseC (loginA maps to userA, recorded in sysusers)


LoginA
(master..syslogins table)

Windows Login (via trusted domain) or


SQL Server Login (mixed) Fixed database roles + user defined roles.

Authentication Modes
The SQL Server DBA can make use of only two forms of end-user authentication to the
instance, that being:

• Windows (integrated) security – same as OPS$ logins for Oracle

• Mixed Mode security (username / password maintained by the instance) – as per


standard user accounts in Oracle

325
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Oracle adds another layer of functionality with Oracle Advanced Security; there is no
equivalent option in SQL Server.

The problem with mixed mode user authentication is that username/password


combinations are passed free-text to SQLServer. This can be circumvented by enforcing
SSL encryption which is discussed in the chapter on Networking. For Windows
authentication, the user authentication is handled by the underlying NOS and as such, is
very secure. The authentication mode used by SQL Server is defined at installation time
but can be altered via a right click on properties within Enterprise Manager and selecting
the security tab.

Ideally, all user logins to the SQL Server user databases use Windows Authentication.
This should be implemented as:

• Application database roles hold object privileges, database login allocated to these

• Logins in SQL Server associated with Local NT Groups on the database server

• Local groups created on the server

• Pointing to global groups on the domain controller

• With NT users added to these global groups on the domain controller

• Providing integrated logins to the DBMS

The use of NT Groups offer a lot of flexibility but care must be taken when providing
access (ie. the name of them should be self documenting to prevent “mistakes”). Apart
from security, this also allows you to provide other team members with the responsibility
for managing security and even better, can utilise the NT password expiration and
management routines (that are missing for mixed logins).

What you use is really dependent on the application itself and how it is architected. Even
more so, the underlying network is a key factor in determining what path to take. I have
always opted for mixed mode authentication, and a small number of secured NT logins
for the application (that COM+ components instantiate themselves under) with a couple
of mixed mode authentication DBA logins for general administration.

BUILTIN/Administrator Login
When the instance is installed, the administrator group and its users will instantly have
sysadmin access to your DBMS via the BUILTIN/Administrator SQL Server Login account.
To alter this and we can:

a) Remove the BUILTIN\Administrators login from within SQL Sever

b) Under NT, create another group called “SQL Server Administrators” or something
like that and place the SQL Server user that starts the SQL Server service in it.
Grant access to any other server administrators access if they need sysadmin
access.

c) In SQL Server, re-create the NT login account linked to the new “SQL Server
Administrators” NT group (don’t re-create BUILTIN\Administrators).

326
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

By default, the service will be started via the local system account and its SQL Server
connection via “windows authentication”. As such, altering the BUILTIN/Administrators
account and revoking sysadmin access will prevent the service from running jobs. Funny
enough, you will see no errors in the SQL Server log or SQL Agent log in relation to this.
Jobs will simply not start and their “next run date” will be “unknown”. In the BOL, it
clearly highlights the fact that the SQL Agent server connection must have sysadmin
access. If you alter the BUILTIN/Administrator login and revoke sysadmin, remember
that this adversely affects the SQL Agent database connection that must be altered
accordingly.

Using the SA login


Never give your SA account password to a developer or server administrator, full stop.
At a bare minimum, you should always set a password for the SA account even when you
select pure windows authentication. The SA account is the master account for the entire
SQL Server instance, in SQL Server 2k it can not be removed, you can not revoke
sysadmin access, and by default it has DBA account for all databases in the SQL Server
instance. The DBA should:

a) never use it scheduled or regularly executed non-scheduled DTS jobs

b) alter the password regularly

c) guard it religiously

d) ensure backup and recovery documents clearly document its use, how to get the
password and associated responsibilities of using the login

What makes the SA account powerful is simply the sysadmin (System Administrator)
fixed server role. Never grant this privilege to any other user, there is simply no reason
to use it other than for DBA administrative tasks.

The DBA can not remove the SA account, just like the Oracle DBA cannot remove the
SYS account. The SA account is inheriantly the dbo user.

Duplexing a Login to Multiple Users

In SQL Server it is possible to login with one name and be connected to a database with
another (strange I know). This is called aliasing logins and should never be used. The
routine used to do it is:

327
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

use mydb
EXEC sp_addalias 'mylogin', 'myuser'

Where mylogin is the login name I used, which maps to the user name myuser. This is a
nightmare to administer and also for security reasons it should never be used.

To locate these users, look at the command sp_helpuser and the UserNameAliasedTo
column that is returned.

Finding NULL Passwords

In SQL Server the DBA cannot manage passwords too well; mainly because of the fact
that Microsoft pushes windows logins (OS managed login) rather than SQL Server logins
(database managed login). It is rare for the security conscious DBA that null or blank
passwords exist, but to find them run this query:

select
name,
password
from master..syslogins
where (password is null or password = ‘’)
and name is not null

DBO Access

I can think of no valid reason what so ever for DBO privilege access for any standard (ie.
non sysadmin or backup admin) user in production. There should be no DDL changes,
the auditing is all in place, and any calls to a predefined SQL Server extended stored
procedure has been sorted out the appropriate access granted. With proper role
management DBO is not an option for any application.

The only problem here can be third party software that utilises SQL Server as its security
or other repository in order to run. I have come across a few products that prompt to for
the SA password, then end up creating a database with no other user but SA, only to
spend hours reading documentation and testing to change it.

User Quota and Resource Restrictions

In Oracle we have a variety of commands to lock, unlock, expire passwords, set quota
limits, control password reuse, grace times etc for resource and access management.
We have nothing of the sort in SQL Server, apart from Windows Authenticated user that
will of course utilise password management features of the operating system.

Password File

The Oracle password file will store passwords for users with administrative privileges.
There is no equivalent option in SQL Server.

Development Server Privileges

328
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

To allow developer access to creating stored procedures as dbo and granting execute
access to the appropriate roles the DBA has created and documented, consider giving
your developers access to the database roles:

db_ddladmin
db_securityadmin

These privileges should be revoked in the test and of course production server
environments.

Lookup grant in the books online for a excellent matrix of database and instance level fix
role privileges.

Application Security – Connection Strings & Authentication

The following suggestions are based on this server set-up:

The first aim is to hide and/or secure the connection string used at the Web-Server in
order to connect to the database. This does not stop a hacker from installing their own
COM/COM+ objects that talk to your existing methods and utilise the business logic
exposed through them. But you do want to stop at all costs complete access to your
user database through an insecure connection string placed in an INI file on the server.
The second aim is to determine the access method to the database. We can either use
mixed mode or windows authentication.

It is important to understand that as remotely possible it may seem to the programmers,


security is of utmost importance in production and a text file based INI file is not
acceptable. Altering data over a period of time (or even once!) is the worst type of
hacking as it can span many backups and it the implications can be extremely costly to
the organisation.

NOTE - The ideas below can be cumulative, ie. they do not necessary describe a
complete solution, but a variety of ideas for securing general connectivity to the
database.

329
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Authentication Example

• Client to Web Server

o Consider HTTPS where appropriate. I have worked with the Athelon SSL
accelerator (hardware) with great reliability and performance. Such
hardware can selectively encrypt/decrypt and supports hundreds of
simultaneous SSL connections per second but is a very expensive option
and is another “point of failure”. Remember that once on the Internet,
network sniffers can make short work of passwords and sensitive business
data (to and from your server).

o The authentication mode at the webserver and the associated web-pages


and folders is the key to web-site security (authentication modes
summarised below). In the example above, a common method of
authentication is via basic or integrated authentication to the web-site and
all associated pages. The user has an account in Active Directory to
facilitate the login and may be internal and external users (typically
grouped and segregated). Authentication to SQL Server may be via
common userid/password combination (shared account) for all users or
fully integrated.

• Integrated, Digest and Basic Authentication

o Under IIS, if all are selected then the highest to the lowest level of security
will be used in order based on what the client initially accepts. An NTFS
partition must be used for Digest and Integrated.

o Basic

330
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

ƒ Standard HTTP over readable text stream (base 64 encoded string)


to the server unless HTTPS is used or a lower level protocol
encryption is employed.

ƒ User is only prompted for login ID and password

ƒ Used by many organisations to prevent from being promoted with


domain (see integrated security).

o Digest

ƒ Sends a hashed password over the network rather than the


encoded password in Basic.

ƒ User/password prompted must be a valid NT user and has


appropriate NTFS permissions on the object(s) it is trying to
access.

ƒ Works via a challenge/response scheme and checksum.

o Integrated

ƒ Uses underlying Windows cryptographic data exchange with


IE. This enabled single-sign-on where appropriate if the user
is already logged into the domain IIS is talking over.

ƒ User prompted for login, password and domain. This can be


confusing for end-users where we are authenticating via a
Domain. I have yet to see a program that utilises integrated
security and pre-enters the domain field in the login prompt.

• COM+ (from a security context - there are also numerous other performance
and feature benefits to the programmer)

o Roll-based security and authentication

ƒ Can administratively construct authorisation policies for an


application down to a method level

ƒ Enables you to manipulate security information from all


upstream callers in the execution chain of your component.

o Client authentication

o Client impersonation and delegation

o Software restriction policies

Obtaining the DB Connection string and Connecting to the Database

Here the objective is to:

a) Store connection strings securely at the webserver

331
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

b) Encrypt communication between webserver and database server

c) Ideally, encrypt data where appropriate between client and webserver (out of scope
for this section)

d) Use only Windows Authentication for SQL Server login, deny local server login for
these accounts.

e) Avoid using the global.asa

Presented below are a series of diagrams that provide a catalyst for ideas in achieving
this security. The examples all assume a COM+ (Component Services) business layer as
a default for Enterprise Computing. Substitute this for COM as required. I do not
recommend straight DB connection from ASP (global.asa variables etc) to the database
for any sort of internet based application.

General notes on the examples below:

1. Consider application roles in SQL Server to set and configure security


context. Remember though only 1 role at a time as security privileges are
not additive.

2. Add registry entries and protect via regedit32.exe for database connection
strings. The COM+ package will run as a specific local domain user and
connects to the database via integrated security.

3. As per 1, but rather than using the registry with encrypt the INI file via
Windows 2k encrypted file system (EFS). As the encryption is based on a
specific user profile this can be a little more difficult to manage if the
COM+ package runs as a different user.

4. Set-up a series of User DSN’s that are only accessible by the Windows user
that created them. These typically map to a 1:1 SQL Server login.

5. Rather than using the registry, use Active Directory (Win 2k) for other 3rd
party LDAP directory to store connection strings. Access is restricted via
Windows Authentication and is always read-only.

6. Consider a global “security or management” database. Such a database


includes a range of information for connectivity, login/password
(encrypted) combinations, security contexts and lookups to establish
connections and use the application.

7. COM+

a. De-encrypt routines (ideally talking to a lower level crypto API) to de-


encrypt and pass connection strings and passwords to establish
connectivity.

b. COM+ supports shared memory areas that can use used to


collectively manage connectivity settings and logins amongst
packages and associated methods.

332
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

c. Supports integrated security at a package level to individual users


and/or groups.

Views and Stored Procedures

Over the years I have talked to a variety of people about application design and how data
models are simplified via views and stored procedures to access and manipulate data.
Although fine, it can be a hard sell to programmers, analysts and project managers.
Why? because many programmers want complete CRUD access to virtually all schema
tables, they want to code all DB access via the application and believe views are only for
reports and simplifying complex lookups.

When under pressure, the time to sit back and think “security” and “performance” is a
tough ask. This is very simplistic view of course as security at this level in the database
is typically dictated by:

a) Cost to implement in terms of time and effort

333
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

b) Understanding of the requirement for such access (definition of the security


requirements)

c) Architecture of the application

d) Need for simplicity (unnecessary complexity?)

e) Skills to implement

f) Ease of maintenance

I like to take the approach of not exposing more data than you have to in selected areas
within the application. Exposure to CRUD (create,read,update,delete) level can be
implemented by views, stored procedures, roles, table priviligies, instead-of triggers and
other object level and column privileges.

The use of views is an excellent method of implementing security and hiding schema
relationships and relational database complexities. Each table has an equivalent simple
or complex view; the views may include instead-of triggers to re-direct DML to other
"hidden" tables for complex views, for auditing or data partitioning. If instead-of triggers
to do appeal to you, another option for managing CUD (create/update/delete) access is
to grant select only access to the views and implement all CUD via predefined stored
procedures. Therefore, the database users view of the actual database structure may be
quite different from that of the schema owner and how they manipulate it is restricted by
the stored procedures (business rules).

Another approach is only using stored procedures for insert, delete, update and select
access and access to the database schema is only via these stored procedures. This can
have significant performance benefits also due to caching of procedure execution plans.
On top of this, you can lever the benefits of OPEN XML.

Getting back to security, you can effectively deny all access to tables, and implement all
CRUD through stored procedures. The only problem with this is a T-SQL one, which is its
poor exception handling (ie. none!).

The use of views and stored procedures also assist in application maintenance (no
embedded SQL statements in your COM+ and ASP code) and makes impact analysis of
schema change and performance tuning much simpler.

334
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

NOTE - It is important to remember that you do not need to grant CRUD access
to the tables and views and stored procedure is referring to, only to the procedure
itself.

Virtual Private Databases

The Oracle virtual private database option is managed via the DBMS_RLS (row level
security) package. This option allows fine grained access control (FGAC) to table and
view data, making sure a user only sees data they are allowed to see, no matter how
they access the data (SQL*Plus or a prewritten Application). There is no equivalent
option in SQL Server.

Label Security

The Label Security option use the virtual private database feature to implement row level
security. By creating policies, row data can be tagged (based on sensitivity) to assist in
managing and controlling access to table data.

Locking Down Extended and System Procedures


Securing xp_cmdshell (OS Shell)
The extended stored procedure xp_cmdshell allows you to shell out and execute an
valid operating system command. By default, all users allocated to the fixed system role
sysadmin (ie. SA account) have execute access.

This is a real tough command to administer. Why? every project I have worked on to
date has some need for it. Because of the fact that SA is the only user with sysadmin
access, rather than creating a special account or looking at other work-arounds, the SA
account is used to execute the task. Classic examples are stored procedures wrapped up
in DTS jobs or supposed global “administrative” functions. This is problematic because:

a) now “application” databases are using the SA account and rely on it to run their
jobs.

b) altering the SA password has application impact

c) xp_cmdshell will be executed under the security context in which the SQL Server
service is running

Points a) and b) are obvious and the fix is a simple matter of explicitly granting execute
access to xp_cmdshell via a role and allocating that role to a managed and secure
database user whose actual login is rarely used (ie. DTS connectivity only to run the
command shell tasks).

Point c) is the very important. If the database user is a member of sysadmin then, more
than likely, the user will have “local administrative” privileges to the server, as this is the
user running the MS SQLServer and associated services. This is even more the reason
why not to use the SA account. If the user is not a sysadmin but has been granted

335
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

execute access as described above, then the SQL Server Agent proxy service user will be
used instead.

The SQL Server Agent proxy account can be altered via xp_sqlagent_proxy_account
(undocumented in BOL) which defines the account used to run the SQLServerAgent
service. This may be your SQLServer NT user if you are not using the Administrator
account (which is bad security practice), so you may decide to alter this to another user
with restricted access rights for finer control to the operating system.

In the end, xp_cmdshell should be carefully evaluated before using it. Ideally it should
be totally disabled (revoke execute permission) for ultimate security. Look at using isql
jobs scheduled via AT and look closer at the options available to you via DTS.

Securing xp_cmdshell (OS Shell)


The security check-list from www.sqlsecurity.com mentions a variety of other extended
stored procedures to lock down where possible. In the end, I believe its better to
‘disable’ them rather than simply removing them and loosing functionality in Enterprise
Manager or other 3rd party products. With strict role management and user security
they should not be accessible. The list is (not definitive by any means):

OLE Automation
Sp_OACreate
Sp_OADestroy
Sp_OAGetErrorInfo
Sp_OAGetProperty
Sp_OAMethod
Sp_OASetProperty
Sp_OAStop

Registry Access
Xp_regaddmultistring
Xp_regdeletekey
Xp_regdeletevalue
Xp_regenumvalues
Xp_regread
Xp_regremovemultistring
Xp_regwrite

Other routines
sp_sdidebug
xp_availablemedia
xp_cmdshell
xp_deletemail
xp_dirtree
xp_dropwebtask
xp_dsninfo
xp_enumdsn
xp_enumerrorlogs
xp_enumgroups
xp_enumqueuedtasks
xp_eventlog
xp_findnextmsg
xp_fixeddrives
xp_getfiledetails
xp_getnetname
xp_grantlogin
xp_logevent
xp_loginconfig
xp_logininfo

336
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

xp_makewebtask
xp_msver
xp_perfend
xp_perfmonitor
xp_perfsample
xp_perfstart
xp_readerrorlog
xp_readmail
xp_revokelogin
xp_runwebtask
xp_schedulersignal
xp_sendmail
xp_servicecontrol
xp_snmp_getstate
xp_snmp_raisetrap
xp_sprintf
xp_sqlinventory
xp_sqlregister
xp_sqltrace
xp_sscanf
xp_startmail
xp_stopmail
xp_subdirs
xp_unc_to_drive

Data Transformation Services


Disabling the following via a role or revoking PUBLIC execution to lock down data
transformation tasks (all in the MSDB database):

sp_add_dtspackage save dts into sysdtspackages


sp_enum_dtspackages open dts package
sp_add_job adds new job executed by the SQLServerAgent service
sp_add_jobstep add new step for a job created above

It should be very rare that DTS creation and editing in production is required unless of
course during emergency fixes. You may have routines that dynamically create jobs, add
job steps (classic examples are backup routines) where the above may need to be
rethought, but in a majority of cases DTS can be safely locked out.

By default in SQL Server 2k the DTS job is encrypted but unless you specify a password
they remain editable.

It is important to remember that SQL Servers access model for DTS packages is, well,
limited. Meaning that only members of sysadmin can edit and save any package they
like, but all other users are restricted only to the packages they initially created
themselves. This holds true even when you try and give users dbo access to the MSDB
database in a vain attempt to “share” packages with other database users. To get
around some of these issues read the chapter on Managing Databases.

System, Object Privileges and Roles


Within Oracle, we have System Privileges (80+) and Object Privileges, many of these
privileges do not extend to the data dictionary objects, for example 'update any
table' or 'select any table' privileges will not flow over to the data dictionary tables.

337
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Within the SQL Server architecture these privileges are wrapped up into server roles
that exist at a variety of “levels” within the instance. These are shown below:

a) System Privs - Instance Level - unknown as a "fixed server role"


b) System Privs - User database level - unknown as a "fixed database role"
c) Object Privs - permissions allocated to distinct object or to other roles
d) Statement Privs - ability to perform a "statement", namely create table
etc.

The roles of course are similar to Oracle roles, where a fixed role allocation can
provide to user with numerous bundled system and object privileges.

Example fixed server roles (instance level) are:

Example fixed server roles (database level) are:

Example statement privileges are:

BACKUP DATABASE
BACKUP LOG
CREATE DATABASE
CREATE DEFAULT
CREATE FUNCTION
CREATE PROCEDURE
CREATE RULE
CREATE TABLE
CREATE VIEW
CREATE INDEX
CREATE STATISTICS
<..etc..>

Example object level privileges are:

GRANT ALL ON mytable TO myrole


GRANT INSERT,DELETE,UPDATE,SELECT ON mytable TO myuser

Typically, such statement privileges are naturally inherited from fixed server roles
and other fixed database roles. For example, CREATE DATABASE is granted
automatically
with the sysadmin and dbcreator fixed server roles. On top of this, you may also
get extended privilege (WITH ADMIN in Oracle) to grant this statement privilege to
other
users as the sysadmin and securityadmin fixed server roles can do. This can become
somewhat complex and its well worth exploring in details before allocating fixed
server and fixed database roles to any user.

We will not compare every Oracle system privilege with SQL Servers statement and
other privileges, but, we will compare SQL Server fixed server and database roles
with Oracle.

338
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Fixed Server Roles (Instance)

The fixed server roles in SQL Server are basically made up of the SYSDBA and SYSOPER
accounts and the grant DBA privilege in Oracle. The permissions are high level ones that
are really aimed at the DBA or the System Administrator. In no circumstance should you
allocate any other user to these accounts.

I do not grant any user these privileges, think long and hard account your senario before
giving an account access to these (typically the db_owner database privilege is the
highest I would grant).

The roles are:

Role Name Used for?


Bulk Insert Administrators Similar to the import/export privilege in Oracle but via the
bulk insert DML statement.
Database Creators Can create user databases. DBA should never allow this for
backup and recovery purposes.
Disk Administrators Can manage any database file group data files
Process Administrators May be allocated during development only to allow developers
to kill off running DTS jobs.
Security Administrators Manage user account, create databases, read error logs.
Server Administrators Can alter instance settings, DBA only.
Setup Administrators Manage linked servers and startup permissions.
System Administrators DBA only (sysadmin role)

To get an better idea as to what is included in the privilege, use EM, Security Æ
logins Æ select a user, properties, Server Roles tab, select a role and click
properties, for example:

Fixed Server Roles (Database)

For each database the following fixed roles exist:

Role Name Oracle Equivalent Used for?


Fixed Role
Db_owner (dbo) CONNECT DBO owner account (DBA only)

339
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

RESOURCE
DBA
Db_datareader N/A Read access to any table or view
but not stored procs or UDF’s.
Db_datawriter N/A Write access to any table or view.
Db_ddladmin CONNECT Alter or create or drop any user
RESOURCE definable database object.
DBA
Db_backupoperator SYSDBA Can issue backup, checkpoint,
SYSOPER DBCC commands.
EXP_FULL_DATABASE
IMP_FULL_DATABASE
Db_securtityadmin CONNECT Deny, grant and revoke
RESOURCE permissions.
DBA
Db_accessadmin CONNECT Can add or remove users.
RESOURCE
DBA
Db_denydatareader N/A As per data reader by deny the
privilege.
Db_denydatawriter N/A As per data writer by deny the
privilege.

Oracle recommends you don’t use the predefined roles, but build a custom set of
privileges.

User Defined Roles

The name explains it all, they are the same in Oracle. They are simple enough to
manage and require no explanation. The DBA cannot alter fixed database and instance
roles.

Object Privileges

The management of object level privileges is Oracle and SQL Server are essentially the
same. The DBA can grant the basic select, insert, update, delete, execute, and
references (DRI) privileges to tables, views, stored procedures and user defined
functions. At a lower level, the DBA can also grant virtical security at a column level via:

GRANT UPDATE ON [dbo].[mytable] ([mycolumn]) TO [myuser_role]

Removal of privilege is via the REVOKE command:

REVOKE REFERENCES ON [dbo].[efs] FROM [public] CASCADE

Use the DENY command if you want to retain the permission in the role and/or user but
close off access temporarily.

The CASCADE option will revole the privilege for all users part of the role, in this case the
public role.

The public role should be left alone where possible, meaning that the DBA should create
their own version of the role and allocate privileges through that. The public role includes
these standard permissions begin tran, print, rollback tran, set, commit tran, raiserror,
save transaction.

340
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

No database user in SQL Server can create objects with being explicitly granted the
permission to do so. The DBA should carefully consider the implications of granting the
the db_ddladmin database role or explicity granting the create table or view statements.
The objects by default will be owned by the user unless explicitly prefixed with dbo.

This is unlike oracle where we would need to revoke access to say, create table etc
after allocating the 'connect' role.

Auditing
Application Auditing
There are no SYS$AUD objects as in Oracle to assist the SQL Server DBA with auditing of
user databases and its objects; this is a right pain as the classic fix is typically a range of
triggers that log inserts, updates, deletes against the table(s). Here is an example of
some simple auditing in action:

Source Table : dbo.MyTable (trigger on this table)


Audit Table : dbo.MyTable_Audit
Audit actions column on audit table: 1 = Insert, 2 = Update, 3 = Delete

CREATE TRIGGER dbo. MyTable_Audit_Trigger ON dbo.MyTable


FOR INSERT, UPDATE, DELETE
AS
DECLARE
@insert_count int,
@delete_count int,
@current_time datetime

SET NOCOUNT ON
SET @current_time = GETDATE()
SET @insert_count = (SELECT COUNT(*) FROM INSERTED)
SET @delete_count = (SELECT COUNT(*) FROM DELETED)

/* A new record is inserted */


IF @insert_count > 0 AND @delete_count = 0
BEGIN
INSERT INTO dbo.MyTable_Audit
(
col1_code,
col2_desc,
update_count,
last_updated_on,
last_updated_by,
Audit_Action, Modified_By, Modified_Time
)
SELECT
access_type_code,
col2_desc,
update_count,
last_updated_on,
last_updated_by,
1, last_updated_by, @current_time
FROM INSERTED
END

/* A record is updated */
IF @insert_count > 0 AND @delete_count > 0
BEGIN
INSERT INTO Dbo.MyTable_Audit

341
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

(
col1_code,
col2_desc,
update_count,
last_updated_on,
last_updated_by,
Audit_Action, Modified_By, Modified_Time
)
SELECT
col1_code,
col2_desc,
update_count,
last_updated_on,
last_updated_by,
2, last_updated_by, @current_time
FROM INSERTED
END

/* A record is deleted */
IF @insert_count = 0 AND @delete_count > 0
BEGIN
INSERT INTO dbo.MyTable_Audit
(
col1_code,
col2_desc,
update_count,
last_updated_on,
last_updated_by,
Audit_Action, Modified_By, Modified_Time
)
SELECT
col1_code,
col2_desc,
update_count,
last_updated_on,
last_updated_by,
3, last_updated_by, @current_time
FROM DELETED
END

If you are using identity columns on your trigger tables as well as the sourse table, then
the application must use the @@SCOPE_IDENTITY() function to source the correct
identity value from an insertion. The last thing you want to do is to capture the identity
value from the trigger table.

342
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Expanding on the trigger and tables above, the scenario we are using is this:

USERA

Application logs in via


USERA (OS Authenticated single (or very few) actual
via Basic Authentication on DBMS accounts as defined
Web Site, 1 of 8000 users) by INI file.

Mycom.ini
USERX
COM+ component
(business layer) connects
to DBMS via USERX in INI select only
file access

mytable mytable_audit

Trigger fires

This creates some issues the DBA must be aware of, namely:

• if triggers are off (disabled) whilst initially migrating data into the table, then you
will not record the first “insertion” audit entry for the record. This may have flow
on issues later down the track.

• The application layer must manage issues with concurrency in a stateless web
environments. This is typically done by columns for each table such as
update_count, last_updated_on, last_updated_by which can also be used for
auditing. As in the example above, last_updated_by must be passed in from the
application and not sourced from the DBMS.

• If you don’t update the record before deleting it, then you will capture the wrong
user who actually performed the deletion, as we are simply using the
last_updated_by column to record the user who performed the operation. As
mentioned in c), we can not use the USER_NAME() system function as all users
stream through a single (common) login via the applications business layer.

The DBA should work closely with the developers and establish the auditing schemes
early on in the project cycle, especially in terms of recording update by and updated on
information. The DBA should ask:

• retention period of audit table, how will it be purged or moved?

• how the end users will interact (search) over the audit data and the associated
indexing issues. How will the added indexing affect OLTP performance?

• will you create a separate file-group to store audit data tables?

343
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

• how roles will be used to control CRUD access to the audit tables

• consider writing a generic audit display framework for your application rather than
writing custom reports

• have you considered third party applications?

• remember the text, ntext and image restrictions within triggers and communicate
these to the analysts/developers

Profiler (trace)
The DBA can also audit via profiler, letting it run for a period of time collecting a variety
of events for the DBA to review (use sp_trace rather than the GUI, use the GUI to
generate the script for you). Although fine, this method may not be practical and may
drive down performance slightly.

The trace utility will not trace sp_addlogin and associated routines dealing with
passwords.

Instance level auditing


Apart from application based auditing and using profiler, the DBA can audit some basic
DBMS events. Within EM, right click and select properties for the instance. Click on the
security table and we get:

exec xp_instance_regwrite
N'HKEY_LOCAL_MACHINE',
N'SOFTWARE\Microsoft\MSSQLServer\M
SSQLServer',N'AuditLevel',
REG_DWORD,2

A restart may be required for the property to take affect due to the registry change. To
read the current value, use the command:

exec xp_instance_regread N'HKEY_LOCAL_MACHINE',


N'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer', N'AuditLevel'

344
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

C2 Level Auditing

For detailed information on C2 level auditing in SQL Server see the books online. I would
not recommend it unless you have explicit requirement to do so.

Encryption / Obfuscation Options


Networking Options

See the chapter on Networking for more information on protocol encryption. Basically,
SQL Server supports 40 and 128bit SSL encryption of its listener protocols and of course
standard NOS encrypted Windows authentication (kerberos), whereas Oracle supports a
large range of other encryption methods through the Oracle Advanced Security option.
Most will agree that SSL is the better way to go.

Encrypted File System


In the Windows 2000 server environment, the DBA can utilise the EFS (encrypted file
system) option to secure database files and database backups files at the operating
system file level. This option facilitates file encryption via the Windows Crypto
Architecture feature and associated public key infrastructure features.

Before using this option, the DBA should have their instance service(s) running under a
custom NT user rather than the Administrator account, see Secured Installation
previously discussed.

Login as the service account and shutdown all instance services. Once done, goto the
directory you want to EFS encrypt via Explorer, right client properties, advanced button
and check the encrypt contents to secure data option:

IMPORTANT – Backup all files before attempting encryption.

345
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

You may be prompted about encrypting the this folder only or this folder and all sub-
folders, and then asked about encrypting the parent folder (does all existing and any new
files in the folder) or just this file, in most cases you will want the entire folder:

Only the user that encrypted the files can de-encrypt.

To check on the status of encryption via the command line, utilise the cipher.exe
command with no parameters. The “U” of course meaning un-encrypted. Take a close
look at the command options via the /? Switch, namely the /E (encrypt) and the /D (de-
encrypt) switches.

Note that windows binaries cannot be encrypted.

WITH ENCRYPTION option

The WITH ENCRYPTION option can be used with stored procedures and views to encrypt
their contents. I wanted to believe that SQL Server 2k under Windows 2000 was using
the Windows Crypto API and as such, was using a key complex enough to make hacking
very difficult. Then I came across this article from www.SecuriTeam.com:

346
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

http://www.securiteam.com/windowsntfocus/6Q00H2A3FY.html

I have to say that security specialists and hackers are some of the most sarcastic people
I know! but with good reason. The articles example, which I have tested under SQL
Server 2k, shows you all the code of a stored procedure created with the WITH
ENCRYPTION option.

Here is an extract from this article regarding SQL Server 2k encryption:

“Here is how stored procedure (and view and trigger) encryption works on SQL Server 2000:
1. Take the database's GUID (generated when the db is created), the object id (from sysobjects) and the
colid (from syscomments) and concatenate them.
2. Hash the key using SHA.
3. Use the SHA hash as an RC4 key, generate a sequence of bytes equal in length to the stored procedure
text.
4. XOR this stream of bytes against the stored procedure text.”

The example given in the article works with any user that has priviligies to create and
alter procedures and select access against syscomments. To help mitigate the problem:

a) Deny SELECT access to PUBLIC against syscomments

b) Deny create and drop procedure commands

c) See previous notes on restricting DBO access and sysadmin access to your
database.

With all this said, I believe it is still worth the effort to encrypt code. It is though,
imperitive that your test t-sql code execution thoroughly to determine the CPU impact
this may have on execution (though I would imagine it to be very small).

T-SQL

There are no native encryption or obfuscation options available to the T-SQL developer
with SQL Server. In Oracle the developer may utilise the dbms_obfuscation_toolkit, but
in SQL Server the developer must either code their own, or utilise another language and
its API calls (OS or language dependent).

Some DBA’s actually regard database encryption as bad practice. I tend to disagree and
can think of a variety of reasons where, especially one way encryption, would be
required. The trick here is private key management and exposure of the de-encryption
functions/routines. This requires very careful planning and realisation of the security
risks and possible litigation if data is cracked. Developers in .Net will find the new system
calls very helpful.

347
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

INDEX
Data transformation service · 237
Data types in SQL Server · 306
A Database connection · 17
Database links · 229
ado-md · 217 DATABASEPROPERTYEX · 85
alert log · 227 Datafiles · 5
Archived redo log · 7 Date functions · 295
authentication · 325 DBCC · 65
DBCONTROL · 85
DBMS_JOB · 284
B DBMS_LOB · 287
DBMS_MAIL · 283
Backup DBO privilege · 328
history of · 95 dbrepair · 104
no more space · 96 DBVERIFY · 65
backup set · 78 DbwN · 20
BFILE · 287 Deadlocking · 126
Block size · 25 developer
boot.ini · 11 security rights · 329
Buffer cache · 12 diagrammer
BUILTIN/Administrator · 326 scripting · 90
BUILTIN/Administrators · 53 differential backup · 81
bulk insert · 66 dso · 217
Dynamic SQL · 309
C
E
cell security · 215
CHECKALLOC · 104 Editions · 37
CHECKDB · 104 Encrypted file system · 44
Checkpoint · 18 encryption
Ckpt · 20 multi-protocol · 319
Client Network Utility · 316 error log · 227
collation Explain plan · 137
database · 203 Extended stored procedures · 18
Collation Extents · 26
Column · 204
COM+ · 169
COM+ isolation level · 171 F
COM+ proxy · 172
command shell · 281 Federated databases · 187
component load balancing · 185 File IO statistics · 160
Connection · 17 Fillfactor · 26
Control file · 4 for xml · 283
Corrupt Fragmentation · 30
indexes · 104 FREELISTS · 26
Counters full backup · 80
performance monitor · 142 Functions
user defined · 278

Data dictionary · 5

348
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

G M

Global allocation map page · 27 maintenance plan


GUI tools · 58 backups · 75
MDAC · 2
media set · 78
H metadata · 283
Moving
High Water Mark · 33 master database · 55
Hints MSDB and MODEL databases · 55
Comparison · 304 TEMPDB database · 57
HINTS · 302 MTS · 322
Multi-protocol · 315

I
N
IAM · 28
identity · 289 network load balancing · 183
Index Network monitoring · 320
tuning wizard · 134 Northwind
index types compared · 289 re-install · 105
Indexes Numerical functions · 293
composite · 152
fragmentation · 156
function based · 152 O
rebuilding · 158
skewing · 155 Object
types of · 150 change owner · 253
information schema · 283 check ownership · 253
installation ODS · 317
security of · 323 olap
Installation · 37 administer · 210
Instance · 1 backup · 219
Named · 4 installation · 208
repository migration · 211
security · 215
J storage models · 213
Open Data Services · 317
JServer · 66 OPENQUERY · 236
OPENROWSET · 235
OPS$ login · 252
K Optimal Flexible Architecture · 48
orphaned session · 256
Kill user sessions · 254
Killing users · 92
P

L Package · 278
pad_index · 26
Label Security · 335 Page free space · 27
Latch statistics · 140 Page splitting · 140
Lgwr · 20 Page types · 25
License Manager · 40 Parallel
Licensing · 38 affinity option · 301
Linked Server · 229 IO · 302
Listener · 68, 313 query · 301
log miner · 69 password file · 328
log shipping · 189 passwords
login vs user · 325 finding null · 328

349
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

Performance monitor · 142 xp_cmdshell · 335


Pmon · 20 Segments · 35
Procedure cache · 15 sequence · 289
Profiler SERVERPROPERTY · 40
example events · 131 Service account · 43
saving scripts · 133 Service accounts · 53
services
re-creating · 257
Q set nocount · 172
Setup · 42
Query Analyser · 68 Shared global allocation map page · 27
SHOWCONTIG · 30
Shutdown instance · 84
R sp_spaceused · 28
Space Management · 26
RAID · 46 SQL Loader · 66
raw partitions · 258 SQL Trace · 67
Read-ahead · 13 SQLDiag.exe · 322
recovery interval · 72 SQLOLEDB · 319
recovery model · 73 STATSPACK · 69
Redo log buffer · 14 Stored procedure · 279
Relational engine · 35 stored procedures · 172
REPAIR_REBUILD · 104 String functions · 294
Resource Striping · 49
File · 206 Suspect Database · 99
Restore SVRMGRL · 65
emergancy mode · 102 SYS login
file added · 101 equivalent · 327
file group · 101 SYS$AUD · 341
filelistonly · 96
full backup · 103
loading mode · 100 T
logical names · 96
master database · 97 table · 287
MSDB and MODEL databases · 99 Tablespace · 22
point in time · 104 tablespace backup · 83
rebuildm.exe · 106 Tablespaces · 6
suspect database · 99 temporary · 7
tempdb · 105 Task manager · 169
with file move · 100 TDS · 321
RMAN · 75 tempdb · 256
rollback · 110 Temporary tablespace · 23
Rollback segments · 7 timezones · 296
Tracing · 130
black box · 139
S system functions · 134
trace flags · 147
SA account · 327 transaction log backup · 82
scripting · 220 TRUNC() · 296
Scripting · 89 truncate
security transaction log · 83
auditing · 341
c2 auditing · 345
data transformation services · 337 U
encrypted file system · 345
object permissions · 340 UMS · 11
tracing · 344 unique identifier · 292
via views and stored procedures · 333 update statistics · 261
WITH ENCRYPTION · 346 uptime · 257

350
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

User V
database ownership · 252
orphaned · 251 Versions · 37
resource quota · 252 Virtual address space · 11
user accounts virtual private database · 335
quotes, resource restrictions · 328
user defined function · 288
W

Wait statistics · 160


Worker threads · 21

351
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

References
Please take the time to refer to these references from DBA experts around the world.

(1) What is the Maximum page size in SQL Server 2000?, Steve Jones, 7/2/2002,
http://www.sqlservercentral.com/columnists/sjones/pagesize.asp
(2) SQL Server 7: Some Useful Undocumented DBCC Commands, Alexander Chigrik,
22/10/2001,http://www.sqlservercentral.com/columnists/achigrik/sqlserver7someusef
ulundocumenteddbcccommands.asp
(3) Oracle Concepts: The Instance and the Database, Joe Lax,
http://www.devx.com/dbzone/articles/laxseries/lax082001/lax082001.asp
(4) INF: Job to Monitor SQL Server 2000 Performance and Activity, Microsoft Support,
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q283696
(5) http://support.microsoft.com/default.aspx?scid=kb;EN-US;q272428
(6) Memory Management, Can a readme file contain extra memory, Kalen Delaney, March
2001, http://www.sqlmag.com/Articles/Index.cfm?ArticleID=16522
(7) Technology Comparison Discussion, Microsoft,
http://www.microsoft.com/sql/evaluation/compare/discussion.asp
(8) How to Migrate Unix based Oracle Applications to Windows and SQL Server, Microsoft,
http://www.microsoft.com/windows2000/migrate/unix/unixoracle.asp
(9) MS SQL Server 2000 Books Online
(10) Oracle9i Database : The Power of Globalisation Technology, An Oracle Whitepaper
[February] [2002]
(11) Best Practices for Globalisation using the Oracle 9i Internet Application Server,
Simon Wong, July 12 2001, v1.0
(12) Oracle 8i/9i and Microsoft SQL Server 2000 A comparative Study from a
Developers and DBA Perspective, Sriram Kumar, April 2002.
(13) SQL Server: Enterprise vs. Standard, Rahul Sharma, 19/4/2002,
http://www.sqlservercentral.com/columnists/rsharma/enterprisevsstandardedition.asp
#_ftnref3
(14) http://msdb.microsoft.com/library/en-us/vbcon98/html/
(15) Data Concurrency and Consistency, Oracle Documentation, Oracle 9i database
concepts,
http://otn.oracle.com/docs/products/oracle9i/doc_library/release2/server.920/a96524
/c21cnsis.htm#2841
(16) PRB: How to recover SQL Server After a Tempdb Database is Marked Suspect,
Microsoft Support, http://support.microsoft.com/search/preview.aspx?scid=kb;en-
us;Q288809
(17) Transferring a SQL Server Diagram, Brian Knight, 24/5/2002,
http://www.sqlservercentral.com/columnists/bknight/transferdiagram.asp
(18) Managing Rollback/Undo Segments in AUM (Automatic Undo Management),
Note:135090.1
(19) Creating, Optimizing, and Understanding Rollback Segments, Note:62005.1
(20) Inside SQL Sever: Parse, Compile, and Optimize, Introduction to the query
processor, Kalan Delaney, December 1999,
http://www.sqlmag.com/Articles/Index.cfm?ArticleID=7446
(21) Oracle Bulletin – Checkpoint Tuning and Error Handling
(22) Query Recompilation in SQL Server 2000, Thomas Davidson, Microsoft Corporation,
May 2002 [http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/dnsql2k/html/sql_QueryRecompilation.asp]
(23) www.sql-server-performance.com
(24) www.sqlteam.com
(25) Optimizing SQL Server Performance by using File and Filegroups, Alexander Chigrick,
27/9/2001, http://www.sqlservercentral.com/columnists/achigrik/fileoptimtips.asp

352
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

(26) Improving text and image column performance, Brian Knight, 1/4/2002,
http://www.sqlservercentral.com/columnists/bknight/textinrow.asp
(27) Microsoft SQL Server 7.0 Performance Tuning Guide, Henry Lau, Microsoft
Corporation, October 1998,
http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/dnsql7/html/msdn_sql7perftune.asp
(28) Microsoft SQL Server 7.0, Storage Engine Capacity Planning Tips, Microsoft
Coorporation, March 1999,
http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/dnsql7/html/storageeng.asp
(29) “What rules of thumb you live by when programming?”, SQL Server Central forum
posting(s),http://www.sqlservercentral.com/forum/topic.asp?TOPIC_ID=2772&FORU
M_ID=61&CAT_ID=5&Topic_Title=What+rules+of+thumb+you+live+by+when+progr
amming%3F&Forum_Title=Anything+that+is+NOT+about+SQL%21
(30) Inside Microsoft SQL Server 7.0, Book Sale Site,
http://mspress.microsoft.com/prod/books/2394.htm
(31) INF: How to Use KEEPFIXED PLAN to Disable Stored Procedure Recompilations,
Microsoft Support, http://support.microsoft.com/search/preview.aspx?scid=kb;en-
us;Q276220
(32) Minimizing the Number of Log Backups, Andy Warren, 11/5/2001,
http://www.sqlservercentral.com/columnists/awarren/logbackup.asp
(33) Logins, Users, and Roles –Getting Started, Andy Warren, 20/11/2001,
http://www.sqlservercentral.com/columnists/awarren/loginsusersandrolesgettingstart
ed.asp
(34) Don’t shutdown that database! Use Oracle 9i Online Object Redefinition, Chris
Lawson, Copyright 2002 Database Specialists,
http://www.dbspecialists.com/presentations/online_redef.html
(35) Network Load Balancing Service, Tony Norhrup,
http://www.mcpmag.com/reviews/Services/article.asp?EditorialsID=1
(36) http://www.microsoft.com/ntserver/downloads/bin/nts/clustering_apps.exe
(37) INF: SQL Virtual Server Client Connections Must be Controlled by Clients, Microsoft
Support, http://support.microsoft.com/default.aspx?scid=kb;EN-US;q273673
(38) http://www.microsoft.com/israel/events/presentations/teched2002/inf305.ppt
(39) New SQL Server 2000 Data Types, Brian Knight, 14/5/2001,
http://www.sqlservercentral.com/columnists/bknight/sql2knewdatatypes.asp
(40) INF: How to enable Analysis Services to use 3 Gb of RAM, Microsoft Support,
http://support.microsoft.com/search/preview.aspx?scid=kb;en-us;Q295443
(41) Intro to User defined functions, Garth Wells, 8/1/2001,
http://www.sqlteam.com/item.asp?ItemID=1955
(42) Information Schema Views, Brian Kelley, 9/1/2002,
http://www.sqlservercentral.com/columnists/bkelley/informationschemaviews.asp
(43) Keep SQL Server Up and Running – Availability enhancements in SQL Server 2000
can keep your business going 24x7, Kalen Delaney, Dec 2000,
http://www.sqlmag.com/Articles/Index.cfm?ArticleID=15742
(44) DBCC SHOWCONTIG, SQLMag.com Forum Post,
http://www.sqlmag.com/Forums/messageview.cfm?catid=3&threadid=6878
(45) Understanding MS SQL Servers SHOWPLAN Output, Microsoft,
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/sql
/maintain/featusability/showplan.asp
(46) http://webtool.rte.microsoft.com/tutor/perf_NT4.htm
(47) Transact-SQL Language Reference Guide, Randy Dyess,
http://www.transactsql.com/Manuscripts/tslrg.html
(48) Microsoft T-SQL Performance Tuning, Part 1: Analysing and Optimizing T-SQL Query
Performance on Microsoft SQL Server using SET and DBCC, Kevin Kline, 2002, Quest
Software
(49) Understanding Execution Plans Part 1, Robert Marda, 26/7/2002,
http://www.sqlservercentral.com/columnists/rmarda/understandingexecutionplans.as
p

353
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

(50) INF: Moving SQL Server Databases to a New Location with Detach/Attach
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q224071
(51) Microsoft SQL Server Administration FAQ,
http://vyaskn.tripod.com/administration_faq.htm
(52) MS SQL Server Performance Tuning and Optimisation for Developers, Part 3,
Configuring SQL Server for Performance, Adam Shapiro, 1997,
http://www.microsoft.com/technet/treeview/default.asp?url=/TechNet/prodtechnol/sq
l/maintain/optimize/dat412ef.asp
(53) Chapter 9 – Server Architecture, Microsoft,
http://www.microsoft.com/technet/treeview/default.asp?url=/TechNet/prodtechnol/sq
l/proddocs/intro/part3/75515c09.asp
(54) Oracle 9i Application Server: Availability, Scalability, and Manageability of J2EE and
Web Cache Clusters, An Oracle Whitepaper May 2002.
(55) Clustering Web Accelerators, Presented at IEEE WECWIS, San Diego, June 28th
2002, James Feenan, Patrick Fry, Ming Lei.
(56) How to Setup Log Shipping Microsoft SQL Server 2000, Purna Gathani.
(57) Like without model, Jasper Smith, 28/7/2002,
http://www.sqlteam.com/item.asp?ItemID=10060
(58) The FROM clause, Bill Graziano, 25/6/2002,
http://www.sqlteam.com/item.asp?ItemID=9867
(59) INF: Effect of Database File Additions or Deletions on Database Recovery, Microsoft
Support, http://support.microsoft.com/default.aspx?scid=kb;en-us;Q286280
(60) Quest – Knowledge Expert for Oracle Administration v6.1.1
(61) Developing Databases with Microsoft SQL Server 7.0 – Transaction Processing
(62) How to Diagnose and Fix Wait Locks, Cathan Kirkwood, 21/11/2002.
(63) Stored Procedures and Caching, Brian Kelly, 28/1/2002
(64) Managing Extended Properties, Bill Vaughan, July 2001, SQLMag.com
(65) Optimizing Stored Procedures to avoid recompiles,
http://www.transactsql.com/Articles/OSPR.html, Randy Dyess 2002
(66) Version Control for Stored Procedures, Andy Warren, 10/5/2002
(67) Understanding parallel queries in SQL Server v7.0, Scott Mauvais, May 2000,
http://www.mauvais.com/PubsCached/ZD-Parallel.htm
(68) Documented and Undocumented Trace Flags for SQL Server 2000 and 7.0, Randy
Dyess, 2002,
http://www.sqlservercentral.com/columnists/RDyess/traceflags_printversion.asp
(69) Indexed views in SQL Server 2000, Doug Carpenter, 18/10/2002
http://www.sqlteam.com/item.asp?ItemID=1015
(70) INF: How to Automate an Archive or Backup of OLAP Database, Microsoft Support,
http://support.microsoft.com/default.aspx?scid=kb;en-us;294287
(71) HOW TO: Setup and Troubleshoot a Linked Server to Oracle in SQL Server, Microsoft
Support, http://support.microsoft.com/search/preview.aspx?scid=kb;en-us;Q280106
(72) INFO: Limitations of Microsoft Oracle ODBC Driver for OLEDB Provider, Microsoft
Support, http://support.microsoft.com/default.aspx?scid=kb;en-us;Q244661
(73) Transact-SQL.com, http://www.transactsql.com/sprocs/sp_tempdbspace.html
(74) Index maintenance, Baya Pavliashvili, 06 Aug
2002,http://searchdatabase.techtarget.com/tip/0,289483,sid13_gci841586,00.html
(75) Using the SQL Server Transaction Log to Improve Database Availability and
Performance, Lev Vaitzblit, http://www.dbta.com/transactionlog/index.html
(76) How to restart SQL Server service at regular intervals?,
http://vyaskn.tripod.com/restart_sql_server_service.htm
(77) How to troubleshoot orphan users in SQL Server databases?,
http://vyaskn.tripod.com/troubleshooting_orphan_users.htm
(78) FIX: AUTO-SHRINK Option or DBCC SHRINKDATABASE May Slow Down SQL Server
2000 Performance, http://support.microsoft.com/default.aspx?scid=kb;en-us;296386
(79) Introducing Indexed Views – SQL Server 2000 unviels another path to peak
performance, May 2000, Kalen Delaney
(80) What's in an ADO Connection String?, John Peterson,
http://www.asp101.com/articles/john/connstring/default.asp

354
S Q L S E R V E R 2 0 0 0 F O R T H E O R A C L E D B A

(81) HOWTO: Set the SQL Server Network Library in an ADO Connection String,
Microsoft Support, http://support.microsoft.com/default.aspx?scid=kb;en-us;238949
(82) Securing your SQL Server, Brian Knight, 14/5/2001,
http://www.sqlservercentral.com/columnists/bknight/securitypitfalls.asp
(83) SQL Server Security FAQ, http://www.sqlsecurity.com/faq.asp
(84) Administering User and Security, Kevin Cox and William Jones, July 1997,
http://www.windowsitlibrary.com/Content/77/10/toc.html
(85) Are SQL Server userid’s and passwords passed in clear on the network?, Neil Pile,
5/2/2000, http://www.sqlmag.com/Articles/Index.cfm?ArticleID=14357
(86) http://www.microsoft.com/sql/techinfo/administration/2000/security.asp
(87) Permissions in SQL Server 7.0, Michael Deignan, June 1999,
http://www.sqlmag.com/Articles/Index.cfm?ArticleID=5392
(88) Multiple Vulnerabilities in Microsoft SQL Server 2000 and 7.0, Ken Pfeil, 2/1/2002,
http://www.ntsecurity.net/Articles/Index.cfm?ArticleID=23639
(89) SQL Server Security Checklist, SQLServerSecurity.com,
http://www.sqlsecurity.com/DesktopDefault.aspx?tabindex=3&tabid=4
(90) Microsoft SQL Server 2000 Security, Microsoft,
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/sql
/deploy/confeat/c05ppcsq.asp
(91) SA to be denied access, SQL Server Central Forum,
http://www.sqlservercentral.com/forum/topic.asp?TOPIC_ID=1978&FORUM_ID=5&CA
T_ID=1&Topic_Title=SA+to+be+denied+Access&Forum_Title=Administration
(92) Advanced Security Concepts, Nelson Howell and Ben Forta,
http://local.15seconds.com/issue/971130.htm
(93) http://www.microsoft.com/ntserver/techresources/webserv/iissecure.asp
(94) K-026: Microsoft SQL Server Admin Login Encryption Vulnerability, March 22 2000,
http://ciac.llnl.gov/ciac/bulletins/k-026.shtml
(95) Microsoft SQL Server Password Recovery, Password Crackers Inc,
http://www.pwcrack.com/sql.shtml
(96) How to I encrypt fields in SQL Server? Neil Pike, 5/2/2000,
http://www.sqlmag.com/Articles/Index.cfm?ArticleID=14035
(97) The SQL Server 7 hackers toolkit, Tom Sager, Xephon,
http://www.xephon.com/oldcode/Q016A01
(98) dSQLSRVD, SQL Server SysComments Decryptor, securiteam.com,
http://www.securiteam.com/tools/6J00S003GU.html
(99) Analysis of Microsoft SQL Server 2000 Stored Procedure Encryption,
securiteam.com, http://www.securiteam.com/windowsntfocus/6Q00H2A3FY.html
(100) Implementing row level security in SQL Server databases, Narayana Vyas
Kondreddi,
http://vyaskn.tripod.com/row_level_security_in_sql_server_databases.htm

355

You might also like