Identify the size and document count of a single SharePoint Site

The following query is useful, if you have a SharePoint site which uses one content database and all websites hang off the one top url.  The script can be used to identify the total size of each site and the number of documents contained in the site.  

USE [<YourContentDatabaseName>]; — don’t forget the semi-colon!

with
folderhierachy as(
select f.fullurl, (((sum(cast(d.size as bigint))) / 1024) /1024) as sizeinMB, count(d.Id) as DocCount
from webs f, docs d, lists l
where
d.webid = f.id
and
l.tp_id = d.listid
and
d.size > 0
and
(d.LeafName NOT LIKE ‘%.stp’)
AND (d.leafname NOT LIKE ‘%.aspx’)
AND (d.leafname NOT LIKE ‘%.xfp’)
AND (d.leafname NOT LIKE ‘%.dwp’)
AND (d.leafname NOT LIKE ‘%template%’)
AND (d.leafname NOT LIKE ‘%.inf’)
AND (d.leafname NOT LIKE ‘%.css’)
group by f.FullUrl
)
select substring(fullurl,1,charindex(‘/’,fullurl)) as Url, sum(sizeinMB) as “Size In MB”, sum(DocCount) as “Document Count”
from folderhierachy
group by substring(fullurl,1,charindex(‘/’,fullurl))
order by Url, [Size In MB] desc;

 

Weekly SQL: Create a trigger to send an email when a login is amended.

The following trigger can be used to send an email when a login is created, altered or dropped. This is useful to audit when a new login is configured on a server and to provide a paper trail or alert on work being performed by other DBAs.

——

USE [master]
GO
IF EXISTS (SELECT * FROM sys.server_triggers
WHERE name = ‘ddl_trig_LoginEvents’)
DROP TRIGGER ddl_trig_LoginEvents
ON ALL SERVER;
GO
CREATE TRIGGER ddl_trig_LoginEvents
ON ALL SERVER
FOR CREATE_LOGIN, ALTER_LOGIN, DROP_LOGIN
AS
— Declare variables
DECLARE @mailSubject Nvarchar(100);
DECLARE @mailBody Nvarchar(MAX);
DECLARE @data XML;
DECLARE @eventType nvarchar(max);
DECLARE @newuser Nvarchar(max);
DECLARE @creationuser Nvarchar(max);
DECLARE @sql Nvarchar(max);

— Set Data
SET @data = EVENTDATA();
SET @newuser = @data.value(‘(/EVENT_INSTANCE/ObjectName)[1]‘, ‘nvarchar(max)’);
SET @creationuser = @data.value(‘(/EVENT_INSTANCE/LoginName)[1]‘, ‘nvarchar(max)’);
SET @eventType = @data.value(‘(/EVENT_INSTANCE/EventType)[1]‘, ‘nvarchar(max)’);
SET @sql = @data.value(‘(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]‘,’nvarchar(max)’)

—- Set the email data
SET @mailSubject = ‘New SQL Login Event ‘ + @eventType + ‘ occurred on: ‘ + @@SERVERNAME;
SET @mailBody = ‘A login event was detected on the SQL Server: <b>’ + @@SERVERNAME + ‘<br></b>’ +
‘User name affected: <b>’ + ISNULL(@newuser, ‘Null User Name’) + ‘<br></b>’ +
‘Event type : <b>’ + ISNULL(@eventType, ‘Null event’) + ‘<br></b>’ +
‘Performed by user: <b>’ + ISNULL(@creationuser, ‘Null Created User’) + ‘<br></b>’ + +
‘On date: <b>’ + CONVERT(nvarchar, getdate(), 13) + ‘</b><br>’ +
‘SQL command executed (if any):<b> ‘ + ISNULL(@sql, ‘No SQL’) + ‘<p> ‘ +
‘Please verify why this login was edited on a production server!’ + ‘<br></b>’ ;

–Send the mail
EXEC msdb.dbo.sp_send_dbmail
@recipients=N’<enter Email Address or create an Operator>’,
@subject=@mailSubject,
@body = @mailBody,
@profile_name = ‘DefaultMailProfile’ — Change to the configured Mail Profile,
@body_format = HTML;

———————-

The email will look like the following:

A login event was detected on the SQL Server: SQL_Server_Prod
User name affected: Domain\User1
Event type : DROP_LOGIN
Performed by user: DOMAIN\DBA1
On date: 18 Nov 2013 15:27:13:133
SQL command executed (if any): DROP LOGIN [Domain\User1]

