Overblog
Folge diesem Blog Administration + Create my blog
Blog von Olaf Helper

Verlauf der Systemspeichernutzung ermitteln

24. Februar 2011 , Geschrieben von Olaf Helper Veröffentlicht in #T-SQL

Die DMV sys.dm_os_ring_buffers, die mit Microsoft SQL Server Version 2005 eingeführt wurde, gehört zu den wenigen, die offiziell nicht dokumentiert ist und in der BOL zu den DMVs zum Betriebssystem steht „..not supported …only for information … not guaranteed …“. Nun, für Applikationen würde ich die DMV als Informationsquelle nicht verwenden, aber ein Blick schadet nicht, vielleicht liefert sie doch interessante Informationen.

 

Die View selbst ist sehr „flach“, nur 4 Felder:

-       ring_buffer_address varbinary(8): Mit der kann ich noch nichts anfangen

-       ring_buffer_type nvarchar(60): Eine Typebezeichnung in Klartext

-       timestamp bigint: Weder datetime noch rowversion, sondern reine Zahlen

-       record nvarchar(2048): Die Daten sehen aus wie XML, sind nur nicht so deklariert

 

Der Inhalt von „timestamp“ war schnell geklärt, es sind die Ticks (= Millisekunden) seit dem Rechnerneustart, hat also nichts mit @@TIMETICKS zu tun. Über das Feld ms_ticks aus dem DMV sys.dm_os_sys_info kann man den aktuellen Ticks-Stand ermitteln und darüber auf den eigentlichen Zeitpunkt rückrechnen.

Welche Type es (aktuell) gibt, kann mit einer einfachen Abfrage ermitteln:

 

 SELECT ring_buffer_type 
  ,COUNT(*) AS Occured 
 FROM master.sys.dm_os_ring_buffers 
 GROUP BY ring_buffer_type 
 ORDER BY ring_buffer_type 

 

Ergebnis (auf Laptop, der kurz vorher gestartet wurde):

 

ring_buffer_type

Occured

RING_BUFFER_MEMORY_BROKER

6

RING_BUFFER_RESOURCE_MONITOR

1

RING_BUFFER_SCHEDULER

824

RING_BUFFER_SCHEDULER_MONITOR

18

RING_BUFFER_XE_BUFFER_STATE

4

RING_BUFFER_XE_LOG

1

 

Na, das erste, was hier mein Interesse weckt, ist natürlich RING_BUFFER_RESOURCE_MONITOR. Wie schon erwähnt, sehen die Daten in „record“ wie XML aus und in den Datentypen kann man es auch konvertieren. Ein solcher „record“ für einen Resource_Monitor Eintrag sieht so aus:

 

 <Record id="0" type="RING_BUFFER_RESOURCE_MONITOR" time="1261574341"> 
  <ResourceMonitor> 
  <Notification>RESOURCE_MEMPHYSICAL_HIGH</Notification> 
  <IndicatorsProcess>0</IndicatorsProcess> 
  <IndicatorsSystem>1</IndicatorsSystem> 
  <NodeId>0</NodeId> 
  <Effect type="APPLY_LOWPM" state="EFFECT_OFF" reversed="0">0</Effect> 
  <Effect type="APPLY_HIGHPM" state="EFFECT_ON" reversed="0">0</Effect> 
  <Effect type="REVERT_HIGHPM" state="EFFECT_OFF" reversed="0">0</Effect> 
  </ResourceMonitor> 
  <MemoryNode id="0"> 
  <ReservedMemory>1671680</ReservedMemory> 
  <CommittedMemory>16636</CommittedMemory> 
  <SharedMemory>0</SharedMemory> 
  <AWEMemory>0</AWEMemory> 
  <SinglePagesMemory>2496</SinglePagesMemory> 
  <MultiplePagesMemory>10232</MultiplePagesMemory> 
  </MemoryNode> 
  <MemoryRecord> 
  <MemoryUtilization>100</MemoryUtilization> 
  <TotalPhysicalMemory>2086596</TotalPhysicalMemory> 
  <AvailablePhysicalMemory>832044</AvailablePhysicalMemory> 
  <TotalPageFile>4416176</TotalPageFile> 
  <AvailablePageFile>2442676</AvailablePageFile> 
  <TotalVirtualAddressSpace>2097024</TotalVirtualAddressSpace> 
  <AvailableVirtualAddressSpace>326988</AvailableVirtualAddressSpace> 
  <AvailableExtendedVirtualAddressSpace>0</AvailableExtendedVirtualAddressSpace> 
  </MemoryRecord> 
 </Record> 

 

