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
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
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
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
13 Kommentare
Neuester Kommentar
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.
https://www.sqlshack.com/how-to-discover-and-handle-orphaned-database-us ...
HIer nochomal was zu den Waisenkindern. Auch eine Methode.
HIer nochomal was zu den Waisenkindern. Auch eine Methode.
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
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.
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.
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
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
ab.
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
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)
Ok danke für die Blumen @ukulele-7 Kam aber überwiegend aus dem stackoverflow Foren
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 !!!
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
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. .
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. .