Thursday 13 September 2012

Some scripts

Script :: To compare objects in two databases.

    DECLARE @Sourcedb sysname
    DECLARE @Destdb sysname
    DECLARE @SQL varchar(max)
    
    SELECT @Sourcedb = '<<Database1>>'
    SELECT @Destdb = '<<Database2>>'
    
    SELECT @SQL = ' SELECT ISNULL(SoSource.name,SoDestination.name) ''Object Name''
                         , CASE 
                           WHEN SoSource.object_id IS NULL      THEN SoDestination.type_desc +  '' missing in the source -- ' 
                                                                                             + @Sourcedb + ''' COLLATE database_default
                           WHEN SoDestination.object_id IS NULL THEN SoSource.type_desc      +  '' missing in the Destination -- ' + @Destdb 
                                                                                             + ''' COLLATE database_default
                           ELSE SoDestination.type_desc + '' available in both Source and Destination'' COLLATE database_default
                           END ''Status''
                     FROM (SELECT * FROM ' + @Sourcedb + '.SYS.objects 
                            WHERE Type_desc not in (''INTERNAL_TABLE'',''SYSTEM_TABLE'',''SERVICE_QUEUE'')) SoSource 
          FULL OUTER JOIN (SELECT * FROM ' + @Destdb + '.SYS.objects 
                            WHERE Type_desc not in (''INTERNAL_TABLE'',''SYSTEM_TABLE'',''SERVICE_QUEUE'')) SoDestination
                       ON SoSource.name = SoDestination.name COLLATE database_default
                      AND SoSource.type = SoDestination.type COLLATE database_default
                      ORDER BY isnull(SoSource.type,SoDestination.type)'
     EXEC (@Sql)


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

Script :: To get SQL transaction locks details.

SELECT  L.request_session_id AS SPID, 
        DB_NAME(L.resource_database_id) AS DatabaseName,
        O.Name AS LockedObjectName, 
        P.object_id AS LockedObjectId, 
        L.resource_type AS LockedResource, 
        L.request_mode AS LockType,
        ST.text AS SqlStatementText,        
        ES.login_name AS LoginName,
        ES.host_name AS HostName,
        TST.is_user_transaction as IsUserTransaction,
        AT.name as TransactionName,
        CN.auth_scheme as AuthenticationMethod
FROM    sys.dm_tran_locks L
        JOIN sys.partitions P ON P.hobt_id = L.resource_associated_entity_id
        JOIN sys.objects O ON O.object_id = P.object_id
        JOIN sys.dm_exec_sessions ES ON ES.session_id = L.request_session_id
        JOIN sys.dm_tran_session_transactions TST ON ES.session_id = TST.session_id
        JOIN sys.dm_tran_active_transactions AT ON TST.transaction_id = AT.transaction_id
        JOIN sys.dm_exec_connections CN ON CN.session_id = ES.session_id
        CROSS APPLY sys.dm_exec_sql_text(CN.most_recent_sql_handle) AS ST
WHERE   resource_database_id = db_id()

ORDER BY L.request_session_id

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

Script :: Find a text in database.

CREATE PROCEDURE [REWARDS].[p_FindTextInObjects]
declare 
  @findText               nvarchar(1000),
  @havingCountGreaterThan int

set @findText = '#GLEntry'

set @havingCountGreaterThan=0

  declare @findText2 nvarchar(1002)

--  Example Calls
--    exec p_FindTextInObjects 'union all', 1
--    exec p_FindTextInObjects 'XML EXPLICIT'
--    exec p_FindTextInObjects 'declare%cursor', 1
--    exec p_FindTextInObjects '@@IDENTITY', 1
--    exec p_FindTextInObjects 'summit'
--    exec p_FindTextInObjects 'vehicle'

  if @findText is null 
    return
  
  set transaction isolation level read UNCOMMITTED
  create table #output
  ( ObjectType varchar(12),
    Name       varchar(128),
    ColumnType varchar(30),
    Length     int,
    Nullable   varchar(10),
    FindCount  int, 
    ObjectId   int
  )

  set @findText2 = '%' + upper(@findText) + '%'
  
-- tables
  insert into #output (ObjectType, Name)
  select
    case TYPE
      when 'U'  then 'Table'
      when 'F'  then 'Foreign Key'
      else TYPE
    end ObjectType,
    so.name Name
  from sysobjects so
  where so.name like @findText2
  and type in ('U','F')
  order by 1