Die Namen der Tags sind wie die aus den Speicher Performance Counters von Windows. XML lässt sich in SQL Server ab 2005 prima abfragen und das machen wir mal.

Auf einem Produktiv-System ausgeführt gibt es einige „RESOURCE_MEMPHYSICAL_HIGH“ Einträge; was für einen Server mit laufenden MS SQL Server aber auch nichts Ungewöhnliches ist.

Aber so kann man mit einfachen Mitteln sein System etwas monitoren und das auch noch rückwirkend.

 

 DECLARE @actualTS BIGINT 
 SET @actualTS = (SELECT ms_ticks FROM sys.dm_os_sys_info) 
 PRINT @actualTS 
   
 SELECT ORB.EventTime 
  ,ORB.Notif 
  ,ORB.AvailPhyMem 
  ,ROUND(CONVERT(float, 100 * AvailPhyMem) / TotalPhyMem, 3) AS PercentAvailable 
  ,ORB.MemUtil 
  ,ORB.ResvMem 
  ,ORB.CommMem 
  ,ORB.recordXml 
 FROM (SELECT DATEADD(s, EventTs, GETDATE()) AS EventTime 
  ,ORB.recordXml.value('(./Record/ResourceMonitor/Notification)[1]', 'varchar(50)') AS Notif 
  ,ORB.recordXml.value('(./Record/MemoryNode/ReservedMemory)[1]', 'int') AS ResvMem 
  ,ORB.recordXml.value('(./Record/MemoryNode/CommittedMemory)[1]', 'int') AS CommMem 
  ,ORB.recordXml.value('(./Record/MemoryRecord/MemoryUtilization)[1]', 'int') AS MemUtil 
  ,ORB.recordXml.value('(./Record/MemoryRecord/TotalPhysicalMemory)[1]', 'int') AS TotalPhyMem 
  ,ORB.recordXml.value('(./Record/MemoryRecord/AvailablePhysicalMemory)[1]', 'int') AS AvailPhyMem 
  ,recordXml 
  FROM (SELECT CONVERT(int, (ORB.timestamp - @actualTS) / 1000) AS EventTs 
  ,CONVERT(xml, record) AS RecordXml 
  FROM master.sys.dm_os_ring_buffers AS ORB 

            WHERE ORB.ring_buffer_type = N'RING_BUFFER_RESOURCE_MONITOR'

            ) AS ORB

      ) AS ORB

ORDER BY EventTime desc

Weiterlesen

BIDS Templates für Reporting Projekte anpassen

22. Februar 2011 , Geschrieben von Olaf Helper Veröffentlicht in #Reporting

Die Microsoft Business Intelligence Developer Studio (BIDS) Standard Vorlagen für Reporting Projekte sind nicht so ganz optimal, wie ich finde. Die Report Vorlage selbst ist im Letter Format mit Inches Angaben und die Textgrößen bei Tablix & Co, die vom Wizard erstellt werden, finde ich etwas sehr groß.

Hinzu kommt, das man im Sinne von Corporate Identity bestimmt Elemente wie Header-Logo oder eine Footer-Zeile mit Standard-Infos immer gleich platziert und die Mühe möchte man sich eigentlich sparen.

Diese Standard Vorlagen kann man aber einfach an seine Vorstellungen anpassen; vorher aber immer eine Sicherheitskopie der Dateien erstellen!

 

 

