madmax93
Goto Top

Alte SQL Datenbanken: Wann zuletzt genutzt?

Hallo zusammen,

wir haben ein alten WS 2012 R2 Server übernommen der als SQL-Server fungiert. Darin laufen einige Datenbanken, welche wir nur schwer bis gar keiner virtuellen Maschine bzw. Software zuordnen können. Vermutlich laufen schon einige dieser VMs bzw. Programme gar nicht mehr.

Deswegen würde ich gerne herausfinden, wann zuletzt Daten in diese Datenbanken geschrieben wurde. Das Erstelldatum lässt sich ja durch einfachen rechtsklick -> Eigenschaften feststellen.

Da meine Kenntnisse in SQL eher gering sind, wollte ich mal Nachfragen wie man das am besten anstellen kann oder gibt es zu so einem Fall ein Best Practice?

Hintergrund ist der, dass wir gerade ein neuen SQL-Server aufbauen und den alten ablösen wollen.

Besten Dank,
Max93

Content-ID: 91410572792

Url: https://administrator.de/forum/alte-sql-datenbanken-wann-zuletzt-genutzt-91410572792.html

Ausgedruckt am: 22.12.2024 um 07:12 Uhr

Crusher79
Crusher79 27.02.2024 aktualisiert um 10:18:50 Uhr
Goto Top
select max(LastAccess)
from (
    SELECT last_user_seek as LastAccess FROM sys.dm_db_index_usage_stats WHERE last_user_seek is not null and [database_id]= DB_ID ( N'lansweeperdb')  
    union
    SELECT last_user_lookup as LastAccess FROM sys.dm_db_index_usage_stats WHERE last_user_seek is not null and [database_id]= DB_ID ( N'lansweeperdb')  
    union
    SELECT last_user_seek as LastAccess FROM sys.dm_db_index_usage_stats WHERE last_user_seek is not null and [database_id]= DB_ID ( N'lansweeperdb')  
    union
    SELECT last_user_update as LastAccess FROM sys.dm_db_index_usage_stats WHERE last_user_seek is not null and [database_id]= DB_ID ( N'lansweeperdb')  
) UserAccess

https://stackoverflow.com/questions/711394/how-do-you-find-the-last-time ...

So z.B. Hier mal lansweeperdb als ID übergeben.

Aber es gibt auch automatische Prozesse die das verfälschen. Statt DB zu löschen,kannst du sie auch erstmal einfach Offline setzen und schauen wer schreit.
elix2k
elix2k 27.02.2024 um 10:25:32 Uhr
Goto Top
Ich schaue auch immer nach dem Änderungsdatum der Datenbankdateien, hatte auch mal einige Leichen die ich dann erstmal offline geschaltet habe.
Crusher79
Crusher79 27.02.2024 um 10:27:20 Uhr
Goto Top
https://www.sqlshack.com/how-to-discover-and-handle-orphaned-database-us ...

HIer nochomal was zu den Waisenkindern. Auch eine Methode.
MadMax93
MadMax93 27.02.2024 um 13:09:11 Uhr
Goto Top
Hey zusammen,

vielen Dank für die schnelle Rückmeldung. Durch die Abfragen habe ich einige Daten rausbekommen, die aber leider nur den Neustart des Servers wiederspiegeln. Fast alle Datenbanken (bis auf ich 4 Stück) haben das 04.09.2023 als Datum. Das ist das Datum des letzten Neustart des Servers.

Es zeigt auch nur die letzten User an, aber nicht ob da irgendwelche Daten reingespeichert wurden.
Gibt es hierzu auch noch einige Abfragen die ich Anwenden könnte?
Übersicht aller alten datenbanken. last login
Crusher79
Crusher79 27.02.2024 aktualisiert um 14:18:10 Uhr
Goto Top
SELECT last_execution_time, text
FROM sys.dm_exec_query_stats stats
CROSS APPLY sys.dm_exec_sql_text(stats.sql_handle) 
ORDER BY last_execution_time

Hab ich mir selber geklaut face-big-smile

https://stackoverflow.com/questions/123781/logging-all-queries-on-a-sql- ...

Geht auch für den normalen SQL.

Alles ist vlt. nun drüber. Du musst es noch filtern.
Crusher79
Crusher79 27.02.2024 um 14:23:39 Uhr
Goto Top
SELECT OBJECT_NAME(OBJECT_ID) AS DatabaseName, last_user_update,*
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID( 'lansweeperdb')  
AND OBJECT_ID=OBJECT_ID('htblautomaticclosetickettypes');)  

https://stackoverflow.com/questions/6344413/sql-server-row-date-last-mod ...