-- columns
  insert into #output (ObjectType, Name, ColumnType, Length, Nullable)
  select
    'Column' ObjectType,
    convert(varchar(128), so.name + '.'+ sc.name) Name,
    convert(varchar(30),st.name) ColumnType,
    sc.length,
    case sc.isnullable when 0 then 'not null' else 'null' end [Null]
  from syscolumns sc
  join systypes st on st.xusertype = sc.xusertype
  join sysobjects so on sc.id = so.id
  where sc.name like @findText2
  order by 2,3

-- indexes
  insert into #output (ObjectType, Name)
  select
    'Index' ObjectType,
    si.name Name
  from sysindexes si
  where si.name like @findText2
  order by 1

-- procs, triggers,
  insert into #output (ObjectType, Name, FindCount, ObjectId)
  select
    case TYPE
      when 'P'  then 'Procedure'
      when 'TR' then 'Trigger'
      when 'U'  then 'Table'
      when 'V'  then 'View'
      else TYPE
    end ObjectType,
    OBJECT_NAME(sm.ID) as Name,
    count(*) as [FindCount],
    sm.ID
  from SYSCOMMENTS sm
  join SYSOBJECTS so on so.ID = sm.ID
  where OBJECTPROPERTY(sm.ID, 'IsMSShipped') = 0
  and PATINDEX(@findText2, upper([TEXT])) > 0
  group by sm.ID, TYPE
  having (count(*) > @havingCountGreaterThan)
  order by TYPE, [Name]

  select * from #output

  drop table #output
  set transaction isolation level read COMMITTED
  
  return
GO

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

Script :: Database buffer status


DECLARE @total_buffer INT;

SELECT @total_buffer = cntr_value
FROM sys.dm_os_performance_counters 
WHERE RTRIM([object_name]) LIKE '%Buffer Manager'
AND counter_name = 'Database Pages';

;WITH src AS
(
SELECT 
database_id, db_buffer_pages = COUNT_BIG(*)
FROM sys.dm_os_buffer_descriptors
--WHERE database_id BETWEEN 5 AND 32766
GROUP BY database_id
)
SELECT
[db_name] = CASE [database_id] WHEN 32767 
THEN 'Resource DB' 
ELSE DB_NAME([database_id]) END,
db_buffer_pages,
db_buffer_MB = db_buffer_pages / 128,
db_buffer_percent = CONVERT(DECIMAL(6,3), 
db_buffer_pages * 100.0 / @total_buffer)
FROM src
ORDER BY db_buffer_MB DESC; 

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

Script :: Database text search.


DECLARE @SearchStr nvarchar(100) = 'Corporate Web Site'
DECLARE @Results TABLE (ColumnName nvarchar(370), ColumnValue nvarchar(3630))

SET NOCOUNT ON

DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET  @TableName = ''
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

WHILE @TableName IS NOT NULL

BEGIN
    SET @ColumnName = ''
    SET @TableName = 
    (
        SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
        FROM     INFORMATION_SCHEMA.TABLES
        WHERE         TABLE_TYPE = 'BASE TABLE'
            AND    QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
            AND    OBJECTPROPERTY(
                    OBJECT_ID(
                        QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                         ), 'IsMSShipped'
                           ) = 0
    )

    WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)

    BEGIN
        SET @ColumnName =
        (
            SELECT MIN(QUOTENAME(COLUMN_NAME))
            FROM     INFORMATION_SCHEMA.COLUMNS
            WHERE         TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                AND    TABLE_NAME    = PARSENAME(@TableName, 1)
                AND    DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'int', 'decimal')
                AND    QUOTENAME(COLUMN_NAME) > @ColumnName
        )

        IF @ColumnName IS NOT NULL

        BEGIN
            INSERT INTO @Results
            EXEC
            (
                'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
                FROM ' + @TableName + ' (NOLOCK) ' +
                ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
            )
        END
    END    
END

SELECT ColumnName, ColumnValue FROM @Results


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

Wednesday 8 August 2012

List out Mirroring databases

SELECT A.name,
       CASE
         WHEN B.mirroring_state IS NULL THEN 'Not in Mirroring'
         ELSE 'In Mirroring'
       END AS MirroringState
FROM   sys.databases A
       INNER JOIN sys.database_mirroring B
               ON A.database_id = B.database_id
WHERE  a.database_id > 4
ORDER  BY A.name 