Report Projekte Vorlage

Die Vorlage für Report Projekte fürs BIDS 2008 findet man in:

%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\ReportProjects\ReportProject.rptproj

 

Die Standard Vorlage ist eher leer und viel zum Anpassen gibt es auch nicht, aber man kann schon mal die Ziel-Url vom verwendeten SSRS angeben; halt all die Konfigurationswerte, die man in den Projekt-Eigenschaften festlegt.

 

<?xml version="1.0"?>
<Project xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" 
         xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
  <DataSources />
  <Reports />
  <!-- Mein Anpassung -->
  <Configurations>
    <Configuration>
      <Name>Debug</Name>
      <Platform>Win32</Platform>
      <Options>
        <TargetServerURL>http://MeinServer/Reportserver_InstanzenName

        </TargetServerURL>
      </Options>
    </Configuration>
    <Configuration>
      <Name>Release</Name>
      <Platform>Win32</Platform>
      <Options>
        <TargetDataSourceFolder>Datenquellen</TargetDataSourceFolder>
      </Options>
    </Configuration>
  </Configurations>
  <!-- 
Ende Anpassung -->  
</Project>

 

 

Report Vorlage

Liegt in

%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\ProjectItems\ReportProject\Report.rdl

und ist eine ganz normale RDL Datei, die man entsprechend auch mit BIDS bzw. dem Report Builder 2.0 bearbeiten kann, also kein kryptische XML Bearbeitung.

Hier kann man also schon mal das gewünschte Seitenformat vorgeben, ein Logo einfügen, Seitenfuß festlegen und so weiter. Selbst Custom Code, Assemblies und Classes können hier schon eingefügt werden. Wenn man dann in seinem BIDS Projekt einen neuen Report hinzufügt, wird diese RDL Datei als Vorlage kopiert. Der Report Builder verwendet diese Vorlage nicht, ob und von wo der eine Vorlage zieht, ist mir nicht bekannt, im Internet war auch nichts zu dem Thema auffindbar.

 

 

Styles Vorlage

Die Vorlage für Styles liegt in

%ProgramFiles\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\Business Intelligence Wizards\Reports\Styles\de\StyleTemplates.xml

Hier ist also wieder XML Bearbeitung angesagt, da empfiehlt es sich, einen XML Editor zu verwenden.

Am besten ist es, man kopiert einen vorhandenen <StyleTemplate> Block, gibt diesen einen neuen, eindeutigen Namen und bearbeitet dann die Werte.

Die Struktur der Styles wird schnell ersichtlich, man kennt es bereits, wenn man schon per Wizard ein Tablix angelegt hat. Man kann je Verschachtelungstief 1 – 3+ (Group Level) die Formatierung definieren. Dabei kann man alle Properties angeben, die man auch aus BIDS kennt. Man muss nur beachten, das XML immer Case Senstive ist, man muss also Groß-/Kleinschreibung beachten.

Die Vorschaufunktion im Wizard funktioniert zwar nicht mit den selbst definierten Styles, aber das stellt nun wirklich kein Beinbruch dar.

 

Hier mal ein Beispiel, bei dem ich für den Report „Title“ das TextAlign=Center setze:

 

<StyleTemplate Name="Olaf">
  <Label>Olaf</Label>
  <Styles>
    <Style Name="Title">
      <FontFamily>Arial</FontFamily>
      <FontSize>20pt</FontSize>
      <Color>MidnightBlue</Color>
      <FontWeight>Bold</FontWeight>
      <TextAlign>Center</TextAlign>
    </Style>
    <...

 

Weiterlesen

SSAS Objekte per AMO verarbeiten und Verlauf per SessionTrace verfolgen

18. Februar 2011 , Geschrieben von Olaf Helper Veröffentlicht in #OLAP

Einen Microsoft Sql Server Analysis Services (SSAS) Cube und dessen Objekte lässt man im produktiven Betrieb natürlich zeitgesteuert per SSIS Package verarbeiten; da will man nicht wirklich bei „zusehen“.

