Chapter 14. Administrative Tasks for High Availability

Like the human body, Microsoft SQL Server needs care. When the body gets the right nutrition, sleep, and exercise, it performs at a higher level. If you ignore your body’s needs, you are at a higher risk of developing problems. Proactive administration of your SQL Servers is like daily exercise: your systems will tend to live longer and stay healthier. The topics in this chapter are there for a reason: in most cases they are not about only the administration of one particular technology related to SQL Server. This chapter addresses security, memory, transferring objects, and normal maintenance tasks, such as rebuilding indexes.

Note

Although monitoring is an administrative task, it is covered in its own chapter, Chapter 15. Performance is also an administrative task and is related to availability. For more information, see HA_Perf_And_Scale.doc, available on the CD.

On the CD

Examples of the automated tasks run internally in some parts of Microsoft can be found on the CD in DBAScripts.zip.

Security

The most basic—and arguably the most important—thing you can do from an administrative standpoint is to secure your Microsoft SQL Server 2000 instances. Beyond the obvious steps of putting your servers in racks, locking cases, and physically securing data centers (all of which were discussed in Chapter 2, how can you specifically secure things at the operating system and SQL Server layers? You need to address multiple threats. A few years ago it might have been good enough to throw up a firewall and make sure that your SQL Server was isolated. Unfortunately, the game has changed. Worms, viruses, and denial of service attacks—some of which are directed at your database, others of which are not—can compromise your data’s security.

When a Web site pops up on the evening news in a story about how it was hacked, it is a glaring example of how something can be compromised. But how do you measure what was compromised—especially sensitive data? Because many systems now access both internal and external systems, the potential for someone gaining unauthorized access increases dramatically unless you have dedicated security professionals making sure that you are protected. There have recently been cases where hackers have broken into an e-commerce site or into a bank and compromised large numbers of credit cards. Or think about the recent rash of identity theft. Do not assume it cannot happen to you or your systems. As important as your platform’s availability is, it is your data’s availability and security that you are really protecting. However, the reality is that sometimes security and availability do not always play nicely together in the sandbox, and you might have to make tradeoffs one way or the other.

Securing Your SQL Server Installations

You can do several things to ensure that your physical SQL Server installations are secure.

  • Do not use a blank or weak sa password. For obvious reasons, this can compromise your SQL Servers. Even before SQL Server 2000, it was a common practice in testing or development environments to use the SQL Server’s sa account with no password in testing or development environments. The unfortunate thing is that the practice followed into production and was never altered.

  • Passwords for all accounts—whether or not they are SQL Server and from system administrators on down to users—should not be weak passwords. Since there is no direct way to enforce stronger passwords, a weak or a blank password can be a problem if you configure your instance to only use SQL Server security. The recommended approach is to set SQL Server to use Microsoft Windows Authentication and to require your applications to use it as well. This allows you control at the Windows level. For example, you can create a group in Windows and place users in it. In SQL Server, you can then assign a login to that group and add that login as a user to a database. Now, when you want to have someone gain access to the database, your administrators can do it in a standard way. In addition, you can force your Windows users to change passwords on a periodic basis, you can enforce strong passwords, and you can take other measures to ensure that you are protecting your data.

    Important

    Even if you use Windows Authentication, you must still set a strong password for the sa user. If you just select Windows Authentication, the sa user still exists in SQL Server, but a password is not set. Also, if you later change to Mixed, you might need to use sa.

  • The service accounts used in your environments, especially ones for SQL Server, should not have unneeded privileges, nor should SQL Server share the same account (with the same password) with every other application on the server. This means that the use of accounts like LocalSystem or a domain administrator is strongly discouraged. That way, if someone accesses your SQL Server, that person cannot then turn around and use something like xp_cmdshell to attack the rest of your environment.

  • Install SQL Server only on NTFS partitions.

  • Never install SQL Server 2000 instances on a domain controller unless it is absolutely necessary. Doing so might expose your data to attackers who can gain escalated user permissions through some other method.

  • Stay abreast of security patches, hotfixes, and service packs. As noted in Chapter 13, you should evaluate all updates to see if they need to be installed; if they enhance your security, apply them!

  • Where possible, set your SQL Server instances only to Windows Authentication, sometimes known as Integrated Security. Doing so permits centralized account management and the use of other protocols such as Kerberos. If you use SQL Server authentication, use Secure Sockets Layer (SSL), at a minimum, to encrypt the login packets as well as strong passwords (which you must enforce yourself). Never use blank passwords.

  • Turn on auditing in SQL Server. Although this might cause overhead, you can track failed login attempts and then take care of the problem. This is done by setting the Audit Level in the Security tab of your server properties, which is shown in Figure 14-1. Setting it to Success records successful logins. Failure records unsuccessful logins. Setting it to All records both.

    Security tab of Properties.

    Figure 14-1. Security tab of Properties.

    Note

    Turning on the auditing feature will cause you to cycle your SQL Server, causing an availability outage.

  • You are strongly advised to use Enterprise Manager to change your service accounts, as there are file system and registry dependencies that go along with a change in service accounts. You do this in two places:

    • SQL Server service account. You change this in the Security tab of your instance’s properties.

    • SQL Server Agent service account. You change this in the General tab of the SQL Server Agent (see Figure 14-2), which is in the Management folder in Enterprise Manager.

      The General tab of SQL Server Agent Properties.

      Figure 14-2. The General tab of SQL Server Agent Properties.

If you do not change the passwords in the recommended way in Enterprise Manager, it might be possible to use the Services utility. The problem is that doing it there will not reset the correct registry keys or NTFS permissions in all cases. For a full list of what you would have to alter after using Services, see Knowledge Base article 283811, "HOW TO: Change the SQL Server Service Account Without Using SQL Enterprise Manager in SQL Server 2000" (available at http://support.microsoft.com/).

Warning

You can use only the Windows-level Services utility to change password accounts on nonclustered SQL Server instances.

Important

Changing your service account passwords will require you to stop and start the associated SQL Server services. So you must plan for this availability outage.

  • Use Server Network Utility to change the port to a static port that is known only to you. By default, the first instance installed on your server or cluster will try to take port 1433, which is a known port for SQL Server and can potentially be exploited. To access Server Network Utility, you can find it in the Microsoft SQL Server folder of the Programs menu. Once it is started, select your instance in the dropdown list, select TCP in the Enabled protocols list, and then click Properties. You can then modify the port number (see Figure 14-3).

    Modifying your port.

    Figure 14-3. Modifying your port.

    Important

    Two instances on the same server cannot share the same port number. If you are using a version of the Microsoft Data Access Components (MDAC) prior to MDAC 2.6, you might need to physically put this port number in the connection string, as it will not be 1433.

  • Avoid using User Datagram Protocol (UDP) port 1434 at a firewall if possible. This is the SQL Server listener.

  • Use the Microsoft Baseline Security Analyzer (http://www.microsoft.com/technet/security/tools/Tools/mbsahome.asp) to help you assess your environment, including SQL Server. It will scan for known things such as blank sa passwords, file and registry permissions, exposure of xp_cmdshell to users who are not system administrators, and more. Version 1.1 or later supports multiple instances of SQL Server.

  • Do not configure unnecessary features, tools, and utilities, and do not install more software on your SQL Server machine than you need to.

  • Never change the default permissions on xp_cmdshell. Restrict the people who can have access to this extended stored procedure by not configuring users as system administrators.

  • Never allow anyone to access your SQL Servers directly. Using a method such as Terminal Server will allow you not only to see who is logging into the machine, but also to prevent physical access to the server.

  • You can use SQL Profiler to audit events. For information on how to do this, see SQL Server Books Online, available with the SQL Server installation.

  • Scan and remove logins with NULL passwords. On a regular basis, evaluate and remove old and unused logins; this might prevent unauthorized access.

  • Make sure that when you are assigning roles, you trust the user that you are giving privileges to. Although this seems obvious, the point is to put thought into what roles you assign to users.

  • Secure your startup procedures.

  • Always verify your file and registry key permissions, as outlined in the earlier Knowledge Base article 283811.

  • After you install a service pack or an instance (or something else), passwords might be exposed in the installation or log files. To scan those files and remove any potential offending exposures, Microsoft Product Support Services (PSS) has a tool called KillPwd that you can download from http://download.microsoft.com/download/SQLSVR2000/Utility/2.0/W98NT42KMeXP/EN-US/killpwd.exe. For instructions on its use, consult Knowledge Base article 263968, "FIX: Service Pack Installation May Save Standard Security Password in File."

  • SQL Server supports the encryption of your file system. As of Windows Server 2003, it is also supported with SQL Server 2000 failover clustering. Using it will decrease the chance of someone using a text tool to read your data or backup files, but you must account for any system overhead incurred.

  • You can enable C2 security with SQL Server 2000 if it is necessary.

More Info

To see how to use C2 with SQL Server 2000, see the "SQL Server 2000 C2 Administrator’s and User’s Security Guide" at http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/sql/maintain/security/sqlc2.asp.

Securing Your SQL Server–Based Applications

As a database administrator (DBA), or as someone who will be performing database-related tasks, whether you like it or not, you are responsible for every application’s database in your environment. Although you might control the back end, developers control the front end. It is in your best interests to validate custom database-specific code and ensure that packaged applications will work with your security model. Here are some tips to consider:

  • When coming up with the architecture for your application, how will you access the database? You have essentially three options: flowing the user to the database, using a single Windows context to the database, and using a single connection to the database using SQL Server authentication.

    If you use flowing, all machines must be part of the same domain or be trusted, Kerberos and delegation must be enabled, and impersonation must be enabled in ASP.NET. This will allow you to enforce security for SQL Server and audit all user actions. If, however, you have external components (such as outside vendors accessing the application), this might not be feasible, and connection pooling is limited since you cannot share connections.

    If you use Windows Authentication, run ASP.NET as a nondomain administrator. The users would authenticate at the application component, and the connection to the database is made in the context of the ASP.NET account (usually ASPNET user). This account should not have a system administrator role in SQL Server. With this method, you do not have to store passwords or pass any credentials to SQL Server, connection pooling is possible, and running ASP.NET as a low privileged account will minimize risk.

    If you are using SQL Server authentication, the application is using SQL Server to authenticate your login. You now need to ensure that all logins have the correct privileges at the SQL-level and to force users to enter strong passwords. You can use secure credentials at the middle tier using data protection application programming interfaces (APIs) to encrypt the credentials, which means that only that account can decrypt. The problem with this method is that you now need to store credentials, and SQL Server authentication, by its nature, might not be as secure as Windows Authentication. But you can work across firewalls and nontrusted domains and use connection pooling. If you do not have a specific limitation in your application, it is highly recommended that you design and deploy using Windows Authentication to grant user access and privileges.

  • If your company is writing an application (or has hired contractors to write one), make sure that they have the skill and experience to implement your company’s security policies through the use of things like correctly privileged logins and roles. No single user should be doing everything in the application. At the very least, you should have a separate user and administrator account. Since many developers install SQL Server on their machines, they incorrectly assume that all database access requires credentials equivalent to a highly privileged administrator.

  • Some developers might hardcode the sa user directly into the application, which is not only bad for security, but which also might hurt you if you need to use another server for a warm standby. Do not allow a developer to hardcode passwords, ever!

  • For a security model, Windows Authentication should be your first choice, if possible. Because the control is now at the network level, not in the application, your application is, by default, easier to secure. Passwords are stored in one place (at the domain controller), and you can combine Windows Authentication with some sort of encryption to secure your connections. Active Directory directory service can assist you in centrally managing your passwords.

  • If possible, use some form of encryption (Internet Protocol Security [IPSec], SSL, Kerberos, or other forms of encryption, such as data encryption with third-party tools like Protegrity) in your application or database. If you are doing things like passing credit card numbers, performing online bank transactions, sending Social Security numbers, and doing other sensitive operations across a network, you do not want to transmit these as clear text in an HTML stream that could be sniffed or found in a log somewhere.

  • Know your connection method. If you do your best to encrypt data, but your underlying protocol winds up sending passwords and SQL statements through text, you need to mitigate this somehow by using another form of encryption like SSL, IPSec, or Kerberos to encrypt the connection as well as the underlying data access protocol.

  • When designing the schema, make sure that roles, and not users, own all objects. If, for some reason, the user is dropped or renamed, you will not have any issues of access to the object.

  • Use ownership chaining to mask or hide the actual schema by using views and stored procedures, and not direct SQL statements, to go against base tables in your database. If the object and the user calling it have the same owner, the underlying permissions check is skipped. This not only makes your code secure, but more efficient. Consider the following example:

    You have an Orders table in your sales database created by User1. To access it, User2 creates a stored procedure to retrieve data from the table, which also includes some potentially sensitive information. If User3 tries to execute User2’s stored procedure, SQL Server will check both the execute permissions for the procedure as well as the SELECT permissions on the underlying table created by User1. However, if you created the stored procedure with User1 and granted execute permissions to User3, since User1 is the owner of both the table and the stored procedure, only one permissions check is needed.

  • Perform code reviews to ensure that the code is safe to implement (like making sure your application is available and scalable, among other things). A code review should be a formalized, regular process. Similarly, your company should develop coding standards that can govern the creation of code.

  • Developers will often put debugging code used for testing or messages into the application that might be accidentally exposed or be too technically informative to an end user. You should remove the information that is presented (such as account names, passwords, Internet Protocol [IP] addresses) prior to rolling the application out in production.

  • The application should also disallow any ad hoc queries. A savvy person might use a text field he or she knows is issued as part of a SQL statement and use it to do something malicious. You should validate all user input and reject anything that does not meet the standards of your company’s security policy. Along the same lines, if you can, attempt to avoid using dynamic SQL statements within a stored procedure.

  • Although focusing on code is important, developers need to also think about how the application could be compromised through something like a denial-of-service attack or exposing problems (publicly known or not yet known) through standard interfaces. For example, if a hacker gains access to your Web server, that person might now have access to your entire enterprise. How you have your security model will determine how far the hacker will be able to get. To combat this, ensure that your operations people who are doing monitoring know how to interpret a seemingly harmless blip on the monitor.

Maintenance

Besides backup and restore, there are other tasks that you will need to do from time to time. These will largely involve maintaining your indexes for performance and routine maintenance using DBCC commands. However, some of these maintenance tasks can be intrusive. By intrusive, it is meant that it might affect performance, availability, or both.

Table 14-1 shows a list of what to run and what the best practices are for running these commands so that there is minimal impact on online processing.

Table 14-1. Routine Maintenance Commands

DBCC

Note

CHECKDB, CHECKALLOC, CHECKFILEGROUP, and CHECKTABLE

Does not block updates, with recommended parameters

DBREINDEX (nonclustered index)

Shared lock (used to take an exclusive in previous versions)

SHOWCONTIG

Has an option not to take a shared lock on the base table

DBREINDEX (heap)

Exclusive lock

UPDATEUSAGE

Shared lock

CHECKCONSTRAINTS

Shared lock

DBCC INDEXDEFRAG

Runs while database is fully operational

DBCC CHECK (CHECKDB, CHECKALLOC, CHECKFILEGROUP, and CHECKTABLE) and DBCC INDEXDEFRAG can each be run online without blocking updates, but they do prevent log truncations while running. The impact is minimal when you use the recommended settings. You still have to understand the impact these have on your system. You also should weigh different options and carefully consider what you are getting out of the process.

Perform regular updates to your index schema or statistics. Your goal is to find out how long everything takes, and then decide which action will provide the best benefit. (You can create scripts that keep track of the time elapsed during any maintenance task you do on a regular basis.) Be sure to review the documentation for these traditional maintenance tasks thoroughly before you use them in SQL Server 2000; they have undergone significant improvement and enhancement specifically for the purpose of supporting online maintenance. You cannot use the same cost/benefit grid as you did for Microsoft SQL Server 6.5 or Microsoft SQL Server 7.0.

Calculating the Cost of Maintenance

You might find that your tasks (some or all) are so lightweight (good examples of this include DBCC CHECKDB with the PHYSICAL_ONLY option or DBCC INDEXDEFRAG) that you notice only a minor effect on performance during the scan.

On the other hand, if you drop and recreate an index, the build process will perform faster than a DBCC INDEXDEFRAG (especially if you have Microsoft SQL Server 2000 Enterprise Edition and you take advantage of the parallel index builds). But there is a cost: if it is a vital index, you will still see performance degradation until it is rebuilt, and if it is a clustered index, your data is completely unavailable while the index is rebuilt. In most cases, use the lightweight DBCC INDEXDEFRAG, which might take a little more time to complete because it runs without interfering as much with online processing.

Table 14-2 provides some tips about planning and running these medium impact commands. Run these as a SQL Profiler script on your test server and get a baseline of its performance. Then run each maintenance task and record the results. Compare them to the original and begin to put together a plan for maintenance and administration.

Table 14-2. Medium Impact Commands

Process

Impact

Recommendation

UPDATE STATISTICS

Depends on usage of the command. The higher the sample ratio, the more of an impact this will have. Monitor your system carefully to determine optimal usage.

Use autocreate and autoupdate where possible. (Test this before changing your system’s setting.) In high transaction volume systems or any situation where autostats are not used, explicitly update statistics on specific tables at scheduled times. The higher the sample ratio, the more useful your statistics will be, but the longer it will take to build them.

DBCC SHOWCONTIG

Minimal (with the WITH FAST option).

Use this to help you determine if decreasing query performance is linked to fragmentation.

DBCC INDEXDEFRAG

Minimal (system transactions), no blocking.

If you determine you have fragmentation, this is one method you can use to defragment your indexes.

DBCC CHECKDBNote: CHECKDB includes CHECKALLOC

Minimal with PHYSICAL_ONLY, NO_INFOMESSAGES; uses log analysis to get transactional consistency; makes heavy use of CPU and tempdb.

Corruption in the database stems primarily from problems at the hardware layer. Run this periodically and before and after upgrades or hardware changes. Do not run simultaneously with other CPU and disk-intensive tasks.

Another potential problem is any need to truncate and refresh a table in the production system. You can create two tables and alternate between them.

This is just one example, but you can introduce many design changes to make sure that services are not interrupted. The following is a brief history of how things have changed:

  • In SQL Server version 6.5, CHECKALLOC had to run offline to avoid spurious errors. In SQL Server 7.0, you could run it with read-only access.

  • From SQL Server 7.0 on, CHECKDB, CHECKALLOC, CHECKFILEGROUP, and CHECKTABLE all became fully online operations.

  • A nonclustered index rebuild only takes an S lock on the base table. It used to take an exclusive lock.

Intrusive Maintenance

Some maintenance operations are more intrusive than others. By intrusive, it is meant that a table, or possibly the entire database, will be unavailable while the command is running. Notable ones include create index, rebuild index, full update statistics (auto update statistics does not cover all customer scenarios), and restore database. Customers must plan for these intrusions.

Table 14-3 provides some tips about planning and running these processes should you decide to run them; you should try less intrusive versions before running some of these commands.

Table 14-3. Intrusive Maintenance Commands

Process

Recommendation

 

UPDATE STATISTICS FULLSCAN

Use autocreate and autoupdate where possible. (Always test changes prior to implementing in production.) In high transaction volume systems, or any situation where autostats are not used, explicitly update statistics on specific tables at scheduled times. The higher the sample ratio, the more useful your statistics will be, but the longer it will take to build them.

 

DBCC SHOWCONTIG WITH TABLERESULTS, ALL_INDEXES

Again, another variation of SHOWCONTIG that can help you determine if you have fragmentation and are seeing poorly performing queries.

 

DBCC CHECKDB with options other than physical_onlyNote: CHECKDB includes CHECKALLOC

As with CHECKDB described earlier, this can help you determine things about possible corruption, but if you check more than PHYSICAL_ONLY, this might take some time. Do only as directed by PSS, so as to not cause availability problems.

 

DBCC DBREINDEX clustered index WITH NO_INFOMSGS or DROP/CREATE INDEX

Do this during the lowest levels of usage. This should be a very infrequent process, and it is covered here because of its former prominence. DBREINDEX is more optimized than drop/create index. Use the white paper mentioned in "Defragmenting Indexes" later in this chapter to determine if you need to run DBREINDEX.

 

DBCC SHOWCONTIG WITH TABLERESULTS, ALL_INDEXES

Using TABLERESULTS or ALL_INDEXES may take some time, depending on the results.

 

Defragmenting Indexes

Defragmenting indexes, whether small or large, might become a problem for you at some point. You do have a few options, but you need to weigh them carefully. All of them will have some impact on your system. The size of your database will definitely affect index defragmentation, since the larger the database is, the more complex the solution has to be.

More Info

An excellent resource on defragmenting indexes is the white paper "Microsoft SQL Server 2000 Index Defragmentation Best Practices," which is located at http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/sql/maintain/Optimize/SS2KIDBP.asp. Use this section as a primer, but this white paper should be your main guide.

Before you even attempt to defragment an index, you need to determine if you have fragmentation and if you need to actually do something about it. This is documented in the white paper.

If you need to defragment your indexes, one thing you could choose to do is to run a DBCC INDEXDEFRAG, but it might not be optimal for you. It can only defragment a single index. It can span files, but it only does one file at a time if you are using file sand filegroups, although you have to issue only one command. DBCC INDEXDEFRAG is an online operation, which means that you do not have to worry about users affecting the defragmentation process.

DBCC DBREINDEX can rebuild a single or even all indexes for one table. However, it is an offline operation—that is, the underlying tables will be unavailable for use while the DBREINDEX is happening, and you cannot generate any transaction log backups. Its advantage over an explicit DROP INDEX and CREATE INDEX is that you can rebuild indexes enforcing PRIMARY KEY or UNIQUE constraints without worrying about needing to recreate the constraints manually. Statistics are also rebuilt automatically and DBREINDEX will use multiple processors if they are available. You will also need to account for disk space during a DBREINDEX operation.

More Info

The white paper mentioned in the previous reader aid has a good comparison of the two options.

Logical vs. Physical Fragmentation

Logical fragmentation means that you have a fragmented SQL Server file internally where the data is stored but that the physical file on the file system is not fragmented. Your data can also be logically fragmented if you do many inserts and deletes. If your data is fragmented, you will need to find some way to compact your data so that it is contiguous and not fragmented. DBCC SHRINKDATABASE can shrink the database, but it is not coded to know about or reduce fragmentation; it only compacts things. DBCC SHRINKDATABASE will shrink a database even if it spans multiple files. Physical fragmentation can also occur if you are using your server for multiple applications and each one is using the same disk(s).

Physical fragmentation at the disk level can occur for SQL Server. With releases prior to SQL Server 7.0 that could not automatically grow, you physically had to create additional segments for your data or log. This could cause physical fragmentation over time. Now, with SQL Server 7.0 and SQL Server 2000, you can allow your databases to grow or shrink automatically, but you need to realize that these two can cause physical fragmentation at the disk level since you are expanding or shrinking your database files, or both.

This is directly related to placement of your data and log files. If you place all your files on the same spindle, your growth will occur on each database and expand (or contract, if shrinking) to the next available disk block(s). Over time, this can fragment your files. This is one good reason to place your disk files onto separate spindles. If you encounter severe physical fragmentation, you will have to consider defragmenting at the file system level. If you choose to do this, it is recommended that you make sure that no users are connected to SQL Server and possibly that SQL Server is shut down so you do not encounter any potential conflicts while the disk pages are moved around on the disk. It might be easier, however, to use a utility like sp_detach_db to copy and move the data and log files safely, reformat the disk so that it has a clean slate, and then copy the data back and reattach it.

How you approach physical fragmentation will vary depending on the size of your data, on whether other things will be affected, and on how fragmented things are. Make sure you back up your databases prior to initiating such an action.

Note

Because you have fragmentation does not necessarily mean you have to do something about it. Some storage area networks (SANs) actually have logic to prevent such a problem. That said, as part of your monitoring, you need to determine if you are actually having problems that might indicate fragmentation, such as longer average reads and writes per second and poor throughput (disk reads and writes per second).

In the end, you will have to test what works best in your environment to give you availability and performance, as well as the windows of opportunity you will need to perform the necessary maintenance.

Example: Defragmenting a VLDB That Uses Log Shipping

Consider the following scenario: you have a database that log ships to another server every 15 minutes. Once a week, it is necessary to defragment the indexes on the database. Unfortunately, at the end of the process, you now have a 5 GB transaction log that takes too long to send and apply on your warm standby. To make matters worse, the database has 12 files. Also, you cannot control the fill factor directly with INDEXDEFRAG. If you consider DBCC DBREINDEX, you can control fill factor and it will span files, but it will cause a lot of blocking on the database at the time—and that only increases with size.

In this case, you might want to think about the following:

  • Concern yourself with fill factor rather than fragmentation. You would do well to scan the same amount of data with less I/O.

  • You might want to switch the recovery model to BULK_LOGGED, do a SELECT INTO and a rename for the data, and then switch to FULL recovery model. This will keep the integrity of the transaction-log chain, and you get the benefits of minimally logged operations.

  • Consider disabling log shipping before the defragmentation, and then resynchronize after the defragmentation. This might potentially take less time; however, you will be exposed during that time.

  • DBCC INDEXDEFRAG is definitely slower, but it has less impact on end users. Because the transactions are smaller with INDEXDEFRAG, the transaction logs will be much smaller. It is likely that the latency between the log-shipped database and the production database will be negligible.

  • Alternate DBCC INDEXDEFRAG and DBCC DBREINDEX.

Ultimately, the right answer is the one that suits a company’s conditions. For the bullets listed previously, messing around with the fill factor of your indexes might be too granular, and, unless you really know what you are doing, you might cause more harm than good. Switching recovery models and moving data around and such is too much movement for some and might be risky for others. Disabling log shipping is a viable option, but you will still have the problem of a large transaction log after the defragmenting is complete. You are also exposed from an availability perspective, so you need to think about that. Alternating between DBCC DBREINDEX and DBCC INDEXDEFRAG is certainly viable, but unless you have a maintenance window to allow for DBREINDEX to happen, just doing DBCC INDEXDEFRAG might be your best option from an availability standpoint. At some point you might have to do a full DBREINDEX or DROP and CREATE INDEX, but you might be able to stave that off.

Database Corruption

Although it is not common, you can still encounter database corruption with SQL Server 2000. Corruption usually happens due to some hardware error (good example: a bad or improper disk driver) that corrupts your SQL Server databases when data is written to them. A good indicator of corruption is 605 errors in your SQL Server error log. If you suspect disk corruption, scour Event Viewer as well as any hardware-specific monitoring tools to find out if you are seeing any errors outside of SQL Server. Whether you are seeing other messages or not, the best way to handle corruption is to call Microsoft PSS to have them help you assess your problems and walk you through the next steps. You do not want to accidentally cause additional problems by running DBCC commands that might not be necessary. At this point, you might be reliant on your backups and disaster recovery plans.

Changing Database Options

You should not change configuration options once a system is in production if you do not have to. However, if you do, some will require you to stop and then restart your SQL Server instance. You must take this into account for your availability. Here are the options in SQL Server 2000 that require a stop and restart (when configuring or changing the option if it is already configured):

  • affinity mask

  • AWE enabled

  • C2 audit mode

  • fill factor

  • lightweight pooling

  • locks

  • max worker threads

  • media retention

  • open objects

  • priority boost

  • remote access

  • scan for startup procs

  • set working size

  • user connections

Memory Management for SQL Server 2000

One of the most important administrative tasks any DBA or system administrator has to do is manage the memory that an instance of SQL Server 2000 uses. This section covers the various types of operating system memory tuning you can use with SQL Server and offers recommendations on how to use them. Several types of memory tuning are available, and each has its own advantages, disadvantages, and uses.

Note

This is not intended as a complete guide to the operating system memory manager. Rather, this is a brief overview designed to give you enough understanding of the memory manager to comprehend the various memory-tuning techniques available to SQL Server, as well as the implications that can arise from using them.

Before describing the various types of memory tuning, however, here is a brief "tour" of the operating system memory manager. This "tour" will help you understand the hows and the whys of employing the various types of memory tuning.

Understanding the Memory Manager

All versions of Windows up through Microsoft Windows 2000 and some versions of Microsoft Windows Server 2003 were primarily 32-bit operating systems until the release of the 64-bit versions of Windows Server 2003.

The amount of memory the operating system can address is directly tied to how many bits the operating system is. The 32-bit versions of Windows are able to address 232 bytes of physical memory out of the box, or 4,294,967,296 bytes. To put it more plainly, Windows can address 4 GB of physical memory. The obvious implication is that the more address bits your operating system has, the more memory you can address. So a 64-bit operating system would be able to address, at most, 264 bits worth of physical memory (which is 18,446,744,073,709,551,616 bytes—an extremely large number). From this discussion, you would think that 32-bit versions of Windows are limited to supporting only 4 GB of physical memory, but that is not the case.

However, before you get excited and start writing or implementing applications that will require 4 GB of memory just to load, there are a few ground rules about how memory can be used. Windows utilizes something known as a memory split (see Figure 14-4). This means that by default, the kernel can utilize up to 2 GB of memory in its own separate memory space and each application can utilize up to 2 GB of memory in its own private address space.

An example of a memory split.

Figure 14-4. An example of a memory split.

The memory manager works this way for two main reasons: self protection and application protection. The kernel mode gets 2 GB all to itself so that it will have enough room to do whatever it needs to do without running out of space. Plain and simple, applications will not run if the kernel space does not have enough memory. Along with this self-protection, user mode applications cannot address kernel mode space and accidentally corrupt kernel mode memory and cause an access violation (AV).

Notice that previously it was noted that each application can utilize up to 2 GB of memory. That might seem a little odd given that, natively, the operating system can recognize only 4 GB of total memory. For example, pretend that a server that has 4 GB of RAM (which we will call \myserver for the purpose of the example), and the kernel mode functions are using 1 GB of memory, leaving 3 GB for all other applications. Now, also imagine that an instance of SQL Server 2000 is active and using its full range of 2 GB of memory, leaving only 1 GB for all other applications. Now add Web services, native user mode applications, management and monitoring processes, and we are running at a full 3.9 GB of memory used. What happens when a new process is started that needs 200 MB of memory? This single request would put the processes over the actual amount of memory that the system has in total. So now, with each application getting its own 2 GB range, the memory picture begins to look a little more like Figure 14-5.

Memory split with a paging file in use.

Figure 14-5. Memory split with a paging file in use.

To combat this hard limit of physical memory in the server, the memory manager uses disk space to substitute for physical memory. This disk space is called the paging file (pagefile.sys). Whenever there is not enough physical memory left to satisfy requests, memory that is currently not in use will be written to the paging file on disk, freeing physical memory to satisfy requests (actually, the process is somewhat more complicated than described here, but for this discussion, it is sufficient).

Note

Paging is a fairly generic term that refers to the memory manager writing from memory to disk. This can be writing data out to a paging file or simply saving a file to disk. In context for this text, we will use the term paging to refer to writing to the page file for the purposes of memory management unless otherwise noted.

So far, there can be 4 GB of memory in the operating system with 2 GB available to kernel mode functions and 2 GB available to each user mode application. If physical memory becomes constrained, items in memory that have not been recently used will be written out to a pagefile to free physical memory for more pressing needs, and the memory picture looks more like Figure 14-6. So what happens when an application needs some of its memory that has been written out to the paging file?

Freeing physical memory.

Figure 14-6. Freeing physical memory.

To enable applications to not have to keep track of memory in case it gets moved or worry about overwriting the memory of other applications and processes, the memory manager virtualized all the memory addresses used by user mode applications and processes. For example, imagine that we have two processes, process A and process B, and both ask for 1 MB of memory. Both processes get an answer from the memory manager that they have been allocated 1 MB of memory starting at address 0x28394532. What happens when both applications write to that address? Will one of the processes erroneously overwrite the other’s data? Will one of the processes receive an error? Will one or both of the applications crash?

The answer is none of the above. Both processes will be able to write to the same address because of the virtualization that goes on behind the scenes. User mode processes are never able to directly write to physical memory and never actually know where their data resides. A user mode processes and requests a block of memory and writes to it. In the meantime, the memory can be written out to the pagefile, and when the application does something with the memory, the memory manager will go out to the pagefile and retrieve the data from the pagefile for the application. The key thing here is that the application never knew anything about the virtualization process; it simply thinks it is writing to a memory location.

How does an application get its memory back once it is in the paging file? It does not get it back. Whenever an application references memory in the paging file, the memory manager will retrieve the data out of the paging file for the application because, remember, the application is not responsible for keeping track of where the data really is.

Because of this virtualization, each application can write to the virtual locations of 0x00000000 – 0x7ffffffff (or 2 GB) without affecting any other process. Each application thinks that its memory location 0x38344134 is the only one on the server, when, in fact, many applications are simultaneously using that virtual location. All the while, in the background, the memory manager is writing memory for those applications and keeping track of where they are in physical memory and in the pagefile.

Keeping this in mind, the previous statement that the kernel space and each application could utilize up to 2 GB of memory was somewhat incorrect. Now that we have introduced the concept of virtual memory, it is far more accurate to state that the kernel mode space, as well as each application, can utilize up to 2 GB of virtual memory. Certain portions of the memory manager, however, cannot be paged to disk.

The kernel address space can also use 2 GB of address virtual memory, but the key difference is that all processes in the kernel space share the same 2 GB. Each process does not get its own unique memory space use without affecting other kernel mode processes. Any user mode thread that enters and does its work in this space and then returns will lose access to the memory it just used. Because of this, it is very important for drivers and kernel processes to be very good at handling memory. When rogue processes corrupt or overwrite kernel address space memory, the results are disastrous indeed. Errors in the kernel mode space, where most hardware driver code exists, often lead to a dreaded system crash if the right set of conditions occurs. In Windows 2000 and later, this is less likely to happen due to protection mechanisms built into the operating system.

Most memory in the kernel mode space is virtualized. Some memory, depending on the function, can be paged out to disk as well. There is a special type of memory that cannot be paged out to disk. One of the key items that resides in that space is the portion of the memory manager that handles virtual address translation and its related items and drivers for disk access. Those must remain resident in physical memory at all times (this is addressed later).

Memory access is always slow compared to memory access from physical memory. For example, imagine that an application named memoryhog.exe references three pieces of data it has stored in memory: Mem1, Mem2, and Mem3. Mem1 is right where memoryhog.exe left it. The memory manager has not shuffled it around at all. The memory manger has not moved Mem2 either, but the virtual memory address no longer points to the data that is still in physical memory. The data is not out on the paging file yet. The memory manager, however, has moved Mem3 into the paging file. memoryhog.exe does not know this, of course—it simply references the memory virtual addresses it wrote to in the first place. Which reference will occur faster and why? The answer is Mem1, and here is why.

When memoryhog.exe references Mem1, nothing "extra" happens. It is right where memoryhog.exe left it, and no extra looking and retrieving goes on. When Mem2 is referenced, it is a little slower because the memory manager has to repoint the virtual address to the physical memory, but the performance hit is negligible because the item still remained in physical memory. Mem3, however, must be retrieved from disk, and it is the slowest of all. Disk access times are measured in milliseconds and memory access time is measured in nanoseconds, so every time memory has to be retrieved from disk, it takes approximately 1 million times longer to retrieve the data than if it had still been resident in physical memory.

Whenever data is not where an application originally left it and the memory manager has to retrieve the data, a page fault—which means that you are now accessing a physical disk—is incurred. You must be aware of two types of page faults: soft page faults, as occurred with Mem2, and hard page faults, as occurred with Mem3.

Because hard page faults are devastating to system performance, operating system–based solutions were developed to help applications use and retain more data in physical memory.

Breaking the 2-GB Barrier Under 32-Bit

Because databases are growing so large and usage is heavy, the default 2 GB that a single user mode process can utilize is often insufficient for real-world needs. In order to combat this and increase performance (or to prevent performance degradation due to increased load), you will need to tune the amount of memory you are using for a given SQL Server 2000 instance.

The following memory tuning options are discussed in this section:

  • /3GB switch

  • Physical address extensions (PAE)

  • Address windowing extensions (AWE)

Each option does not function the same but has the same goal: to increase performance of an application by modifying the way the memory manager works to reduce disk paging.

/3GB boot.ini Switch

/3GB is a switch configured in the boot.ini file read by Windows at startup. This option allows an application such as SQL Server to utilize up to 3 GB of virtual memory in its private address space rather than the default maximum of 2 GB. The memory is virtual and can still be paged out if necessary. Here is an example of a boot.ini entry with the switch:

multi(0)disk(0)rdisk(0)partition(1)WINDOWS='Windows Server 2003, Enterprise'
/fastdetect /3GB

The benefits of using /3GB are immediately obvious. An application can map 1 more GB of memory into its private memory space. Specifically, SQL Server is able to map 3 GB of data into its memory space, a gain of 50 percent.

Note

Applications have to be compiled specifically with the IMAGE_FILE_LARGE_ADDRESS_AWARE flag to take advantage of the /3GB switch. The 32-bit version of SQL Server 2000 is one of these applications.

Applications such as SQL Server that can frequently refer to the same data multiple times to satisfy different requests can greatly benefit from an extra GB of memory to map.

An administrator will need to keep several considerations in mind before enabling the /3GB switch. Usage of this switch will limit the kernel memory space to the remaining 1 GB. In some cases this can cause undesirable results if the kernel mode space is not large enough for the operating system. If the right conditions do not exist, the server’s performance can be degraded or possibly result in a system crash. It would never be wise to allow a single application to starve the kernel of memory because it not only could affect other applications but also could cause the kernel to not have enough memory to continue to function at all. Also, because the memory is still virtualized, SQL Server or any other application that uses a 3 GB virtual address space might not necessarily realize a performance benefit.

The /USERVA boot.ini Switch

Because of these possible problems, a new subswitch has been introduced in Windows 2003 Server (as well as Windows XP Service Pack 1 or later) that can only be used in conjunction with the /3GB switch, the /USERVA switch. The /USERVA switch allows an administrator to determine the size of the user mode virtual address space between 2 GB and 3 GB. For example, assume that an administrator determines (through testing and benchmarks) that the system will perform at its peak with a user mode virtual address space of 2.5 GB and the kernel will be able to work comfortably with a 1.5 GB virtual address space. The administrator could them modify boot.ini to the following:

multi(0)disk(0)rdisk(0)partition(1)WINDOWS='Windows Server 2003, Enterprise'
/fastdetect /3GB /userva=2560

In some cases restricting the kernel to only 1 GB of memory might not be desirable, but the kernel might not need 2 GB, either, so the /USERVA switch allows administrators a middle-ground alternative to the all-or-nothing approach of the /3GB switch.

Important

Without the /3GB switch, the /USERVA switch will be ignored if it is put into boot.ini alone.

Despite these concerns, using the /3GB switch is a perfectly valid approach to memory. The key to determining whether or not it will be useful in your environment is testing. Usage trends and performance changes can rarely be predicted; before and after performance benchmarks and tests are essential to determining whether or not memory tuning is beneficial in a particular case.

Physical Address Extensions (PAE)

You might have noticed that we mentioned earlier that a condition might exist where total system memory usage is more than 4 GB. What does an administrator do then, since earlier we pointed out that a 32-bit operating system can only address 4 GB of memory? Simple, make the operating system use more than 32 bits.

PAE is a hardware modification that allows a 32-bit hardware platform to address more than 4 GB. Essentially, PAE changes the addressing from 32-bit to 36-bit addressing mode on an Intel server (37-bit on AMD). The calculation for the amount of memory is 2n, where n is the number of bits of the operating system. So an Intel-based processor, when PAE is enabled, will allow an operating system to address up to 64 GB of memory, since 236 works out to 64 GB.

Implementing PAE is done through a /PAE switch configured in the startup line for the specific installation of Windows in boot.ini option. Here is an example of a boot.ini entry with the switch; PAE is also enabled by means of a switch in boot.ini. Table 14-4 shows how much memory you can access with /PAE set under the various editions of Windows.

Table 14-4. Memory Supported for 32-Bit Versions of Windows with PAE

Operating System

Maximum Memory (in GB)

Windows 2000 Advanced Server

8

Windows 2000 Datacenter Server

32

Windows 2003 Server Enterprise Edition

32

Windows 2003 Server Datacenter Edition

64

multi(0)disk(0)rdisk(0)partition(2)WINNT='Windows 2000 Advanced Server' /PAE
/basevideo /sos

PAE allows the operating system to see and utilize more physical memory than otherwise possible. The obvious benefit to this is that with more physical memory available, the operating system will have less need of a paging file to service memory requests.

For example, a server, named MyServer, has 4 GB of memory. SQL Server is using 2 GB, the various kernel functions are using 1.5 GB, and other applications, such as virus scanners, essential services, and support applications, are using 2 GB of memory. Whoops, that adds up to 5.5 GB of memory. Since normally a server can support only up to 4 GB of memory, this means that at least 1.5 GB worth of data is paged out to disk at any given time (again, this is not strictly true, but this is a simple overview of the memory manager). Constantly swapping 1.5 GB of data in and out of the pagefile is a performance-intensive task, so it would really be beneficial if somehow the system could use more than 4 GB of physical memory to decrease, if not eliminate, the pressure on the paging file.

With PAE, a server can recognize and use more than 4 GB of physical memory. This is a great performance enhancer because, even though all memory is virtualized for applications (remember, this means they never know where it is in physical memory or if it has been pushed out to the pagefile), data does not get pushed out to the pagefile unless there is a deficiency of physical memory. Because of this, increasing the amount of physical memory available decreases the amount of pagefile usage that takes place and will therefore increase performance.

How does this help SQL Server? It does not help directly. Although applicationsdirectly take advantage of the /3GB switch, the performance gains that come from PAE are hidden from the application. In fact, applications are completely unaware of PAE or the amount of physical memory. Applications get an indirect performance boost because more of their data can remain resident in physical memory on a system with >4 GB of memory with PAE enabled. That is good news, because applications do not natively need to do anything to take advantage of PAE; it just happens.

Combining /PAE and /3GB

For some, the better news might be that you can combine the /3GB and /PAE switches to allow applications (correctly compiled, of course) to use up to 3 GB of memory and to allow more of that data to remain resident in physical memory, providing a performance boost from both ends.

Earlier, we mentioned that the memory manager virtualizes memory for applications and for portions of the kernel so they do not have to do the work of keeping track of where their data is located. Because of this, the memory manager must keep track of where data is located, in physical memory or the pagefile, so that when an application asks for the data in location 0x12345678, the memory manager can look in a translation table, find the data, and grab it from the right place, whether it is the pagefile or memory, and send it to the application. One of the structures involved in this translation and lookup process is called a page frame number (PFN).

Because PAE creates a larger range of physical addresses for the memory manager to keep track of and index, the amount of PFN entries that is required grows dramatically. On a system that is booted with both the /PAE and /3GB switches, an interesting thing happens. The amount of memory that must be indexed/translated in a lookup table is dramatically increased, more key data structures involved in that lookup process are used, and the area of memory where that structure is stored, kernel mode memory, is capped at 1 GB.

This combination will exhaust system kernel space much earlier than normal. Because of this, the memory manager imposes a hard cap of 16 GB on a system booted with both the /3GB and /PAE boot options. Even if a system has 32 GB, if it is booted with both options, only 16 GB will be recognized. So if your SQL Server instance requires more than 16 GB of memory, you cannot mix these two memory models.

Warning

Even though the memory manager imposes a hard limit of 16 GB in this configuration, it is possible to encounter problems even with lesser amounts of memory (say, 8 GB or 12 GB), so it is always a good idea to give the kernel as much room as possible either by reducing the memory load or by using the /USERVA subswitch to increase kernel memory.

Address Windowing Extensions (AWE)

What if 3 GB is not enough for an application? What if an application needs to use 5 GB of physical memory and cannot ever have that memory paged out to disk? There is a way to have an application use gigabytes of virtual memory and ensure that data mapped into that physical memory was never written to the pagefile. It is Address Windowing Extensions (AWE), which is enabled in SQL Server 2000. This feature was introduced in SQL Server 2000 and does not exist in earlier versions.

AWE is an API set that compliments PAE. Unlike PAE, AWE is not a boot option. Applications must directly invoke the AWE APIs in order to use them. The specifics of the AWE API are beyond the scope of this book and are not covered here.

More Info

To learn about specific APIs and to get code samples, please see MSDN online at http://msdn.microsoft.com.

Since there are no code samples of AWE or even a look at the API set, this section looks at the functionality AWE provides through applications that utilize it, such as SQL Server, and how it affects memory usage.

Because an application virtual address space can be extended only to 3 GB on the Intel 32-bit platform, applications (and database applications in particular, since they deal with such large datasets and do a lot of swapping of data from disk to memory) need a method to map large portions of data into memory and keep that data in physical memory at all times to increase the performance. This also allows an application to map/remap data into its virtual memory space very quickly without failures.

AWE does just that. AWE allows an application to "reserve" chunks of physical memory that cannot be paged out to the paging file or otherwise manipulated except by the reserving application (which will be SQL Server, since that is the topic of discussion). AWE will keep the data in physical memory at all times. Because the memory manager cannot manage this memory, it will never be swapped out to the paging file. The application is now completely responsible for handling the memory in a responsible manner.

Because this technique is only useful if an application is able to reserve large chunks of memory, it is a technology that best compliments existing technology, namely PAE, rather than being a stand-alone memory tuning solution. When you use the combination of PAE and AWE with SQL Server, the instance does not dynamically manage the size of the memory address space used. And once initialized, AWE memory holds all the memory acquired at the instance’s startup until the SQL Server is shut down. To enable AWE in SQL Server, you must use the sp_configure stored procedure. Here is the syntax to run in a query window to enable AWE:

EXEC sp_configure 'awe enabled', 1
RECONFIGURE

Important

AWE enabled is not a dynamic configuration change. You must stop and start your SQL Server instance before it takes effect. And if you need to change the settings, you must also go through another stop and start. You must plan for this downtime, which means it might affect any service level agreement (SLA) you have in place.

You must set the Max Server Memory and Set Working Size configuration options when using AWE with SQL Server. If they are not set, SQL Server grabs the total memory available (except 128 MB to allow the base operating system to function). This potentially deprives the operating system—and any other processes that would be running on the same server—of memory.

Because the memory pages used by the instance of SQL Server are taken from the nonpaged pool of Windows memory, none of the memory can be exchanged. This means that if the physical memory is filled up, SQL Server cannot use the page file set up on a physical disk to account for the surplus in memory usage.

In terms of AWE and multiple instances, since the memory allocated to SQL Server is expecting to grab is a static amount to be kept, if the memory you have told SQL Server to take upon startup is greater than the amount of memory that is actually available, SQL Server 2000 automatically changes the mode form AWE to non-AWE (dynamic allocation) for that instance. This means that SQL Server will only use up to 2 GB of memory. This is the case if there are multiple instances on one server or if the node is starting up an instance after a failover in a server cluster. If more than 2 GB of physical memory is available, the AWE-enabled instance will allocate all available memory during the failover startup and will only leave 100–120MB free for the operating system, effectively starving it. However, if other instances that are not using AWE use more memory during the failover situation or are using AWE and consume that memory, and the whole system has less than 2 GB of physical memory available, the instance that fails over and starts on the other node will be started in the non-AWE mode.

AWE presents the same dangers as the other memory-tuning techniques. Using any one, or a combination, of these methods to boost SQL Server performance through memory tuning can starve other applications—or even the kernel itself—of memory that they need to perform adequately. In some cases the starvation caused by weighing memory too heavily in favor of SQL Server can cause performance degradation in other areas that is severe enough to cause an instance’s performance to drop.

The bottom line is that SQL Server memory tuning can be a really good thing but it also has the potential to cripple a server. As with most things, take time to understand the outcome of server-wide changes such as this before you make them.

You might have noticed that in this section we give no hard numbers, examples, or performance charts showing at which point performance drops off. Because performance is such a subjective topic and very dependent upon hardware, installed applications, services, and the configuration of these items, giving hard and fast numbers for performance is practically impossible. The key to finding the best performance for your infrastructure is testing and establishing benchmarks to gauge the effects of changes. There are literally mountains of data on this subject in MSDN, TechNet, and in the various resource kits, since a subject that broad is outside the scope of this book.

Paging File Sizing and Location

As noted above, the operating system uses the paging file, which is a physical file located on your disk subsystem, for some memory operations. The general rule of thumb is to size it at 1.5 times the amount of physical memory that you have. However, in Windows 2000, there is a maximum of 4 GB for the page file size. A paging file size of 2050 MB (just over 2 GB) is the minimum file size necessary for computers with 4 GB or more of physical memory. In Windows 2000 and Windows Server 2003 32-bit, there is a maximum file size of 4 GB, but there is no limit in 64-bit versions of the operating system. In Windows Server 2003 64-bit, you can have a paging file size much larger than the 2050 MB, and it is typically three times the physical RAM. To do this, you have two options:

Option 1: Through the Graphical User Interface (GUI)

  1. Select My Computer, right-click, and select Properties (in Windows Server 2003 you might need to turn on the Classic view to see My Computer). Or, under Control Panel, select System.

  2. Select the Advanced tab. In Windows Server 2003, click Settings under the Performance category. In Windows 2000, click Performance Options.

  3. In Windows Server 2003, in Performance Options, select the Advanced tab, and in Virtual Memory, click Change. In Windows 2000, in Performance Options, click Change in Virtual Memory. The Virtual Memory dialog box, as shown in Figure 14-7, will be displayed.

    Changing your paging file settings.

    Figure 14-7. Changing your paging file settings.

  4. In Virtual Memory, select the drive where you want to place your paging file and an initial and maximum size. You can allow Windows to manage it, but it is recommended that you control this. Click Set when you are finished. Click OK. You will see a message similar to the one shown in Figure 14-8. Click OK three more times.

    Restart message.

    Figure 14-8. Restart message.

Option 2: Through the Registry

  1. In the location where you will create the extra paging files, create folders for each additional paging file.

  2. Start the Registry Editor with Regedt32.exe, and find the following registry key:

    HKEY_LOCAL_MACHINESystemCurrentControlSetControl
    SessionManagerMemoryManagement
  3. Under the key, find the Pagingfiles value, and double-click it. Delete any entries that exist and add entries for each of the files you will be using in the folders you created. For example:

    c:pagefile1pagefile.sys 3000 4000
    c:pagefile2pagefile.sys 3000 4000
  4. When you are finished, click OK and exit the Registry Editor. You must restart the operating system for the new changes to take effect; this is not a dynamic change.

  5. After the system is rebooted, verify the new settings using the instructions for the GUI to see the changes in the Virtual Memory dialog box.

In terms of placing the pagefile.sys, it is recommended that you do not place it on any disk that will have SQL Server databases, because if you run out of memory and start paging, you could have serious I/O contention with your SQL Server databases and have a double performance problem (memory and disk). You might choose to use a form of redundant array of independent disks (RAID) to protect your paging files, and that is absolutely required if you split your paging files among multiple disks. RAID 1 would work well.

Also, how you configure your paging file is directly related to how you set the Startup and Recovery settings in Computer Management, which you can find in the Advanced tab when you right-click Computer Management (Local) and select the Properties. If you choose either the Kernel Memory Dump or Complete Memory Dump option and select the option Overwrite Any Existing File, Windows will write over any existing dump file and use the same name. If you do not select Overwrite Any Existing File, you will have the ability to save all your memory dumps, but you will have to account for the space. See Figure 14-9 for the Startup and Recovery settings in Computer Management.

Startup And Recovery dialog box from Computer Management.

Figure 14-9. Startup And Recovery dialog box from Computer Management.

If you want to get full memory dumps after a crash with 32-bit systems larger than 4 GB, you must add the /MAXMEM switch in boot.ini like this:

multi(0)disk(0)rdisk(0)partition(1)WINDOWS='Windows 2000 Advanced Server'
/fastdetect /MAXMEM= n

where n is the amount of memory you are specifying as the maximum amount of memory that the operating system can use.

Caution

/MAXMEM was originally designed for stress testing and debugging, so use this with extreme caution.

For example, if you put /MAXMEM=128, you would be restricting the operating system to only 128 MB of memory, and no matter how much more memory you have in your server, that is all it would see. Do not set this lower than 128 MB for Windows 2000 versions of the server or for Windows Server 2003, Enterprise Edition. Windows Server 2003, Datacenter Edition, has a minimum requirement of 512 MB of memory. Realistically, if you use /MAXMEM, you should set it to the minimum recommended RAM, not the bare minimum needed.

Important

Using /MAXMEM requires that one of the paging files on the system must be at least 1 MB larger than your physical memory; otherwise you will not get a full memory dump.

Warning

/MAXMEM is an undocumented boot.ini switch that you can find in Volume 3 of the Windows NT Resource Kit. It is meant only for specific configurations, and the memory you specify must be contiguous. This option is valid through Windows 2000 and is not guaranteed to be in future operating systems. Do not use the /MAXMEM option without careful consideration and thorough testing.

SQL Server Memory Recommendations

The toughest part about understanding the memory models is putting it into practice. What do you do for your SQL Server instances? This becomes more glaring on a server cluster where you are trying to implement more than one instance or where you are trying to consolidate multiple SQL Servers onto one or more instances, possibly on a single server or a cluster. Use Table 14-4 as well as Table 14-5 for 64-bit versions to see how much memory you can use under your operating system of choice.

Table 14-5. Memory Supported for 64-bit Versions of Windows (No Boot.ini Modifications Necessary)

Operating System

Maximum Memory (in GB)

Windows Server 2003, Enterprise Edition

64

Windows Server 2003, Datacenter Edition

512

Note

If your hardware as well as your operating system choice supports hot swap memory, you might be able to add more physical memory to your server without incurring downtime. However, to use the memory, you would need to allocate it in an application such as SQL Server, which might require a reconfiguration that necessitates downtime of some sort.

Important

Although you can expand beyond 4 GB of memory in SQL Server, the 32-bit version of SQL Server 2000 will always be limited to 2.6 GB of procedure cache. If you have multiple workloads, you will need to test whether they can all coexist and one will not exhaust the procedure cache. If so, you might need multiple instances as each instance gets its own procedure cache; it is not shared between instances.

64-bit SQL Server 2000 changes the rules a bit. All memory under 64-bit is dynamic, and you have much more available to you. In this case, whether you are on a cluster or using a stand-alone server, you can allow SQL Server to manage its own memory, and you can set the MIN SERVER MEMORY option of SQL Server to set the minimum amount of memory for each instance. To set this through Transact-SQL, here is the syntax:

EXEC sp_configure 'min server memory', 8000
GO

Conversely, you can also set your memory settings in Enterprise Manager in the Memory tab of the instance’s properties, as shown in Figure 14-10.

Memory tab of an instance’s properties.

Figure 14-10. Memory tab of an instance’s properties.

Using the Memory tab, you can set the following: if you select Dynamically Configure SQL Server Memory, you can set a maximum or minimum amount of memory, or both, that the SQL Server instance can use. By default, the maximum is set to the total amount of memory SQL Server can use and the minimum is set to 0, meaning SQL Server can use up to every amount of available memory. If you are using this option, when you set Minimum (MB) on the screen, it corresponds to executing sp_configure with MIN SERVER MEMORY, and Maximum (MB) is the same as issuing sp_configure with MAX SERVER MEMORY.

If you select the option Reserve Physical Memory For SQL Server, this will physically reserve that amount of memory for SQL Server and not let it go until you reconfigure (and subsequently restart) SQL Server. You should be setting this option only when you also select the option Use A Fixed Memory Size (MB) with an appropriate number. Behind the scenes, when this combination is set, SQL Server is issuing sp_configure twice, once with MAX SERVER MEMORY, and once with SET WORKING SET SIZE (setting that to 1). Setting this option also requires a stop and a restart of SQL Server, as shown in the prompt in Figure 14-11.

Prompt after selecting Reserve Physical Memory For SQL Server.

Figure 14-11. Prompt after selecting Reserve Physical Memory For SQL Server.

Tip

It is not a good idea to select Reserve Physical Memory For SQL Server along with Dynamically Configure SQL Server Memory. They are, in essence, conflicting options, and you would be telling SQL Server to dynamically manage memory but grab a fixed amount. If you set Set Working Set Size with dynamic memory, it might cause problems. The Enterprise Manager GUI does not prevent you from combining these options.

If you are using /3GB only, you can allow SQL Server to manage memory dynamically up to 3 GB, or you can set a static amount. Nothing special is required. However, if you are using AWE memory, as mentioned earlier, you must set the option awe enabled to 1, as well as set working set size to 1 to allow SQL Server to physically reserve the amount of memory. Here is what the syntax looks like:

EXEC sp_configure 'awe enabled', 1
RECONFIGURE
EXEC sp_configure 'set working set size', 1
RECONFIGURE

Then you will need to set the options Max Server Memory and Min Server Memory to the same number.

EXEC sp_configure 'min server memory', 8000
RECONFIGURE
EXEC sp_configure 'max server memory', 8000
RECONFIGURE

Once all this is done and you restart your SQL Server instance, you will be able to take advantage of your memory above 4 GB with AWE.

When you are looking to tune your memory used for SQL Server, when can you combine /3GB with AWE under 32-bit? Follow Table 14-6.

Table 14-6. Memory Recommendations for a 32-Bit SQL Server 2000 Instance

Amount of Physical Memory

Recommendation

Up to 4 GB

No switches (each instance can use only up to 2 GB of memory) or /3GB (each instance can use up to 3 GB of memory dynamically or statically, reserving 1 GB for Windows). No real benefit from setting AWE with this small amount of memory. /3GB is used for plan cache.

4 GB to 16 GB

Can combine /3GB and /PAE with AWE, but you would need to test the use of both to see if any benefit is gained. /3GB can help with plan cache, and AWE for data cache.

More than 16 GB

/PAE with AWE only; /3GB is useless. If combining instances for consolidation or failover clustering, make sure the instances do not rely on /3GB.

Note

It is possible to use AWE memory without having more than 4 GB of memory, but you will get very little benefit from setting a server to use AWE and be able to grab only 2 GB of memory. You might as well just set working set size to 1 (or select Reserve ... from the GUI) and select the amount of memory. They will have basically the same effect.

Warning

Do attempt to deploy AWE, PAE, or /3GB in a production environment without testing the configuration first. You do not want any surprises awaiting you. Also, remember to take into account room for the operating system. The rule of thumb is to leave at least 1 GB for Windows "just in case," as long as you can spare it.

Memory and Multiple Instances on the Same Server or Server Cluster

One thing many people struggle with is how to set memory for a clustered instance or multiple clustered instances running as part of a server cluster or if you have multiple instances on one Windows installation. In addition to the considerations listed in the previous section, for a cluster you now need to take failover into account. If you have a single instance cluster, assuming all nodes are equal in capacity and are configured the same, you will not have to worry about anything. During a failover, the SQL Server should start up and behave exactly the same way.

Multiple instances are different. Why? In a failover, your goal should be to ensure that during the failover, when the instance is restarted on another node, it will have the correct capacity from a processor and memory standpoint (this section will deal only with memory; see Chapter 6, for details on processors). Here is where the version of your operating system greatly plays into how you ultimately configure your memory for each SQL Server virtual server. For example, if you are using Windows 2000 Advanced Server, you are limited to 8 GB of memory, eight processors, and two nodes. If you need two, three, four, or even more instances, this could be challenging to say the least, especially if they all need more than 4 GB of memory each! Switching to Windows Server 2003 Enterprise Edition, you can now have up to 32 GB of memory (not to mention two more nodes that would be available to you).

With multiple instances on a stand-alone server, all instances need to play well together in the proverbial sandbox. Although you do not need to worry about failover, you do need to worry about performance and about ensuring that you are not starving one instance to feed another. Your operating choice and the amount of memory it can handle will influence the design of your instances, and, specifically, the amount of memory you can allocate.

Think of your instances as glasses of liquid. If you have two glasses that are half-full, you can pour the contents of one into the other. If you have two full glasses, you cannot combine them. This is how your SQL Servers will behave in a failover or when you combine instances on one server. To prevent this, no matter what you employ (PAE/AWE or /3GB), you should set the Max Server Memory option on each instance to physically cap the amount of memory each instance will get.

Consider this example: you have a two-node cluster with three SQL Server instances. Instance 1, which currently resides on Node 1, has 7 GB of memory configured using AWE. Node 2 houses Instance 2, which has 5 GB of memory allocated with AWE, and one instance that is not using any advanced options and is currently using 1.5 GB of memory. Each node individually has a total of 8 GB of physical memory. This is shown in Figure 14-12.

Nodes prior to failover.

Figure 14-12. Nodes prior to failover.

A problem occurs on Node 1, causing a failover. The instance tries to restart on Node 2, but it cannot. You now have a failed set of SQL Server resources that cannot come online, causing an availability problem. Why? Well, to use AWE, you need to guarantee that the memory you told SQL Server to use will be there. A failover is basically a stop and start on another server. In this case, you were already using 6.5 of the available 8 GB of memory. 6.5 + 7 does not equal 8, and it does not matter how big your page file is. Your instance will not grab the memory for AWE. It might, however, start up, but it will only grab the amount of memory that it can up to 2 GB (see earlier for how AWE behaves in a failover). Now you are risking memory starvation of the operating system, and this can affect all instances. This is shown in Figure 14-13.

Nodes after failover.

Figure 14-13. Nodes after failover.

So how do you prevent this? By planning, these are the types of scenarios you need to play out in your head when proposing the number of instances on a cluster. Your management might see a two-node cluster and say, "Hey, why is this second server doing nothing? Get something on there!", leaving you in the state of the previous example.

The way you can balance memory in this case would be to give two instances that need a fixed amount of memory 3 GB each and let the other one be dynamic (or set it to 1 GB or 1.5 GB to allow room for the operating system). If you cannot live with this, you will need another cluster or set of servers to handle this workload. The recommendation was basically to halve the memory, which might lead some to believe that you are wasting resources, but again, is performance or availability your goal? By definition, if you are reading this book and implementing things like a cluster, you are probably saying that availability is your highest priority. If you never have to failover and you left the instances at 7 GB, 5 GB, and dynamic, things would work great. But once a failover happened, all bets would be off.

64-bit does change the rules, as stated above. Because all memory is dynamic and you have much more available to you, you should set a fixed minimum amount of memory that SQL Server will need to use and let SQL Server manage anything else it needs. This way, you will always guarantee that your instance will have enough memory to do what it needs to do, but you are giving it the option of grabbing more memory if necessary.

Important

When employing AWE, using 64-bit, or setting a fixed amount of memory, the SQL Server instance upon startup will need to physically reserve the configured amount of physical memory. This process is not instantaneous. The more memory you allocate to SQL Server, the more time it will take to start. In a failover scenario, it will definitely increase your failover time, so take that into account. It is usually measured in minutes, rather than seconds.

Managing SQL Server Resources with Other Tools

Other applications might have the ability to control the amount of memory, or, say, processor that your SQL Server instance can utilize. Is this recommended? In most cases, the answer is no. SQL Server does a good job of managing its own resources, and in some cases it has to. However, in Windows Server 2003, you can use a new feature called Windows System Resource Manager (WSRM). WSRM is supported in both stand-alone and clustered environments, although in a clustered environment, you will need to create or export the settings on one node and apply them to others. WSRM is a nonintrusive tool. You should use SQL Server’s interfaces to manage processor affinity and memory, but using WSRM, you can allocate processor percentage for systems with multiple applications (such as a machine with SQL Server, Internet Information Services [IIS], and Microsoft Operations Manager [MOM]) or multiple SQL Server instances. You cannot do this amount of granular control through existing SQL Serverbased tools. Do not use WSRM to do anything related to processor affinity or memory management for SQL Server.

Transferring Logins, Users, and Other Objects to the Standby

When you are looking to have a server function as a standby, it needs to be functionally in sync with your production database. This means that logins and any other objects that exist on your primary database have to be on your standby. With failover clustering, that is not a worry, as the entire instance moves to another node, so you get not only the same database, but also essentially the same server. With log shipping, replication, and possibly backup and restore, you are not guaranteed to get all objects on your standby, and you will have to institute processes to ensure that in the event of a problem, you can flip the switch and users will not notice any difference in your standby.

Transferring Logins, Users, and Other Objects Between Instances

Although this topic was somewhat covered in Chapter 7, with a more focused approach on log shipping, this is a generic problem that you will have with warm standbys. You have two levels to worry about: the serverlevel login, as well as the user that is in the database. If you transfer just the database login, your users might not be able to connect because the login it is associated with does not exist in SQL Server.

Transferring Logins and Users

Moving logins from one instance to another is perhaps the easiest problem to tackle. One method, which is covered in the first task in section entitled "Step 3: Post-Wizard Configuration Tasks" in Chapter 7, is to use the DTS Transfer Logins task, with its corresponding task, to move the users by BCPing data out of syslogins.

If you do not move your logins, you will see an error similar to the following when applications or users try to access the database:

Msg 18456, Level 16, State 1
Login failed for user '%ls'.

Orphaned Users

When you move over your logins, you might have what is known as an orphaned user. An orphaned user is one that exists in the database but whose system identifier (SID) does not match a login or exist as a login on the new server. To see if you have any orphaned users, you can execute the following Transact-SQL statement to give you a list of all orphaned users:

exec sp_change_users_login 'Report'

Sp_helplogins might also assist you in your debugging process, as it will show you all information about a specific login. Another procedure that might help you is sp_validatelogins, which will tell you if you have Windows users or groups that no longer exist but are mapped to logins in SQL Server.

If you do have orphaned users, they should be able to access the new server, but they will not be able to access the database. This means that the SID is not matching, and you should see this error:

Server: Msg 916, Level 14, State 1, Line1
Server user '%.*ls' is not a valid user in database '%.*ls'.

To map your logins, you can use a tool provided by Microsoft Support Services named MapSids, which can be found at http://download.microsoft.com/download/sqlsvr2000/utility/5.0/win98me/en-us/Mapsids.exe. This will create two stored procedures on your SQL Server. Follow the instructions found in Knowledge Base articles 240872, "HOW TO: Resolve Permission Issues When You Move a Database Between Servers That Are Running SQL Server" and 298897, "SAMPLE: Mapsids.exe Helps Map SIDs Between User and Master Databases When Database Is Moved" on how to map your SIDs using these stored procedures.

Another method you can do once you have generated a report with sp_change_users_login is to use that stored procedure to try to fix your problems. Sp_change_users_login can take the following parameters:

  • @Action, which can have the values of Auto_Fix, Report, and Update_One. As of SQL Server Service Pack 3, Auto_Fix does require a password.

  • @UserNamePattern, which is the user in the database.

  • @LoginName, which is the SQL Server-level login.

For example, if you wanted to change the database login that the database user Fred is mapped to, you would execute the statement below. However, as of SP3, you cannot create logins with NULL passwords, so you will have to ensure that the login you are mapping to has a password.

Exec sp_change_users_login 'Update_One', 'Fred', 'FredNewLogin'

Note

Keep in mind that transferring logins will not solve issues external to SQL Server. For example, if your standby is not in the same domain and you are using Windows Authentication, you need to ensure that the logins you are transferring will actually work on the standby. You might need to work with your network administrators to put things in place, such as two-way trusts between domains.

Transferring Objects

There are two ways to move objects between instances: SQL scripts and Data Transformation Services (DTS) packages.

Generating SQL Scripts

Database objects come in a variety of categories—stored procedures, table definitions, permissions, jobs, triggers, and so on. One of the easiest and most recommended ways of moving objects is to generate a SQL script. The script would be one that you coded to initially get the object into SQL Server, or, if you used the GUI of Enterprise Manager, using Enterprise Manager to generate the script. You can script most objects created within Enterprise Manager directly by selecting it, right-clicking, selecting All Tasks, and then selecting Generate SQL Script. Three tabs are in the Generate SQL Scripts dialog box.

Tip

SQL Server Agent jobs, Alerts, and Operators can also be scripted this way. Scripting replication was covered in Chapter 8.

The first tab of the Generate SQL Scripts dialog box, General, is where you select the objects that will be scripted. An example is shown in Figure 14-14.

General tab of Generate SQL Scripts.

Figure 14-14. General tab of Generate SQL Scripts.

The Formatting tab, shown in Figure 14-15, allows you to control how your files look after they are scripted.

Formatting tab of Generate SQL Scripts.

Figure 14-15. Formatting tab of Generate SQL Scripts.

The Options tab shown in Figure 14-16 is an important tab. It is where you select primary/foreign keys, permissions, logins, and such to be included in the .sql file. If you do not select options such as Script Object-Level Permissions, you might not be able to correctly use the script if you ever need to use it as, say, part of a disaster recovery plan.

Options tab of Generate SQL Scripts.

Figure 14-16. Options tab of Generate SQL Scripts.

When you are done, click OK, and you will be prompted for a location in which to save your .sql file.

If you are scripting SQL Server Agent Jobs, Alerts, or Operators, the dialog box is a bit different. The three are nearly identical, and the Jobs dialog box is shown in Figure 14-17. However, unlike generating scripts for all jobs at once, you do it for each job. You can then combine the output scripts into one master script, but there is no way through the GUI to select more than one job at once.

Generate SQL Scripts windows for SQL Server Agent Jobs.

Figure 14-17. Generate SQL Scripts windows for SQL Server Agent Jobs.

Note

If you are employing log shipping, all objects captured in the transaction log will be automatically transferred to the warm standby. See Chapter 7 for more details.

Using a DTS Package to Transfer Objects

You can use a Data Transformation Services (DTS) package to send certain objects to another SQL Server. In SQL Server 2000, you can transfer logins (as covered in Chapter 7; this is represented by a small gray server icon with a person’s head on it), jobs (represented by a miniature dialog box with a small circle, or clock, in it), error messages (represented by a person’s head and a small thing that looks like a piece of paper with an x in it), and objects (represented by two gray servers with a red arrow pointing from one to the other). You can see these in Figure 14-18.

DTS package with transfer tasks.

Figure 14-18. DTS package with transfer tasks.

Important

DTS packages do not run, and Dtsrun.exe was not ported to SQL Server 2000 64-bit. Under 64-bit, you have the option to create and run DTS packages on 32-bit that can take data from and send data to 64-bit. You can save a DTS package to a 64-bit SQL Server 2000 instance, but you cannot run it on 64-bit. If you have SQL Server 2000 Service Pack 3 or later installed, the option to schedule the package is disabled since you cannot run the package under 64-bit.

The Transfer Logins Task, Transfer Jobs Task, and the Transfer Error Messages Task all have similar dialog boxes: they have three tabs—Source, Destination, and a tab to select the login(s)/job(s)/or message(s) you want to send. An example is shown in Figure 14-19.

Transfer Jobs Task dialog box—Jobs Tab.

Figure 14-19. Transfer Jobs Task dialog box—Jobs Tab.

The Copy SQL Server Objects Task dialog box is different. It also has three tabs, but the third tab, Copy, is more like the Generate SQL Scripts dialog box. An example is shown in Figure 14-20. By default, this task will also copy your data. You will want to deselect the Copy Data option. By default, it will also copy all objects and use default options. If you want to send only selected objects, clear Copy All Objects and click Select Objects. You will then be presented with the Select Objects dialog box to choose what you want. Similarly, if you want to control the default options that will govern the task, clear Use Default Options and click Options. You will see the Advanced Copy Options dialog box.

Copy SQL Server Objects Task—Copy tab.

Figure 14-20. Copy SQL Server Objects Task—Copy tab.

To create a DTS package, do the following:

  1. Select the Data Transformation Services folder in Enterprise Manager, right-click, and select the New Package option.

  2. Select the tasks you want to add to your DTS package from the icons at the left side of the DTS Package dialog box, or select them from the Task menu.

  3. Once you are finished adding and configuring your tasks, save the package by selecting the Save or Save As options from the Package menu. You can now schedule this package to run on a regular basis.

DTS Packages

DTS packages are a bit different. They are not transferred through the transaction log. To move a DTS package, follow these steps:

  1. Select the package and open it by double-clicking.

  2. Under the Package menu, select Save As.

  3. In the Save DTS Package dialog box shown in Figure 14-21, enter a name if one does not exist (that is, it was not previously saved), a password, and select where you want the DTS package to go. If you select Meta Data Services or SQL Server, the package will be saved to the msdb database of the SQL Server you designate in the Server drop-down list. You will then need to back up msdb. However, remember that you cannot restore another server’s msdb database to another server unless you rename the server itself.

    Save DTS Package dialog box with Locations expanded.

    Figure 14-21. Save DTS Package dialog box with Locations expanded.

    If you select Structured Storage File or Visual Basic File, you will be prompted to enter a file name with a .dts or .bas extension, respectively. If you do not put a path name, the package will be saved to your My Documents directory. For transporting packages between servers, saving the package as one of these two options is the preferred method.

  4. Click OK.

Tip

Remember that DTS packages can be versioned and that after loading the packages onto another server, you might need to modify it, as some of the source or destination properties of some tasks will be assigned to the wrong server(s).

Summary

Correct administration and maintenance will go a long way in the battle to keep your servers up—and this means more than performing regular backups. Whether it is securing your instance, performing proactive index maintenance, tuning memory, or moving objects, the little things make a big difference. You should definitely not implement or change your current administrative procedures without correct testing and commitment.

Now that you have learned what it takes to administer your SQL Servers for high availability, it is time look at how you can be proactive in understanding the health of your SQL Server through monitoring.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.109.4