Please verify why this login was edited on a production server!

Weekly SQL: Get automatic alerts if a database hasn’t been backed up.

I add the following procedure to all new SQL Servers Instances I install, so that I can keep a close eye on the status of database backups.  I set up a scheduled job to execute this procedure each morning and it will email out a list of any databases which have not been backed up for over 24 hours. It is very useful if you don’t have a tool such as RedGate SQL Monitor or other monitoring software.

Pre-Requisites: Database Mail is configured.

Create this procedure on the Master Database.  You can amend the wording of the email as you like.  Then set up an SQL Agent job to execute this procedure each day.

USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[BackupCheckNotification]

AS
BEGIN
SET NOCOUNT ON;

DECLARE @Data as Table
(ID INT IDENTITY (1,1),
DBName Nvarchar(128),
LastBackupDate datetime)

DECLARE @BackupsNotDone as Table
(ID INT IDENTITY (1,1),
DBName Nvarchar(128),
LastBackupDate datetime)

DECLARE @mailBody Nvarchar(MAX);
DECLARE @mailSubject Nvarchar(100);
DECLARE @cnt int, @count int;
DECLARE @DataRecord Nvarchar(500);
SET @cnt = 0;
SET @count = 1;

SET @mailSubject = ‘Full Database Backups Failing on Server: ‘ + @@SERVERNAME;
SET @mailBody = ‘The following database(s) running on ‘ + @@servername + ‘ have not been backed for over a day. <p>’

Insert into @Data
select database_name,
COALESCE(Convert(varchar(25), MAX(backup_finish_date), 113),’Backup Not Taken’)
from msdb.dbo.backupset
WHERE type = ‘D’
and database_name in (select name from sys.databases where state_desc = ‘ONLINE’)
GROUP BY database_name
UNION
SELECT Name, ’1900-01-01 00:00:00.000′ as ‘Backup Not Taken’
FROM sys.databases
WHERE name NOT IN
(SELECT database_name from msdb.dbo.backupset
WHERE type = ‘D’
GROUP BY database_name)
AND name != ‘TempDB’

INSERT INTO @BackupsNotDone
select DBName, LastBackupDate
from @Data where LastBackupDate < DATEADD(day, -1, GETDATE())

select @cnt = COUNT(*) from @BackupsNotDone;

IF @cnt > 0
BEGIN
WHILE @count <= @cnt
BEGIN
SET @DataRecord = ”;
DECLARE @backupDate varchar(25);
set @backupDate = ”;

SELECT @backupDate = CASE LastBackupDate WHEN ’1900-01-01 00:00:00.000′ THEN ‘Never Backed Up’ ELSE convert(nvarchar(25), LastBackupDate, 113) END
FROM @BackupsNotDone
WHERE ID = @count;

SELECT @DataRecord = ‘<b>’ + DBName + ‘ </b> – Last Back Up Date: ‘ + @backupDate
FROM @BackupsNotDone where ID = @count;

SET @mailBody = @mailBody + ‘<BR>’ + @DataRecord ;
set @count = @count + 1;

END

— Email out the notification:
EXEC msdb.dbo.sp_send_dbmail
@recipients=N’<Enter email addresses here, or add an operator>’,
@subject=@mailSubject,
@body = @mailBody,
@profile_name = ‘DefaultMailProfile’ — <change this to your mail profile settings>,
@body_format = HTML;

END

END

Red Gate SQL Monitor Metric – New logins to the Sysadmin role.

Red Gate SQL Monitor Metric – New logins to the Sysadmin role.

Another one of my SQL Monitor custom metrics has been published by Red Gate.  This one generates an alert when the count of server principles who are added to the sysadmin server role changes.  It is very useful when multiple members of an IT team may have a DBA support function and are inclined to simple add users with sysadmin roles. This metric can be used to alert when this happens so it can be checked and verified in case it causes a security risk.

Weekly SQL: Filter on SP_WHO2 in a table.

This is a new section of my blog, where I plan to publish a SQL script on a weekly basis.  These will be scripts I either use on a daily basis or ones which I find particularly interesting and worth sharing.

This week, the following script is really useful for finding out who is connected to a particular database. It uses the SP_WHO2 special procedure and allows the data to be filtered.  I am not sure where I got this script from, but it is not mine, but I must use it every day:

Run this on the database you wish to query:

DECLARE @Table TABLE(
SPID INT,
Status VARCHAR(MAX),
LOGIN VARCHAR(MAX),
HostName VARCHAR(MAX),
BlkBy VARCHAR(MAX),
DBName VARCHAR(MAX),
Command VARCHAR(MAX),
CPUTime INT,
DiskIO INT,
LastBatch VARCHAR(MAX),
ProgramName VARCHAR(MAX),
SPID_1 INT,
REQUESTID INT
)

INSERT INTO @Table EXEC sp_who2

SELECT *
FROM @Table
where dbname = db_name(db_id())

You can add to the where clause to filter on the different columns.

I also use this script if I am restoring a database and need to quickly kill of any users.  By adding the following extra code after the above, it will generate a the kill commands which I can copy and paste to a new query window:

–Generate a kill script
SELECT ‘kill ‘ + cast(spid as varchar(3))
FROM @table
WHERE dbname = db_name(db_id())

First Redgate SQL Metric published

First Redgate SQL Metric published

A while ago, my first Red Gate SQL metric was published for use with Red Gates excellent SQL Monitor software.  This metric allows you to be alerted when a transaction log grows over a defined threshold.  This can be particularly useful if a process is stopping the log from truncating or the transaction backups have not been running successfully.

SPN Setup for Double hop from Client (IE) to IIS 8 to SQL Server (2012)

The following is the required steps to set up kerberos authentication for a client to sql server.

This is a rough post, created purely for self reference.  A lot of this work is talked about at the following location http://blogs.msdn.com/b/psssql/archive/2011/02/21/sharepoint-adventures-using-kerberos-with-the-report-server.aspx

On IIS:

  • Open ISS Manager and go to application pools.
  • Set the correct application pool to use a dedicated user – right click and slect advanced settings. Change identity to the domain user required. If you’re not sure what application pool is the being used by the web app, stop them all and then start them individually, whilst refreshing the web app. When the correct one is used, the web app should work (somewhat!).
  • Next, go to the web application web site in IIS manager. Double click authentication and enable ASP.NET Impersonation (right click and select enable).
  • Right click on Windows Authentication and enable too.
  • Right click on Windows authentication and select Advance Settings and untick Enable Kernel-mode Authentication.
  • Click ok then right click on Windows Authentication and select providers.
  • Add Negotiate:Kerberos from the available providers drop down list.  Make sure this is the top of the list of enabled providers, above negotiate.

On a domain connected computer:

Add the SPN’s:

  • Open a cmd window and add an spn for the service account that the web app is running under. This is the domain account you set for the application pool.  This SPN should be for HTTP service for the URL of the server. In this case below the server name:
    setspn -A HTTP/WebserverName domain\domainuser
    i.e: setspn -A HTTP/SGBB1234 CONTOSO\WebAppServiceUser
  • Add the SPN for the Fully qualified domain name too, i.e.:
    setspn -A HTTP/SGBB1234.CONTOSO.UK.COM CONTOSO\WebAppServiceUser
  • Now check the spn is set for the SQL Server Service account. This is the account the SQL Server is running under:
    setspn -l SQLServerServiceAccount
  • If nothing is listed, then add the spn for the database instance using port number and instance name:
    setspn -A MSSQLSvc/ServerNameFQN:portnumber domain\SQLServiceAccount
    setspn -A MSSQLSvc/ServerNameFQN:InstanceName domain\SQLServiceAccount
    i.e.:
    setspn -A MSSQLSvc/DBServer.Contoso.UK.COM:1453 contoso\Account1
    setspn -A MSSQLSvc/DBServer.Contoso.UK.COM:Instance1 contoso\Account1

Once all is done, run the command setspn -X to check for any duplicates. Remove any duplicate SPN’s from the incorrect location.

Now setup Delegation:

Once the SPN’s are set then the delegation tab will be visible in AD for users:

  • Open AD Users and Computers and navigate to the domain user used to run the app pool web service.
  • Click on Delegation tab and select Trust this user for delegation any service, or to a specific service if more granulatrity required.
  • Do the same for the IIS server in AD too.

Once all the above is complete, restart IIS.

On the client pc, make sure no kerberos tickets are cached and causing a incorrect response.  Do this by opening a cmd window and typing “klist purge”. It should say tickets cleared.

Now do a ctrl + F5 refresh in IE, and the kerberos authentication should work!

Hopefully that is it!

Follow

Get every new post delivered to your Inbox.