Während der Entwicklungs- & Designphase eines Cube’s lässt man diesen aus BIDS heraus verarbeiten. Die Daten basieren dabei meist auf Views, die die eigentlichen Daten auf eine repräsentative als auch vertretbare Datenmenge beschränken; schließlich verarbeitet man öfter mal den Cube, um das Ergebnis zu kontrollieren und das soll ja nicht jedes Mal einen halben Arbeitstag in Anspruch nehmen. Der Processing Verlauf wird dabei in BIDS (und auch SSMS) in einem TreeView dargestellt und das bietet einem nicht gerade eine gute und informative Darstellung des Verlaufes.

Andererseits sind die Verlaufsinformationen (mir) wichtig, um von den Test- auf die Produktionsdaten hochrechnen zu können.

AMO bietet die Möglichkeit mit einem .NET Programm oder PowerShell programmatisch einzelne Objekte eines Cubes verarbeiten zu können. Über einen Trace könnte man alle Aktivitäten auf dem Analysis Server nach verfolgen und die der eigenen Session herausfiltern; nicht so ganz einfach. Es geht aber auch wesentlich einfacher, indem man das SessionTrace des AMO Server Objektes verwendet, über das man auch die Verarbeitung der Objekte durchführt. Man setzt eine Variable WithEvents, startet den Trace und kann dann alle Ereignisse Event-gesteuert empfangen. In TraceEventArgs erhält man alle Daten, so wie man sie auch aus dem SQL Profiler kennt.

Es gibt aber kleine Probleme mit ein paar Properties von TraceEventArgs, die könnten durch „Ungenauigkeit“ (alias Bug) in AMO verursacht werden und die gilt es zu umschiffen. Das betrifft zum Beispiel das Property IntegerData. Natürlich und verständlicherweise gibt es nicht bei jedem TraceEvent einen Wert für IntegerData, aber dann würde ich davon ausgehen, das entweder Nothing (C# null) oder -1 geliefert wird. Stattdessen erhält man den Laufzeitfehler

 

 System.ArgumentNullException: Der Wert darf nicht NULL sein. Parametername: String 
  bei System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) 
  bei System.Number.ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt) 
  bei Microsoft.AnalysisServices.TraceEventArgs.get_IntegerData() 

 

egal was man macht; eine einfach Prüfung auf IsNothing reicht bereits als Auslöser. Nun könnte man aufwendig auf alle EventClass / EventSubClass Kombinationen filtern, wo zugesichert ein Wert vorkommt. Ich mache es mir einfacher und deswegen kapsele ich die Abfrage des IntegerData, das bei manchen Events den Fortschritt bzw. die Anzahl verarbeiteter Datensätze enthält, in einer eigenen Funktion und fange den Fehler mit Try Catch ab. Betroffen sind von dem Phänomen die Properties CpuTime, Duration, IntegerData, ProgressTotal, Serverty.

 

Der Rest ist einfach, ich lasse die TraceEventArg-Daten in einer Console ausgeben, der VB.Net Code dazu sieht so aus:

 

 

Imports Microsoft.AnalysisServices
 