OBJECT_ID ist die Tabelle. Ohne die im Where-Partr zeigt es alles für die DB an.
MadMax93
MadMax93 27.02.2024 um 15:34:03 Uhr
Goto Top
Puh, vielen Dank erst mal. Ich krieg hier jetzt die Spalten wie "Last UserSeek, UserScan und UserLookup" angezeigt. Aber welches Datum zeigt dann jetzt, wann die Datenbank zuletzt genutzt wurde? Sorry für meine bescheidenen Fragen, aber bin nicht so der SQL Experte.
ukulele-7
ukulele-7 28.02.2024 um 15:27:42 Uhr
Goto Top
Ist das SQL Express oder vollwertiges SQL?

Du könntest auch eine Audit Log auf eine oder mehrere Tabellen aktivieren aber das ist nicht so ganz easy wie ich erst dachte face-wink Habe das derzeit auf einer Tabelle laufen um Lesevorgänge zu loggen.
MadMax93
MadMax93 29.02.2024 um 14:18:31 Uhr
Goto Top
Habe gerade mal eine Select @@version Abfrage gemacht und es ist ein SQL Server 2012 Standard Edition ;)

Puh also ich dachte man könnte einfach ein Abfragebefehl reinhauen, der mir aufzeigt, wann zuletzt was in die Tabelle reingeschrieben wurde oder wann sie zuletzt aktiv genutzt wurde hm.
ukulele-7
ukulele-7 29.02.2024 aktualisiert um 15:04:13 Uhr
Goto Top
Also ich wäre schon auf die Lösung von @Crusher79 nicht gekommen. Normalerweise tut SQL genau das Nötigste, um eine Aufgabe möglichst schnell und effizient zu erfüllen. Und dazu gehören halt nicht Statistiken zu führen. Natürlich kann man mit SQL Statistiken führen (Lesevorgänge) bzw. z.B. mit Triggern Logs schreiben, das ist aber nicht per Default so, das würde Performance kosten.

Für Lesevorgänge kannst du ein Audit aktivieren. Damit kannst du dann zukünftige Vorgänge beobachten aber natürlich nicht mehr die Vergangenheit. Das mit den Indexen habe ich nicht getestet, scheint aber einen Blick in die Vergangenheit zu ermöglichen. Alternativ geht halt Abschalten und Abwarten, wer sich meldet, das ist einfach face-smile

Mit dem Audit habe ich selbst ein ganz wenig gebastelt. Habe das auf einer Tabelle aktiviert, ich glaube über die GUI vom SSMS, und frage das mit
SELECT * FROM fn_get_audit_file('E:\SQL_Audit\...\*.sqlaudit',DEFAULT,DEFAULT)  
ab.
Crusher79
Crusher79 29.02.2024 aktualisiert um 17:55:48 Uhr
Goto Top
Ok danke für die Blumen @ukulele-7 Kam aber überwiegend aus dem stackoverflow Foren face-wink

Ich selber hab für ein "Abzeichnen" Projekt mal TRIGGER gesetzt. Jeder Manipulation an den Daten hinterlässt spuren. Man kann für jeden aktualisierten Wert auch den alten wieder heran holen. Dafür gibt es spezielle Tabellen: del.x

Delete (del) zeigt den überschriebenen Wert an. Wäre aber auch in deinen Fall etwas drüber. Ein normaler Trigger reicht vollkommen aus. Ich weiß nur nicht, ob das mit der Express so gut geht.

Hab gerade nicht so viel Zeit. Am wichtigsten ist der TRIGGER der nach UPDATE der Tabelle was tun soll.

del und ins liefern die überschriebenen oder neu hinzugefügenen Werte der Felder (DELETE / INSERT).

Es sieht wilder aus, als es ist. Man muss auch nicht alle Spalte überwachen. Je nach Tabelle sagt schon der Inhalt, was die Leute so ändern könnten. Dafür müsste man natürlich deine Tabelle sehen.

Was geschieht hier? [dbo].[e_bericht] ist eine Tabelle mit Dokumenten und Handzeichen, sowie Datum-Feldern.

INS und DEL zur Zeit des auslösens des Triggers geben die Werte wieder. Und zwar für die gelöschten (geändert) und neu hinzugefügten.

Ist quasi ein komplett selbsgebauter Log.

Um es lesbar zu machen knall ich einfach NEW und OLD als Wort rein. Kann auch 0 oder 1 sein. Alt und Neu....

Das muss man abe rnicht in deinen Fall. Hier ging es darum die Zeiten zu erfassen und später zu vergleichen. Die stehen quasi untereinander und konnte mit LAG Funktion verglichen werten.

ALT: 15 Uhr
NEU: 17 Uhr

2 Stunden hat also keiner was gemacht und dann erst da irgendwas geändert. In meinen Fall waren es mehrere Tage.

LAG Funktion siehst du hier nicht! War nur ein Ausflug, was man so mache kann.

