Hier werde ich einen SQL Blog aufbauen, der Sie mit Spezialthemen versorgt, die mich in meiner Arbeitszeit geärgert haben.
Zum Beispiel:
Vor allem möchte ich aber die Internas beleuchten, die für viele Analysen unerlässlich sind.
Mo
01
Sep
2014
Wer bei einem SQL Server schon mal die Netzwerkeinstellungen angeschaut hat, hat feststellen können, dass es zwei verwirrend ähnliche Einstellungsfelder bei den TCP/IP-Einstellungen gibt:
Wenn man den SQL Server auf einen bestimmten TCP-Port festlegen will funktioniert das mit beiden.
ABER: Es gibt einige gravierende Unterschiede:
Das heißt, man sollte sich genau überlegen, was man verwendet, damit es nicht zu Komplikationen kommt.
Beispielsweise:
ABER: Es gibt einige gravierende Unterschiede:
Das heißt, man sollte sich genau überlegen, was man verwendet, damit es nicht zu Komplikationen kommt.
Beispielsweise:
Do
20
Mär
2014
Folgende Fehlermeldung erscheint, wenn zum Beispiel ein SQL Server Job einen Service Account aus dem Active Directory als Owner beinhaltet. Der Service Account steht jedoch in keiner Beziehung zum Service Account des SQL Servers oder des SQL Server Agents.
Unable to determine if the owner (<Domain>\<Username>) of job 41BE1A4A-1E6B-4CC2-946C-6D38C6612D0C has server access (reason: Could not obtain information about Windows NT group/user '<Domain>\<Username>', error code 0x5. [SQLSTATE 42000] (Error 15404)).
Der Fehler kommt daher, dass der SQL Server Service Account keine Berechtigung im Active Directory hat, um Informationen des "unbekannten" Benutzers aus dem Active Directory zu lesen.
Um den Fehler nicht mehr zu erhalten, muss dem Service Account vom SQL Server das Recht gegeben werden, um die Informationen vom Service Account (der im SQL Job als Owner angegeben wurde) im Active Directory auszulesen.
Hierzu muss im Active Directory folgendes gemacht werden:
Um die Änderungen am SQL Server wirksam zu machen, muss der SQL Server Dienst neugestartet werden.
Do
29
Aug
2013
Welcher Admin kennt das nicht: Die Anwender schreien, dass die Anwendung zu langsam ist? Was tun? Erstmal einen Blick auf die aktuellen Prozesse werfen. Welche Prozesse haben den Status "suspended"?
Aber was soll diese Wait-Resource-Spalte mit der kryptischen Zeichenfolge? Diese Frage habe ich mir auch schon gestellt und aus diesem Grund eine Prozedur erstellt, die aus der kryptischen Zeichenfolge weitgehend den genauen Teil, der blockiert wird, spezifiziert.
Es gibt verschiedene Arten von waitresource-Strings. Ein wichtiges Kriterium für die Erkennung des Objektes, auf den gewartet wird, ist der vorangestellte Objekttyp. Dieser Typ kann folgende Ausprägungen haben:
RID: In diesem Fall liegt die Sperre auf der internen ROWID einer Tabelle. Eine ROWID existiert nur auf Tabellen, die keinen eindeutigen Clustered Index haben. Es ist eine vom SQL Server erzeugte GUID zur eindeutigen Identifikation des Datensatzes.
PAGE / PAG: Im Falle einer Page als Wartemedium handelt es sich um eine dedizierte 8-KB-Seite im SQL Server. Das können verschiedene Arten von Pages sein. Meistens handelt es sich um Index-Pages und Table-Pages.
EXT: EXT steht für Extent, welcher physikalisch mit einer Page vergleichbar ist, aber aus einer Menge von 8 Pages = 64 KB besteht.
OBJECT / TAB: In diesem Fall wird auf das vollständige Objekt, meistens eine Tabelle, gewartet, das heißt, der Prozess möchte das Objekt vollständig sperren.
KEY: Wenn eine Tabelle kein Heap ist, sondern einen clustered Index hat, so wird analog zur RowID auf Zeilen von Primärschlüssel gewartet.
Mit diesen Erkenntnissen habe ich eine Prozedur erstellt, die aus diesem String, der die Wait-Resource identifiziert, das spezifische Objekt, also die Tabelle, und wenn möglich sogar die betroffenen Zeilen zurückgibt.
Bei dem Typ KEY ist es nämlich möglich durch den in Klammern stehenden Teil die betreffenden Zeilen im SQL Server zu identifizieren.
Di
04
Jun
2013
Ein Thema, das mich kürzlich beschäftigt hat, ist das programmatische Setzen des MaintenanceMode im Microsoft System Center Operations Manager (SCOM) eines einzelnen Rechners.
1. Der erste Versuch diese Funktionalität mit Powershell zu skripten, habe ich auf Grund des unverhältnismäßigen Zeitaufwands und der Komplexität auf Eis gelegt gehabt.
2. Im zweiten Schritt habe ich einfach beim Setzen des MaintenanceMode in der OperationsShell die Datenbankaktivitäten ausgewertet. Ergebnis war, dass es eine spezielle Prozedur gibt, die den MaintenanceMode starten kann. Die Prozedur heißt [p_MaintenanceModeStart] und enthält vorwiegend die Parameter, die auch in der Operations Shell abgefragt werden. Einzige Schwierigkeit ist die Ermittlung der richtigen "BaseManagedEntityId". Um die Handhabung des MaintenanceMode zu vereinfachen, habe ich nachfolgende Prozedur erstellt, die den übergebenen Computername in den MaintenanceMode setzt.
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ADMIN_SCOM_ComputerMaintenanceModeStart]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[ADMIN_SCOM_ComputerMaintenanceModeStart]
GO
/*
Autor: Patrick Fiedler
Ablauf: 1. Überprüfen, ob auf dem Server eine OperationsmanagerDatenbank existiert
2. Sammeln der benötigten Informationen
3. Setzen des MaintenanceMode
*/
create procedure [dbo].[ADMIN_SCOM_ComputerMaintenanceModeStart]
@ComputerName nvarchar(200),
@EndTime datetime,
@Comment nvarchar(200),
@StartTime datetime = null
as
set nocount on
declare @dbname nvarchar(250),
@ScomDatabaseName nvarchar(250),
@BaseManagedEntityId uniqueidentifier,
@sql nvarchar(max)
-- Übersetzen der Datumswerte in UTC
set @EndTime = dateadd(minute, -datediff(mi,getutcdate(),getdate()), @EndTime)
if(@StartTime is not null)
set @StartTime = dateadd(minute, -datediff(mi,getutcdate(),getdate()), @StartTime)
-- Check, ob ScomDB auf dem Server existiert
declare #cur cursor for
select d.name
from sys.databases d
where d.database_id>4
open #cur
fetch next from #cur into @dbname
while @@FETCH_STATUS=0
begin
begin try
exec('
declare @Date datetime
select top 1
@Date=StartTime
from ['+@dbname+'].dbo.MaintenanceMode m
')
set @ScomDatabaseName = @dbname
print 'INFO: Die SCOM-Datenbank ist '+@ScomDatabaseName+'.'
break
end try
begin catch
print 'INFO: Die Datenbank '+@dbname+' ist keine SCOM-Datenbank.'
end catch
fetch next from #cur into @dbname
end
close #cur
deallocate #cur
-- Ermitteln der Entity-ID
set @sql='
SELECT @BaseManagedEntityId=[BaseManagedEntityId]
FROM ['+@ScomDatabaseName+'].[dbo].[BaseManagedEntity]
where BaseManagedEntityId=TopLevelHostEntityId
and FullName like ''Microsoft.Windows.Computer:%''
and Name like '''+@ComputerName+'%''
'
exec sp_executesql @sql, N'@BaseManagedEntityId uniqueidentifier output', @BaseManagedEntityId=@BaseManagedEntityId out
print 'BaseEntityId: '+cast(@BaseManagedEntityId as nvarchar(50))
if(@BaseManagedEntityId is null)
begin
raiserror('ERROR: Es konnte keine BaseEntityId ermittelt werden.',16,1)
return -1
end
set @sql='
use ['+@ScomDatabaseName+']
declare @CurrentUser nvarchar(200)
set @CurrentUser = SUSER_NAME()
exec [p_MaintenanceModeStart]
@BaseManagedEntityId=@BaseManagedEntityId,
@ScheduledEndTime = @EndTime,
@ReasonCode = 0, -- Unknown (Planned)
@Comments = @Comment,
@User = @CurrentUser, --
@Recursive=1, -- all contained objects
@StartTime=@StartTime -- now
'
exec sp_executesql @sql,
N'@BaseManagedEntityId uniqueidentifier, @EndTime datetime, @Comment nvarchar(200), @StartTime datetime',
@BaseManagedEntityId=@BaseManagedEntityId,
@EndTime=@EndTime,
@Comment=@Comment,
@StartTime=@StartTime
Mi
22
Mai
2013
Letztens hatte ich eine kuriose Fehlermeldung beim Ausführen von xp_fileexist.
DECLARE @FileExists INT, @MailAnhangPfad NVARCHAR(MAX)
SET @MailAnhangPfad = 'D:test.txt'
EXEC master.sys.xp_fileexist @MailAnhangPfad, @FileExists OUT
Der Fehler sah folgendermaßen aus:
Msg 22027, Level 15, State 1, Line 0
Usage: EXECUTE xp_fileexist [, OUTPUT]
Die Fehlermeldung wird eigentlich nur geworfen, wenn nichts übergeben wurde. Aber in diesem Fall kommt der Fehler auch, weil die Variable @MailAnhangPfad NVARCHAR(MAX) ist und das verarbeitet die Prozedur nicht. Deswegen hilft einfach statt NVARCHAR(MAX) NVARCHAR(4000) zu verwenden. Das heißt, der Code muss wie folgt geändert werden:
DECLARE @FileExists INT, @MailAnhangPfad NVARCHAR(4000)
SET @MailAnhangPfad = 'D:test.txt'
EXEC master.sys.xp_fileexist @MailAnhangPfad, @FileExists OUT
Und dann klappt es auch ...
Do
02
Mai
2013
Im Laufe der Zeit sammeln sich als SQL-Administrator bei den verschiedensten Notfällen bzw. Situationen Skripte an, die danach nicht mehr so einfach gefunden und wieder verwendet werden können. Aus diesem Grund ist in mir der Gedanke entstanden:
Wieso, wenn man so viele Skripte zur Lösung von Problemen erstellt, aber selten wieder verwendet werden kann, nicht eine separate SQL Server Datenbank erstellen, die eine Art Werkzeugkasten für den SQL Administrator darstellt und die erstellten Skripte wiederverwertbar in dieser Datenbank zu verewigen?
Wenn man jedoch einige Server mehr verwaltet, stellt sich die Frage, wie kann ich diese Datenbank auf allen Systemen aktuell halten. Man muss die Datenbanken immer aktuell halten, so dass man dafür eine Lösung finden muss:
Di
23
Apr
2013
Vor Kurzem erreichte mich eine Mail mit ein paar Fragen:
Ich komme immer wieder in die Situation SQL Skripte und Reports zu entwickeln. In den durchaus komplexen und gewachsenen Strukturen unserer Kunden kommt es nun immer wieder auf Performance und sauberen Code (u.a. Zugriff auf Daten, Objektsperren, etc.) an. Daher die Frage ob Du gute Ressourcen (Blogs, Bücher, etc.) für folgende Themen empfehlen kannst?
So pauschal lässt sich das eben nicht sagen. Man kann zwar ein paar Grundregeln bzw. Grundvoraussetzungen benennen, aber der Rest hängt von der jeweiligen Situation ab.
Der Flaschenhals kann ja sehr unterschiedlicher Natur sein, zum Beispiel zu wenig I/O-Durchsatz, fehlende Indizes, erhöhte Komplexität der Abfrage, usw.
Wenn man nun aber vor hat, sich in Sachen Performance-Optimierung weiterzubilden, so ist es essentiell, dass man grundlegend die Funktionsweise des MS SQL Servers versteht und dass man nachvollziehen kann, wie der SQL Server seine Abfragen verarbeitet und versucht zu optimieren. Für diese Grundlagen empfehle ich jedem das Buch Microsoft SQL Server 2008 Internals (aktuell ist noch das 2008er Buch, aber am 31. Juli 2013 erscheint die 2012er Version des Buches). In dem Buch ist nicht beschrieben wie ich mir einen Wartungsplan zusammenklicke, aber dafür ist im Detail erklärt, wie der SQL Server agiert und wie er seine Daten organisiert. Mit diesem Verständnis von der Vorgehensweise des SQL Servers kann man wesentlich besser Performance-Engpässe in Abfragen erkennen.
Im nächsten Schritt ist es unerlässlich, zu lernen, wie man Ausführungspläne liest und dessen Inhalt deuten kann. Vor allem muss man identifizieren können, an welchen Stellen im Ausführungsplan Engpässe entstehen können.
Im Endeffekt kann man aber einige wichtige Regeln aufstellen, die in den meisten Fällen Anwendung finden können:
1. Lieber Komplexität verringern und mit Zwischenschritten arbeiten. Das macht die Arbeit für den Abfrageoptimierer einfacher und eindeutiger.
2. Immer Tests mit den Abfragen machen und die Ausführungspläne studieren.
3. Den SQL Server Profiler verwenden, um die Laufzeiten, die CPU-Auslastung und die I/O-Werte zu analysieren.
Zum Thema Datensperre gibt es im MS SQL Server 2008 einen eleganten Weg, dem with (nolock)-Hint aus dem Weg zu gehen, denn es gibt das Snapshot-Isolation-Level.
Ohne die Einstellung des Snapshot-Isolation-Level wird bei jedem SELECT während des Datenabrufes ein Shared-Lock (die Tabelle wird vor ungewollter Änderung während der Sperre geschützt) auf die involvierte Tabelle gesetzt und alle anderen Prozesse, die die Daten manipulieren wollen, sind gezwungen so lange zu warten, bis das SELECT vollzogen wurde.
Letztendlich benötigt man viel Erfahrung und Verständnis auf diesem Gebiet.