Module DimProcess
 
    Private WithEvents mSessionTrace As SessionTrace
 
    Sub Main()
        Dim server As New Server
        server.Connect("MeinServer\MeineInstanz")
 
        Dim database As Database = server.Databases("Adventure Works Cube")
        Dim dimension As Dimension = database.Dimensions("Dim Customer")
 
        mSessionTrace = server.SessionTrace
        mSessionTrace.Start()
 
        Console.WriteLine ("{0} Start of processing"Date.Now().ToString("T"))
        dimension.Process(ProcessType.ProcessFull)
 
        mSessionTrace.Stop
        mSessionTrace = Nothing
        Console.WriteLine ("{0} End of processing"Date.Now().ToString("T"))
        
        dimension.Dispose
        database.Dispose
        server.Disconnect
        server.Dispose
 
        Console.WriteLine ("Hit any key")
        Console.ReadKey
    End Sub
 
    Private Sub mSessionTrace_OnEvent(ByVal sender As ObjectByVal e As Microsoft.AnalysisServices.TraceEventArgs) _
        Handles mSessionTrace.OnEvent
        
        Select Case e.EventSubclass            
            ' Uninteressante EventSubClass:
            Case  TraceEventSubclass.Subscribe, TraceEventSubclass.SqlQuery, _
                  TraceEventSubclass.DiscoverXmlMetadata, TraceEventSubclass.ExecuteSql
            Case Else
                If Not String.IsNullOrEmpty(e.TextData) AndAlso not e.TextData.StartsWith("<"then
                    Console.WriteLine ("{0} {1} {2}"Date.Now().ToString("T"), GetIntegerdata(e), e.TextData)
                end if
        End Select
        
    End Sub
 
    Private Function GetIntegerdata(ByVal e As TraceEventArgsAs string
 
        Try
            Dim result As long = e.IntegerData
            Return result.ToString().PadLeft(6)
 
        Catch ex As Exception
            Return String.Empty.PadLeft(6)
        End Try
 
    End Function
 
End Module

 

Zugegeben, mit dem AdventureWork Demo gibt es nicht groß Daten zu verarbeiten, deswegen ist die Ausgabe auch nicht gerade spektakulär:

 

ProcessCubeObject.jpg

Weiterlesen

Übersicht über alle Berichte ... als SSRS Bericht

17. Februar 2011 , Geschrieben von Olaf Helper Veröffentlicht in #Reporting

Auf Websites sieht man häufiger Übersichtsseiten (Index) mit Links zu allen vorhandenen Seiten. Das ist sehr praktisch, man kann auf der Seite selbst nach Begriffen suchen und schnell auf Seiten navigieren, ohne sich lange durch diverse Menüs hangeln zu müssen.

 

Für eine umfangreiche Report Sammlung im Microsoft SQL Server Reporting Services wäre so was auch nicht verkehrt, also gehen wir das mal an.

 

Alle hierfür benötigten Daten sind in der ReportServer Datenbank in der Tabelle dbo.Catalog vorhanden.
Das Feld „
Type“ kennzeichnet die Objektart, hierbei sind 1 = Folder und 2 = Report für die Übersicht von Interesse, 4 = verlinkte Reports lassen wir mal aus. Über die „ItemId“ und „ParentId“ wird die hierarchische Struktur abgebildet. Hier bietet sich einem zur Abfrage natürlich eine rekursive CTE (Common Table Expression) an. Es wird zunächst das Root Element selektiert (ParentID IS NULL) und dann alle Children über einen JOIN mittels ItemId = ParentID auf CTE selbst.

 In der Übersicht soll dann auch eine Jump-to Action möglich sein, um zum Report springen zu können. Dafür kann man die Daten aus dem Feld „Path“ verwendet werden, es enthält die relative Pfadangabe des Elementes. Bei der Selektion wird der „Path“ bereits so modifiziert, um die Daten für einen HyperLink im Report verwenden zu können. Es muss dabei nur ein paar Kleinigkeiten beachtet werden, so müssen (gemäß Url Regel) die Slash’s durch %2f und Leerzeichen durch ein Pluszeichen ersetzt werden. Zudem müssen Berichte über „/Reports.aspx“ und Ordner entsprechend über „/Folder.aspx“ aufgerufen werden.  
 Schlussendlich, um es halbwegs gemäß der Hierarchie sortieren zu können, muss der Pfad des übergeordneten Elementes als primäre Sortierung verwendet werden; dank CTE kann das aber problemlos mitselektiert werden. 
   
 So sieht nun die Selektion der benötigten Daten als CTE aus: 
   
 -- Selektion aller vorhandenen Folder und Reports 
 -- über eine rekursive CTE  
   
 DECLARE @url varchar(100); 
 -- Url vom ReportManager; muss entsprechend angepasst werden 
 SET @url = 'http://MyServer/Reports_MyInstanz/Pages/§§§ReportOrFolder§§§.aspx?ItemPath='; 
   
 ;WITH RPT AS 
 ( -- Root Pfad 
  SELECT RT.ItemID 
  ,RT.Path 
  ,RT.ModifiedDate 
  ,0 AS [Level] 
  ,CAST(N'Stamm' AS nvarchar(425)) AS ReportName 
  ,CAST(N'Stamm' AS nvarchar(425)) AS ParentFolder 
  ,RT.Path AS ParentPath 
  ,REPLACE(REPLACE(RT.Path, '/', '%2f'),' ', '+') AS ReportLink 
   ,RT.Type AS ObjType 
  FROM dbo.Catalog AS RT 
  WHERE RT.ParentID IS NULL 
  AND RT.Type = 1 -- Nur den Root Folder 
  UNION ALL 
  SELECT CHILD.ItemID 
  ,CHILD.Path 
  ,CHILD.ModifiedDate 
  ,RPT.[Level] + 1 AS [Level] 
  ,CHILD.Name AS ReportName 
  ,CASE WHEN CHILD.Type = 1 THEN CHILD.Name ELSE RPT.ReportName END AS ParentFolder 
  ,CASE WHEN CHILD.Type = 1 THEN CHILD.Path ELSE RPT.ParentPath END AS ParentPath 
  ,REPLACE(REPLACE(CHILD.Path, '/', '%2f'),' ', '+') AS ReportLink 
   ,CHILD.Type AS ObjType  
  FROM dbo.Catalog AS CHILD 
  INNER JOIN  
  RPT ON CHILD.ParentID = RPT.ItemID 
  WHERE CHILD.Type = 2 -- Alle Reports und nur nicht-leere Folders 
  OR (CHILD.Type = 1 
  AND EXISTS (SELECT 1 FROM dbo.Catalog AS SUB 
  WHERE SUB.Type IN (1, 2) 
  AND SUB.ParentID = CHILD.ItemID)) 
 ) 
 SELECT RPT.Path 
  ,RPT.ReportName 
  ,CASE WHEN RPT.ObjType = 1 THEN REPLACE(@url, '§§§ReportOrFolder§§§', 'Folder') 
  ELSE REPLACE(@url, '§§§ReportOrFolder§§§', 'Report') 
  END 
  + RPT.ReportLink 
  + CASE WHEN RPT.ObjType = 1 THEN '&ViewMode=List' ELSE '' END 
  AS Link 
  ,RPT.ObjType 
  ,RPT.ModifiedDate 
  ,RPT.Level 
  ,RPT.ParentFolder 
  ,RPT.ParentPath 
 FROM RPT 
 ORDER BY RPT.ParentPath 
  ,RPT.Path 
  ,RPT.ReportName; 

 

 

Der Report für die Übersicht habe ich zunächst recht einfach als eine Tabelle mit 2 Zeilen, eine für Ordner und eine für Berichte, gestaltet. Die Zeilen werden dann je nach „ObjType“ sichtbar geschaltet.

Eine optische „Hierarchie-Tiefe“ der Elemente wird über die Padding - Left Eigenschaft der Textbox erreicht; hier wird über einen Ausdruck der Wert des CTE Feldes „Levels“ gesetzt und so das Feld nach rechts verrückt.

Als „Action“ wird dann „Gehe zu Url“ verwendet, das an die Daten der Selektion-Feldes „Link“ gebunden wird.

 

ReportLinkAction.jpg

 

Und das Ergebnis sieht dann so wie unten aus. Zugegeben, man kann das optisch noch attraktiver gestalten, da kann jeder seiner Kreativität freien Lauf lassen. Wenn die Reportnamen nicht zu lang und die Strukturebene nicht zu tief ist, könnte man den Bericht auch in 2 Spalten gliedern, um Platz zu sparen.

 

ReportOverview 

 

Der Report kann als „ReportOverview.rdl“ Datei fürs BIDS 2008 bzw. Report Builder 2.0 von meinem SkyDrive herunter geladen werden:

Weiterlesen

SQL Account "sa" als Nicht-SysAdmin

15. Februar 2011 , Geschrieben von Olaf Helper Veröffentlicht in #MSSQL

Man hört und sieht es immer noch häufiger:

Auch heutzutage, wo jedem das Thema Sicherheit präsent sein sollte, gibt es weiterhin viele, kleine oder größere Applikationen, die auf einen MS SQL Server zugreifen und das mit dem SQL Account "sa", welcher nicht zu selten über kein strenges oder noch schlimmer, über gar kein Passwort verfügt; mal abgesehen davon, dass es eh jeder kennt. Dabei ist dieser Standard SysAdmin Account eigentlich sowieso auch nur für die Administration gedacht gewesen; wie es halt immer so ist.

 

Natürlich sollte sowas von Grund auf geändert werden, also das die Anmeldung über den Windows Account des aktuellen Benutzers erfolgt oder zumindest über einen für die jeweilige Applikation dediziert angelegten SQL Account, der über ein strenges Passwort verfügt.

 

Durch die Masse an Applikationen ist eine solche Änderung natürlich zeitaufwendig; und was ist in der Zwischenzeit, bis alle Zugriffe geändert sind? Weiterhin dieses Sicherheitsrisiko eingehen mit der Gefahr, dass jemand "ungewünschte Änderungen" vornimmt und Daten oder gar ganze Objekte löscht?

 

Dafür gäbe es eine Möglichkeit zur Lösung. Seit dem Microsoft SQL Server Version 2005 gibt es die Möglichkeit SQL Account‘s mittels eines einfach ALTER LOGIN umzubenennen, einschließlich dem "sa" Account.

Die Idee ist also folgende:

-       "sa" umbenennen, z.B. in "saRealAdmin"

-       Strenges Passwort für "saRealAdmin" vergeben

-       Neuen SQL Account "sa" mit dem ursprünglichen Passwort anlegen und ihm die minimalst benötigten Rechte geben.

 

Versuchen wir es mal (Empfehlung: Vorher die [master] Datenbank kopieren!):

 

 USE [master] 
 GO 
   
 -- Original "sa" umbenennen 
 ALTER LOGIN [sa] WITH NAME = [saRealAdmin] 
 GO 
 -- Neuen "sa" mit altem Pwd anlegen 
 CREATE LOGIN [sa] WITH PASSWORD=N'altesPasswort' 
 GO 
   
 -- Kontrolle; beide da 
 SELECT sid, name 
 FROM [master].[sys].[syslogins] 
 WHERE name LIKE 'sa%' 
 GO 
   
 -- In AdventureWorks als DB User anlegen 
 -- und nur Lese-Rechte vergeben 
 USE [AdventureWorks] 
 GO 
 CREATE USER [sa] FOR LOGIN [sa] 
 GO 
 EXEC sp_addrolemember N'db_datawriter', N'sa' 
 GO 
   
 -- Test neuer "sa" auf Rechte 
 EXECUTE AS LOGIN = 'sa'; 
 GO 
 DROP TABLE Person.Address 
 GO 
   
 -- User Context wieder zurück schalten 
 REVERT; 

 

Der Test hat geklappt, die Anmeldung mit dem neuen „sa“ funktioniert, die Rechte sind eingeschränkt und auch die Verwendung des vermeintlich alten „saRealAdmin“ funktioniert einwandfrei und hat natürlich weiterhin Admin-Rechte.

 

Auf die Art kann man die Zwischenzeit überbrücken und trotzdem arbeiten Applikationen, die „sa“ verwenden weiterhin.

Nach Umstellung aller Apps sollte man sich überlegen, die Umbenennung rückgängig zu machen, sonst denkt der Admin womöglich nicht mehr daran, einen andern Sql Account zu verwenden.

Weiterlesen