Script to find the jobs running SSIS Packages

USE msdb
go
SELECT sj.job_id     AS JobId,
       sj.name       AS JobName,
       sjs.step_name AS StepName,
       sjs.command   AS Command
FROM   sysjobs sj
       INNER JOIN sysjobsteps sjs
               ON( sj.job_id = sjs.job_id )
WHERE  sjs.subsystem = 'SSIS'
go 

Saturday 23 June 2012

Online Re-Indexing Limitation on LOB Columns

Re-index maintenance job fails with error:

ALTER INDEX <Index_PK> ON [database].[dbo].[table] REBUILD  WITH(ONLINE = ON)  : An online operation cannot be performed for index 'Index_PK' because the index contains column 'Col1' of data type text, ntext, image, varchar(max), nvarchar(max), varbinary(max), xml, or large CLR type. For a non-clustered index, the column could be an include column of the index. For a clustered index, the column could be any column of the table. If DROP_EXISTING is used, the column could be part of a new or old index. The operation must be performed offline.

Why it failed?
Online Index Build operations in SQL Server 2005, 2008 and 2008 R2 do not support tables that contain LOB columns but this limitation removed in SQL 2012.

Workaround:
Option1: Rebuild indexes using a custom script, such as Ola Hallengren's, available at http://ola.hallengren.com (recommended).

Option2: To have two re-indexing tasks, one for the table with LOB column/index by offline and other for all tables except the table with LOB by online.

Option3: Remove online index operations inside the Rebuild Indexes task in the Maintenance Plan.  This has a large impact on the server, so not recommended.

Friday 22 June 2012

Find the Index fragmentation levels and Recomendations

SELECT Db_name(Db_id())             AS DBName,
       SS.name                      AS SchemaName,
       SO.name                      AS TableName,
       SI.name                      AS Indexname,
       index_type_desc              AS IndexType,
       avg_fragmentation_in_percent AS FragmentationPercentage,
       ( CASE
           WHEN avg_fragmentation_in_percent BETWEEN 10 AND 30 THEN
           'Time to Defrag'
           WHEN avg_fragmentation_in_percent > 30 THEN 'Time to Reindex'
           ELSE 'No Action Required Now'
         END )                      AS Recomendation
FROM   sys.Dm_db_index_physical_stats(Db_id(Db_name()), NULL, NULL, NULL,
       'DETAILED')
       IPS,
       sys.indexes SI,
       sys.objects SO,
       sys.schemas SS
WHERE  IPS.index_id = SI.index_id
       AND IPS.object_id = SI.object_id
       AND SI.object_id = SO.object_id
       AND SO.schema_id = SS.schema_id
       AND IPS.index_type_desc IN ( 'NONCLUSTERED INDEX', 'CLUSTERED INDEX' )

       AND IPS.indes_level = 0 -- leaf level only
ORDER  BY recomendation DESC 



Thursday 21 June 2012

Negative SPIDs in SQL Server


While investigating SQL performance issues,you might see SPIDs with negative number blocking other processes.

SPID -2  -> orphaned distributed transaction SPID

The SPID may still be holding on resources ( table, page or row locks), and blocking other SPIDs which want to access that database object. But  KILL command can’t handle SPIDs with a value of less than 1.

Kill -2
Msg 6101, Level 16, State 1, Line 1
Process ID -2 is not a valid process ID. Choose a number between 1 and 2048

To fix it:

select req_transactionUOW
from master..syslockinfo
where req_spid = -2

This will return a 32 digit UOW number eg: 'EDF10728-0156-1112-C501-AG48D72D2310'

KILL 'EDF10728-0156-1112-C501-AG48D72D2310'

Now if you check sp_who/sp_who2 all the offending SPID would have disappeared.

For negative SPIDS (-3 and -4)..

Please refer..

http://www.sqlskills.com/BLOGS/PAUL/post/Disaster-recovery-101-dealing-with-negative-SPIDS-%28-2-and-3%29.aspx


To Establish DB Mirroring between different domain servers using certificates

DB mirror cannot be established between different domain servers and might fail with below error.

 "The server network address "TCP://server.domain.com:5022" can not be reached or does not exist. Check the network address name and reissue the command. (Microsoft SQL Server, Error: 1418)"

In this case, DB mirroring can be configured by using certificates.

Steps to setup DB mirroring using certificates.

On Principle Server:

-- Create the database master key
USE master;
CREATE master KEY encryption BY password = '<Password>';
go

