Archive for September, 2011

User DB Last Backup Time

2011/09/30

Use the script below, you can check the last  time of different user database backup, pay attention to those never been backup!

SELECT db.Name AS DatabaseName,
COALESCE(CONVERT(VARCHAR(50), MAX(bs.backup_finish_date), 120),”) AS LastBackUpTime,
 CASE ISNULL( bs.type,’X')
 WHEN ‘D’ THEN ‘Full backup’
 WHEN ‘L’ THEN ‘Log backup’
 WHEN ‘X’ THEN ‘No backup’
 WHEN ‘I’ THEN ‘Differential database backup’
 WHEN ‘F’ THEN ‘File or filegroup backup’
 WHEN ‘G’ THEN ‘Differential file backup’
 WHEN ‘P’ THEN ‘Partial backup’
 WHEN ‘Q’ THEN ‘Differential partial backup’
 END AS TYPE
 FROM sys.sysdatabases db
 LEFT OUTER JOIN msdb.dbo.backupset bs ON bs.database_name = db.name
 WHERE db.dbid > 4
 GROUP BY db.Name,bs.type

Good luck.
 
 

Long Running Transaction

2011/09/27

For SQL 2000, the only way to find out long running transaction is to run DBCC OPENTRAN.

Begin from SQL 2005, you can query DMV with the script below:

SET NOCOUNT ON
select db_name(database_id) as dbname,tr.transaction_id,ses.session_id,database_transaction_begin_time
from sys.dm_tran_database_transactions as tr
join sys.dm_tran_session_transactions as ses
on tr.transaction_id = ses.transaction_id
where is_user_transaction = 1
and database_transaction_begin_time < (GETDATE()-’00:05:00′)

It will help you to find out transactions which running longer than 5 min.
 

Enable/Disable Lock Partitoning

2011/09/24

Lock partitioning is enabled automatically when the server has16 or more logical cpu. If you want to turn it on on <16 cpu box or turn it off on >=16 cpu box, the only way is to use trace flag as start parameter. Trace flag 1228 enables lock partition for 2 or more logical cpu. Trace flag 1229 disable lock partition.

Multiple Log Files for TempDB?

2011/09/21

Recently I saw a saying about tempdb performance like "…Since you have 8 CPUs, split temp log files on 8 different physical disks to accelerate the write log performance…" This is not correct.

Data file (MDF, NDF) and log file (LDF) have different I/O behavior pattern. For data file, it is "asynchronous random read/write". For log file, it is "synchronous sequential write". Once a data page is modified, SQL Server storage engine will change the page in buffer pool first, and refresh it to disk later. But for log file, SQL Server uses a write-ahead log, which guarantees that no data modifications are written to disk before the associated log record is written to disk. So data file IO pattern is asynchronous, and log file IO pattern is synchronous.

As SQL Server writes log sequentially, even there are more than one log file, SQL Server will use them one by one. The benefit of multiple log files is providing pre-allocated disk place and avoiding single log file size becoming too huge. But for tempdb, the default recover mode is "simple", which means the log space will be used circularly. For those databases with "full" recover mode, backing up log file regularly can also free the log space.

The conclusion is no need to add multiple log files from performance point of view.
 

How to Replace Cluster Disk

2011/09/17

Storage is the shared hardware resource between cluster nodes, making it to be single point of failure. It needs downtime to fix storage error. The challenge of replacing cluster disk is Windows Cluster Service writes down disk digital signature somewhere in Registry, you have to match them back after replacing cluster disk. I spent sleepless hours to apply such change, below is that I learn.

*Important
Make sure data page of user database is not corrupted is VERY IMPORTANT for this kind of change. You have 2 choices:

1. Run DBCC CHECKDB as first step, to see the original status is everything ok.
2. Run DBCC CHECKDB as last step, to see the final status is everything ok too.

or

1. Run DBCC CHECKDB as first step, to see the original status is everything ok.
2. Get file hash value by any file verification tool like File Checksum Integrity Verifier.
3. Calculate file hash value again as the last step, to see no bit is changed during file transfer process.

Method 1: Change Disk Signature

You should have dumpcfg.exe which can be found in Windows 2000 Resource Kit for Windows 2000 and 2003 or have the diskpart.exe shipped by windows 2008. Method 1 can also be used to replace Q drive.

1. Stop SQL Service.
2. Copy data of the whole drive to some place. I prefer to use Robocopy.
3. Power off nodes, leave one node on.
4. Stop Windows cluster service on the alive node.
5. Mount the new disk to the node, typically it’s LUN in the SAN which can be accessed by all the nodes.
6. Set the drive letter to any temp letter.
7. Copy data back to the new drive.
8. Remove the old disk.
9. Rename the new drive to the old drive letter.
10. Start Windows cluster service. It will fail at the first time.
11. Run eventvwr to check the error, you will get error message "Event ID: 1034
", "The disk associated with cluster disk resource %DriveLetter% could not be found. The expected signature of the disk was %Disk Signature%. ". Write down the disk signature you see here.
12. For 32bit windows 2000/2003, use dumpcfg.exe to write expected signature to the disk: dumpcfg.exe -s signature drive_no.
13. For 64bit windows 2003 or windows 2008, use the windows 2008 diskpart’s new feature SET ID to write disk signature. http://technet.microsoft.com/en-us/library/cc753840(WS.10).aspx
14. Start Windows cluster service again. It should work now.
15. Start SQL Service.

 

Method 2: Change Registry Value

You dont need any extra tool here.

1. Run cluadmin to start  Cluster Administrator. Set SQL Server/SQL Agent/etc.’s “Affect Group” setting to “false”. It avoids failover caused by any unexpected error.
2. Stop SQL Service.
3. Copy data of the whole drive to some place. Robocopy please.
4. Back to ”Cluster Administrator”.  Select SQL Server/ Agent/ Full text search/ etc.’s property  ->  dependency -> modify. Remove all the disks then apply the change. This step is to make sure SQL Server cluster resources won’t be deleted when dropping those disk.
5. If SQL Server resources are deleted mistakenly, recreate them with action plan from http://support.microsoft.com/kb/810056.
6. Make sure all the cluster node are online, delete the disk resources from Cluster Administrator.
7. Delete disk volume from Disk Management tool.
8. Mount the new disk to active node.
9. Create a new group “Test” in Cluster Administrator tool. Set it to be online.
10. Add all the new disks to group “Test”. Set them to be online.
11. Switch the group “Test” to every node, making sure the disk resources working well on each node.
12. Restore previous SQL data which we backup in step 3.
13. In Cluster Administrator, move the disk resources from group “Test” to SQL group. Delete group “Test”.
14. For each resource which be modified in step 4, select  property  ->  dependency -> modify, re-add the disk resource as dependency. Apply the change.
15. For each resource which be modified in step 1, change “Affect Group” setting back to “true”.
16. Start the SQL Server service on active node.

HTH.

Use URLScan 3.1 to Protect IIS from SQL Injection

2011/09/12

SQL Injection Attack in short, is to pass malicious code via program parameter to SQL Server and run as dynamic SQL statement. So the fundamental solution to protect your application from SQL Injection Attack is "not to run dynamic SQL statement" or "to check every parameter". The famous saying "all input is evil until proven otherwise" from Writing Secure Code is ture.

"But man, I’m the operation guy but not the coder and I maintain legacy system, what could I do?"  You can use SQL login/user with least privilege for the application connection. And you can try URLScan 3.1 to secure IIS from SQL Injection.

URLScan is tool to secure IIS from old day. IIS 6.0 has built-in features that provide security functionality that is equal to or better than most of the features of UrlScan 2.x. You may not hear URLScan for years. MS release URL3.1 to provide feature like avoiding SQL Injection Attack. It’s rule-based tool to reject requst which hitting the rules.

Now let’s rock!

1. Download and install URLScan 3.1 from http://www.iis.net/download/urlscan. The basic setup guide is here.

2. After installing URLScan, modify the configuration file. The first default setting we should pay attendtion is "AllowHighBitCharacters=0", change it to 1 can enable the URL with Unicode. The second one is "RejectResponseUrl=", change it to "RejectResponseUrl=/~*" will enable the "Logging Only Mode". We should test it in production environment carefully first to avoild banning valid request.

3. Replace "RuleList=" to "RuleList=SQL Injection,SQL Injection Headers", and add the below rules to tail of the config file.

[SQL Injection]
AppliesTo=.asp,.aspx
DenyDataSection=SQL Injection Strings
ScanUrl=0
ScanAllRaw=0
ScanQueryString=1
ScanHeaders=

[SQL Injection Strings]

%3b ; a semicolon
/*
@ ; also catches @@
char ; also catches nchar and varchar
alter
begin
cast
convert
cursor
declare
delete
drop
end
exec ; also catches execute
fetch
kill
open
select
sys ; also catches sysobjects and syscolumns
table

[SQL Injection Headers]
AppliesTo=.asp,.aspx
DenyDataSection=SQL Injection Headers Strings
ScanUrl=0
ScanAllRaw=0
ScanQueryString=0
ScanHeaders=Cookie

[SQL Injection Headers Strings]

@ ; also catches @@
alter
cast
convert
declare
delete
drop
exec ; also catches execute
fetch
insert
kill
select

4. Next step is to create a "hello world" asp page and host it into IIS, name it like "test.asp" for example. Visit http://localhost/test.asp?q=select, one log should be written into the log file.

5. Run URLScan for days, and collect the log files. Now we need to analyze them to see if any valid URL includes the SQL Injection Strings or SQL Injection Headers Strings. Download Log Parser, your best friend to analyze any log.  Run the query below to get the result.

logparser "SELECT COUNT(*) AS Hits,cs-uri,x-reason,x-control FROM urlscan.*.log TO url.csv  GROUP BY cs-uri,x-reason,x-control ORDER BY Hits DESC" -i:W3C -o:CSV

logparser "SELECT COUNT(*) AS Hits,x-reason,x-control FROM urlscan.*.log TO keyword_type.csv  GROUP BY x-reason,x-control ORDER BY Hits DESC" -i:W3C -o:CSV
 

6. Now you can modify the SQL-injection-taboo out of the valid URL or remove the word from SQL Injection Strings and SQL Injection Headers Strings.

7. The final step is change "RejectResponseUrl=/~*" back to "RejectResponseUrl=", URLScan will reject the request which hitting rules from now on. You can analyze the log weekly with the logparser query to monitor if any invalid request is reject.