Ein selbstegebauter Trigger ist schlanker. Du kansnt ihn auch nur auf Spalten los lassen, die definitiv genutzt werden würden, wenn jemand was einträgt.


CREATE TRIGGER TriggerNameON DB_NameAFTER UPDATE AS

DEL und INS sind nur notwendig, wenn man die alten Werte vergleichen will oder sie als Referenz hinzuschreibt in eine neue Zeile.

Im einfaschsten Fall kannst du auch nur 2x Spalten nehmen.

Datum | Tabelle

Ändert wer was, soll nur Datetime hinzugefügt werden + Tabellename. Wenn man 20 kontrolliert will man wissen, wie das Änderungsdatum war.

Da wir sagen die DBs sind eh tot, sollt so ein TRIGGER nix kosten. Er greift nur beim Event AFTER UPDATE !!!


CREATE TRIGGER updE_Bericht ON [dbo].[e_bericht]
AFTER UPDATE AS  
    IF ( 1+2=3
	--(SUBSTRING(COLUMNS_UPDATED(), 6, 1) & 31 > 0)   
        )   

      BEGIN  
-- Audit OLD record.  

      INSERT INTO MyDataBase.dbo.auditE_BerichtHz 
         (audit_log_type,  audit_pat_num, 
		 audit_kurz_sd,
         audit_verlauf1,  
         audit_verlauf2,  
         audit_verlauf3,
		 audit_verlauf4,      
         audit_verlauf5,
		 audit_verlauf6)  
         SELECT 'OLD',     
		    del.pat_num,
			del.kurz_sd,
            del.verlauf1,
            del.verlauf2,  
            del.verlauf3,  
            del.verlauf4,
			del.verlauf5,
			del.verlauf6
         FROM deleted del
		 INNER JOIN inserted ins ON del.pat_num=ins.pat_num 
		 WHERE ins.verlauf1<>del.verlauf1 OR
		 ins.verlauf2<>del.verlauf2 OR
		 ins.verlauf3<>del.verlauf3 OR
		 ins.verlauf4<>del.verlauf4 OR
		 ins.verlauf5<>del.verlauf5 OR
		 ins.verlauf6<>del.verlauf6 OR
		 ins.kurz_sd<>del.kurz_sd;  

-- Audit NEW record.  
      INSERT INTO MyDataBase.dbo.auditE_BerichtHz 
         (audit_log_type,audit_pat_num,  
		 audit_kurz_sd, 
         audit_verlauf1,  
         audit_verlauf2,  
         audit_verlauf3,
		 audit_verlauf4,      
         audit_verlauf5,
		 audit_verlauf6)  
         SELECT 'NEW',     
		    ins.pat_num,
			ins.kurz_sd,
            ins.verlauf1,  
            ins.verlauf2,  
            ins.verlauf3,  
            ins.verlauf4,
			ins.verlauf5,
			ins.verlauf6
         FROM deleted del
		 INNER JOIN inserted ins ON del.pat_num=ins.pat_num 
		 WHERE ins.verlauf1<>del.verlauf1 OR
		 ins.verlauf2<>del.verlauf2 OR
		 ins.verlauf3<>del.verlauf3 OR
		 ins.verlauf4<>del.verlauf4 OR
		 ins.verlauf5<>del.verlauf5 OR
		 ins.verlauf6<>del.verlauf6 OR
		 ins.kurz_sd<>del.kurz_sd;  

   END;  
GO  
ukulele-7
ukulele-7 01.03.2024 um 10:30:30 Uhr
Goto Top
Log Trigger sind ne feine Sache und ziemlich individuell. Allerdings können Trigger nicht bei Lesezugriffen feuern und natürlich sind sie immer nur auf die zugehörige Tabelle beschränkt. Man muss also schon ziemlich genau eine Vorstellung davon haben wo man nach Nutzeraktivität sucht.
Crusher79
Crusher79 01.03.2024 um 14:10:23 Uhr
Goto Top
Stimmt. ka was TS für Tabellen hat.

Wennm man CRM ERP Systeme kennt, hat man ja ein gewisses Gefühl .

Offline nehmen der DB wäre durchaus ok. Wenn jemand schreit, kann man es schnell wieder Online nehmen.

Mitunter werden ja auch Systeme für ODBC Excel Auswertungen angezapft. Ohne den Betrieb, Software etc. zu kennnen echt schwer.

Wenn der Server Offline wäre, sind die DBs ja auch nicht da. Ich finde eine alte DB Offline zu setzen immer noch dann legitim. Kann nicht viel passieren, wenn abhängige Programme sauber gestaltet worden sind. Nich wenn A ncht erreichbar, soll B komplett gelöscht werden. Solche Abhängigkeiten wären fatal. Aber dafür kennen wir den Betrieb halt nicht.

Aus dem Bauch heraus sehe ich da kein Problem. .