-- Create a certificate for DB mirror
USE master;
CREATE certificate principlecert WITH subject =
'Principle certificate for DB mirror';
go

-- Create a mirror endpoint using certificate
CREATE endpoint endpoint_mirroring state = started AS tcp ( listener_port=5022,
listener_ip = ALL ) FOR database_mirroring ( authentication = certificate
principlecert, encryption = required algorithm aes, role = ALL );
go

-- Back up the certificateBACKUP CERTIFICATE PrincipleCert TO FILE = 'D:\PrincipleCert.cer';
-- Copy the certificate (PrincipleCert.cer) to mirror server


On Mirror Server:

-- Create the database master key
USE master;
CREATE master KEY encryption BY password = '<Password>';
go

--- Create a certificate for DB mirrror
USE master;
CREATE certificate mirrorcert WITH subject = 'Mirror certificate for DB mirror';
go

-- Create a mirror endpoint using certificate
CREATE endpoint endpoint_mirroring state = started AS tcp ( listener_port=5022,
listener_ip = ALL ) FOR database_mirroring ( authentication = certificate
mirrorcert, encryption = required algorithm aes, role = ALL );
go

--Back up the certificate
BACKUP certificate mirrorcert TO FILE = 'D:\MirrorCert.cer';
go
-- Copy the certificate(MirrorCert.cer)  to Principle server 

Note: For DB mirror purpose, I have created same login (eg:MirrorUser) on both Principle and Mirror server.

On Principle Server:

-- Create a login on Principle for Mirror server
USE master;
CREATE login mirroruser WITH password = 'password';
go

-- Create user on master
USE master;
CREATE USER mirroruser FOR login mirroruser;
go

-- Associate the certificate with the user
CREATE certificate mirrorcert AUTHORIZATION mirroruser FROM FILE =
'C:\MirrorCert.cer'
go

-- Grant CONNECT permission for endpoint.


GRANT connect on endpoint::endpoint_mirroring to [mirroruser];
go

On Mirror Server:

-- Create a login on Mirror for Principle server
USE master;
CREATE login mirroruser WITH password = 'password';
go

-- Create  user on master
USE master;
CREATE USER mirroruser FOR login mirroruser;
go

-- Associate the certificate with the user
CREATE certificate principlecert AUTHORIZATION mirroruser FROM FILE =
'D:\PrincipleCert.cer'
go

-- Grant CONNECT permission for endpoint
GRANT connect on endpoint::endpoint_mirroring to [mirroruser];
go
 

Configuring the Mirroring Partners
On Mirror Server:

ALTER DATABASE mirrortestdb
SET partner = 'TCP://PrincipleServer.domain.com:5022';
go 

On Principle server:

ALTER DATABASE mirrortestdb
SET partner = 'TCP://MirrorServer.domain.com:5022';
go

-- Change to high-performance mode
ALTER DATABASE mirrortestdb
SET partner safety OFF
go 

Sunday 27 May 2012

Backup on SQL Server 2008 R2 database fails if you enable change tracking on database

BACKUP DATABASE [DB_Name] TO  DISK = N'D:\MSSQL\DB_Name.bak'
WITH STATS = 10
GO


Executing the query "BACKUP DATABASE [DB_Name] TO  DISK = N'D:\MSSQL\DB_Name.bak' failed with the following error: "Cannot insert duplicate key row in object 'sys.syscommittab' with unique index 'si_xdes_id'.
Failed to flush the commit table to disk in dbid 5 due to error 2601. Check the errorlog for more information.
BACKUP DATABASE is terminating abnormally.
The statement has been terminated.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.


This error occuring due to change tracking enabled on the database and Microsoft confirmed this a bug in SQL 2008 R2 RTM version. Need to apply latest service pack to fix this issue.

Ref - http://support.microsoft.com/kb/2522893 , http://support.microsoft.com/kb/2603910

Database Mirroring status is disconnected or synchronizing but no logs moving

Problem::
Database Mirroring status is disconnected or synchronizing but no logs moving.

Steps to Resolve::

Resume the mirroring.
Note :: Trying to resume mirroring from remote would not work all the times, So connect directly and resume it.

ALTER DATABASE <Database Name> SET PARTNER RESUME;

If no changes in mirroring state try to pause(suspend) and resume it.

ALTER DATABASE <Database Name> SET PARTNER SUSPEND;

ALTER DATABASE <Database Name> SET PARTNER RESUME;

If it fails with below error.
Msg 1447, Level 16, State 21, Line 1
ALTER DATABASE "Database Name" command cannot be executed until both partner server instances are up, running, and connected. Start the partner and reissue the command.
(OR)
Msg 1404, Level 16, State 11, Line 1
The command failed because the database mirror is busy. Reissue the command later.


Try to restart the endpoints(This should fix the issue)
use master
GO
alter endpoint endpoint_name state = stopped;
GO
alter endpoint endpoint_name state = started;
GO


If nothing works, restart the Mirror server SQL services. After restart if mirroring is in suspended state, resume it.

Wednesday 23 May 2012

SQL Server Resource Database

Resource database is a system database which is not accessible during normal operations.It is a read only database that contains all system objects used by an SQL server.It is logically presented as system schema in every database. It contains the structure and description of all system objects and no user data.

This database helps to roll back the service pack installation very easily. All you have to do is before SP installation just make a copy of this database so that you can replace the new resource database with old one if needed.

This concept introduced in SQL 2005.

TUF File in SQL server

TUF file is a Transaction Undo file. File containing information regarding any modifications that were made as part of incomplete transactions at the time the backup was performed. A transaction undo file is required if a database is loaded in read-only state. In this state, further transaction log backups may be applied.

TUF file is created when configuring log shipping in Standby mode, TUF file plays important role in log shipping. All uncommitted transactions are recorded to the TUF file while restoring the log backup into standby database so that users can read the database. And in next log backup, server will fetch all uncommitted transactions from undo file and check whether committed or not. If committed, those transactions will included in the log backup else it will be remain in TUF file.

Databases without any backup

SELECT    
   CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS Server,
   master.dbo.sysdatabases.NAME AS database_name,
   NULL AS [Last Data Backup Date],
   9999 AS [Backup Age (Hours)]
FROM
   master.dbo.sysdatabases LEFT JOIN msdb.dbo.backupset
       ON master.dbo.sysdatabases.name  = msdb.dbo.backupset.database_name
WHERE msdb.dbo.backupset.database_name IS NULL AND master.dbo.sysdatabases.name <> 'tempdb'
ORDER BY
   msdb.dbo.backupset.database_name 

SQL Server/Agent restart time

SELECT [SQL Server Start Time] = CONVERT(VARCHAR(23), a.sql_start, 121),
       [SQL Agent Start Time] = CONVERT(VARCHAR(23), a.agent_start, 121),
       [SQL Uptime] = CONVERT(VARCHAR(15),
                      RIGHT(10000000+Datediff(dd, 0, Getdate()-a.sql_start), 4)
                      + ' '
                      + CONVERT(VARCHAR(20), Getdate()-a.sql_start, 108)),
       [Agent Uptime] = CONVERT(VARCHAR(15),
RIGHT(10000000+Datediff(dd, 0, Getdate()-a.agent_start), 4)
+ ' '
+ CONVERT(VARCHAR(20), Getdate()-a.agent_start, 108))
FROM   (SELECT SQL_Start = Min(aa.login_time),
               Agent_Start = NULLIF(Min(CASE
                                          WHEN aa.program_name LIKE 'SQLAgent %'
                                        THEN
                                          aa.login_time
                                          ELSE '99990101'
                                        END), CONVERT(DATETIME, '99990101'))
        FROM   master.dbo.sysprocesses aa
        WHERE  aa.login_time > '20000101') a 

 

Compressed objects in a database

SELECT st.name, st.object_id, sp.partition_id, sp.partition_number, sp.data_compression,
sp.data_compression_desc FROM sys.partitions SP
INNER JOIN sys.tables ST ON
st.object_id = sp.object_id
WHERE data_compression <> 0

SQL Server 2012

SQL SERVER 2012 is now available for download. Try new SQL Server 2012 Evaluation and SQL Server 2012 Express.


SQL Server Release History

SQL Server 2012
codename Denali

SQL Server 2008 R2
codename Kilimanjaro

SQL Server 2008
codename Katmai

SQL Server 2005
codename Yukon

SQL Server 2000
codename Shiloh

SQL Server 7.0 OLAP
codename Plato

SQL Server 7.0
codename Sphinx

SQL Server 6.5
codename Hydra

SQL Server 6.0
codename SQL95

SQL Server 4.2.1
codename SQLNT

SQL Server 1.0, 1.1