कैसे पता करें कि किसने कुछ डेटा SQL सर्वर को डिलीट किया है


29

मेरे बॉस ने कल एक ग्राहक से एक प्रश्न पूछा था कि वे कैसे पता लगा सकते हैं कि किसने अपने SQL सर्वर डेटाबेस में कुछ डेटा को डिलीट किया है (यह अगर यह मायने रखता है तो एक्सप्रेस संस्करण है)।

मैंने सोचा कि यह लेन-देन लॉग से पाया जा सकता है (बशर्ते इसे काट नहीं दिया गया था) - क्या यह सही है? और यदि हां, तो आप वास्तव में इस जानकारी को खोजने के बारे में कैसे जानते हैं?

जवाबों:


35

मैंने एक्सप्रेस पर fn_dblog की कोशिश नहीं की है, लेकिन अगर यह उपलब्ध है तो निम्नलिखित आपको ऑपरेशन हटा देगा:

SELECT 
    * 
FROM 
    fn_dblog(NULL, NULL) 
WHERE 
    Operation = 'LOP_DELETE_ROWS'

लेन-देन के लिए लेनदेन आईडी लें जिसमें आप रुचि रखते हैं और उस सिड की पहचान करें जिसने इसके साथ लेनदेन शुरू किया है:

SELECT
    [Transaction SID]
FROM
    fn_dblog(NULL, NULL)
WHERE
    [Transaction ID] = @TranID
AND
    [Operation] = 'LOP_BEGIN_XACT'

फिर SID से उपयोगकर्ता की पहचान करें:

SELECT
    *
FROM 
    sysusers
WHERE
    [sid] = @SID

संपादित करें: निर्दिष्ट तालिका पर हटाए जाने के लिए सभी को एक साथ लाना:

DECLARE @TableName sysname
SET @TableName = 'dbo.Table_1'

SELECT
    u.[name] AS UserName
    , l.[Begin Time] AS TransactionStartTime
FROM
    fn_dblog(NULL, NULL) l
INNER JOIN
    (
    SELECT
        [Transaction ID]
    FROM 
        fn_dblog(NULL, NULL) 
    WHERE
        AllocUnitName LIKE @TableName + '%'
    AND
        Operation = 'LOP_DELETE_ROWS'
    ) deletes
ON  deletes.[Transaction ID] = l.[Transaction ID]
INNER JOIN
    sysusers u
ON  u.[sid] = l.[Transaction SID]

यह वास्तव में एसक्यूएल एक्सप्रेस के साथ काम करता है लेकिन मेरे सिस्टम पर यह केवल लेनदेन को दर्शाता है जो आज हुआ। मुझे नहीं लगा कि एसक्यूएल एक्सप्रेस में लेन-देन लॉग ट्रंकेशन आउट ऑफ़ बॉक्स था?
मैट विल्को

5
यदि आपका डेटाबेस सरल पुनर्प्राप्ति मॉडल में है, तो आप लॉग में चारों ओर लंबे समय तक निष्क्रिय लेन-देन के बारे में कोई धारणा नहीं बना सकते हैं।
हारून बर्ट्रेंड

3
लेन-देन लॉग वैकल्पिक के बजाय मौलिक है। डेटाबेस (सरल या पूर्ण) के लिए पुनर्प्राप्ति मॉडल क्या है और बैकअप कैसे कॉन्फ़िगर किए गए हैं (केवल पूर्ण या लॉग बैकअप + पूर्ण)?
मार्क स्टोरी-स्मिथ

मैंने अपने उत्तर के लिए इसे यहाँ चुरा लिया था , हालांकि स्व-जुड़ने से बचने के लिए थोड़ा सा रिफ्लेक्ट किया fn_dblog। एक नकारात्मक पक्ष यह है कि यह USERNAME()अधिक उपयोगी लॉगिन नाम के बजाय डेटाबेस को लौटाता है ।
मार्टिन स्मिथ

3

यदि डेटाबेस पूर्ण पुनर्प्राप्ति मोड में है या यदि आपके पास लेन-देन लॉग बैकअप है, तो आप तृतीय पक्ष लॉग रीडर का उपयोग करके इन्हें पढ़ने का प्रयास कर सकते हैं।

आप ApexSQL लॉग (प्रीमियम पर एक नि: शुल्क परीक्षण) या SQL लॉग रेस्क्यू (केवल लेकिन 2000 sql) आज़मा सकते हैं ।


3

वे कैसे पता लगा सकते हैं कि किसने अपने SQL सर्वर डेटाबेस में कुछ डेटा डिलीट किया है

यद्यपि यह उत्तर दिया गया है, यह जोड़ना चाहता था कि SQL सर्वर में एक डिफ़ॉल्ट ट्रेस सक्षम है और इसका उपयोग यह पता लगाने के लिए किया जा सकता है कि वस्तुओं को किसने गिराया / परिवर्तित किया।

वस्तु घटनाएँ

ऑब्जेक्ट ईवेंट में शामिल हैं: ऑब्जेक्ट परिवर्तित, ऑब्जेक्ट निर्मित और ऑब्जेक्ट हटाए गए

नोट: डिफ़ॉल्ट रूप से SQL सर्वर में 5 ट्रेस फ़ाइलें, 20 एमबी प्रत्येक हैं और इसे बदलने का कोई ज्ञात समर्थित तरीका नहीं है। यदि आपके पास एक व्यस्त प्रणाली है, तो ट्रेस फ़ाइलें बहुत तेज़ी से (यहां तक ​​कि घंटों के भीतर) भी लुढ़क सकती हैं और आप कुछ परिवर्तनों को नहीं पकड़ सकते हैं।

उत्कृष्ट उदाहरण पाया जा सकता है: SQL सर्वर में डिफ़ॉल्ट ट्रेस - प्रदर्शन और सुरक्षा ऑडिटिंग की शक्ति


1

आप लॉग बैकअप फ़ाइलों को क्वेरी करने के लिए इस प्रक्रिया को आज़मा सकते हैं और पा सकते हैं जिसमें लॉग बैकअप फ़ाइल (s) तालिका के स्तंभ का एक विशिष्ट मूल्य अभी भी / अंतिम मौजूद था।

उपयोगकर्ता को खोजने के लिए, यह जानने के बाद कि लॉग बैकअप का अंतिम मान क्या है, आप उस लॉग बैकअप तक एक डेटाबेस को पुनर्स्थापित कर सकते हैं और फिर मार्क स्टोरी-स्मिथ के उत्तर का पालन कर सकते हैं ।

कुछ पूर्वापेक्षाएँ

  • जानिए किन मूल्यों से हटाए गए कॉलम
  • पूर्ण पुनर्प्राप्ति मॉडल के अंतर्गत हैं और लॉग बैकअप ले रहे हैं
  • आपके पास अपने लॉग बैकअप में दिनांक या पहचानकर्ता होते हैं, जैसे कि ओला हैलेनग्रेन के समाधान का उपयोग करते समय

अस्वीकरण

यह समाधान जलरोधी से बहुत दूर है, और बहुत अधिक काम करने की आवश्यकता है।

यह बड़े पैमाने पर वातावरण, या यहां तक ​​कि कुछ छोटे परीक्षणों के अलावा किसी भी वातावरण पर परीक्षण नहीं किया गया है। वर्तमान रन SQL Server 2017 पर था।

आप मुहम्मद इमरान से नीचे की प्रक्रिया का उपयोग कर सकते हैं जो मैंने लाइव डेटाबेस के लॉग की सामग्री के बजाय लॉग बैकअप की सामग्री के साथ काम करने के लिए संशोधित किया था ।

इस तरह आप तकनीकी रूप से पुनर्स्थापना नहीं कर रहे हैं, बल्कि लॉग सामग्री को अस्थायी तालिका में डंप कर रहे हैं। यह शायद अभी भी धीमा होगा, और बग और मुद्दों के लिए बहुत खुला है। लेकिन यह काम कर सकता है, सिद्धांत ™ में।

संग्रहित प्रक्रिया fn_dump_dblogलॉग फ़ाइलों को पढ़ने के लिए अनिर्धारित फ़ंक्शन का उपयोग करती है ।


परीक्षण वातावरण

इस डेटाबेस पर विचार करें, जहां हम कुछ पंक्तियों को सम्मिलित करते हैं, 2 लॉग बैकअप लेते हैं, और तीसरे लॉग बैकअप पर हम सभी पंक्तियों को हटाते हैं।

CREATE DATABASE WrongDeletesDatabase
GO
USE WrongDeletesDatabase
GO
BACKUP DATABASE WrongDeletesDatabase TO DISK ='c:\temp\Full.bak'

ALTER DATABASE WrongDeletesDatabase SET RECOVERY FULL
GO

CREATE TABLE dbo.WrongDeletes(ID INT, val varchar(255))

INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (1,'value1')
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log1.trn'
GO
INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (2,'value2')
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log2.trn'
GO
DELETE FROM dbo.WrongDeletes
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log3.trn'
GO
INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (3,'value3')
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log4.trn'
GO

प्रक्रिया

आप यहां संग्रहीत प्रक्रिया को ढूंढ और डाउनलोड कर सकते हैं ।

मैं इसे यहां नहीं जोड़ सका क्योंकि यह चरित्र की सीमा से बड़ा है, और इस उत्तर को इससे भी कम स्पष्ट कर देगा।

इसके अलावा, आपको प्रक्रिया को चलाने में सक्षम होना चाहिए।

प्रक्रिया चल रही है

इसका एक उदाहरण, जब मैं अपनी सभी लॉग फाइल ( 4) को संग्रहीत कार्यविधि में जोड़ता हूं और मान 1 की तलाश में प्रक्रिया चलाता हूं

EXEC dbo.Recover_Deleted_Data_Proc  @Database_Name= 'WrongDeletesDatabase',
                                    @SchemaName_n_TableName= 'dbo.WrongDeletes', 
                                    @SearchString = 'value1', 
                                    @SearchColumn = 'val',
                                    @LogBackupFolder ='C:\temp\Logs\'

यह मुझे मिलता है:

ID  val LogFileName
1   value1  c:\temp\Logs\log3.trn
1   value1  c:\temp\Logs\log1.trn

जहां हम पा सकते हैं कि पिछली बार ऑपरेशन कब value1हुआ था, तो डिलीट करें log3.trn

कुछ और परीक्षण डेटा, विभिन्न स्तंभों के साथ एक तालिका जोड़ना

CREATE TABLE dbo.WrongDeletes2(Wow varchar(255), Anotherval varchar(255),Val3 int)

INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (1,'value1')
INSERT INTO dbo.WrongDeletes2(wOw,Anotherval,Val3)
VALUES ('b','value1',1)
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log1_1.trn'
GO
INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (2,'value2')
INSERT INTO dbo.WrongDeletes2(wOw,Anotherval,Val3)
VALUES ('c','value2',2)
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log2_1.trn'
GO
DELETE FROM dbo.WrongDeletes
DELETE FROM dbo.WrongDeletes2
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log3_1.trn'
GO
INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (3,'value3')
INSERT INTO dbo.WrongDeletes2(wOw,Anotherval,Val3)
VALUES ('d','value3',3)
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log4_1.trn'
GO

लॉग फ़ाइल नाम बदलना और प्रक्रिया को फिर से निष्पादित करना

EXEC dbo.Recover_Deleted_Data_Proc  @Database_Name= 'WrongDeletesDatabase',
                                    @SchemaName_n_TableName= 'dbo.WrongDeletes', 
                                    @SearchString = 'value1', 
                                    @SearchColumn = 'val',
                                    @LogBackupFolder ='C:\temp\Logs\'

परिणाम

ID  val LogFileName
1   value1  c:\temp\Logs\log1_1.trn
1   value1  c:\temp\Logs\log3_1.trn
1   value1  c:\temp\Logs\log3_1.trn

2के val3कॉलम में पूर्णांक ( ) की खोज करते हुए एक नया रनdbo.WrongDeletes2

EXEC dbo.Recover_Deleted_Data_Proc  @Database_Name= 'WrongDeletesDatabase',
                                    @SchemaName_n_TableName= 'dbo.WrongDeletes2', 
                                    @SearchString = '2', 
                                    @SearchColumn = 'Val3',
                                    @LogBackupFolder ='C:\temp\Logs\'

परिणाम

Anotherval  Val3    Wow LogFileName
value2  2   c   c:\temp\Logs\log2.trn
value2  2   c   c:\temp\Logs\log3.trn

मार्क स्टोरी स्मिथ के जवाब को लागू करना

अब हम जानते हैं कि यह तीसरी लॉग फ़ाइल में हुआ, चलो उस बिंदु तक पुनर्स्थापित करें:

USE master
GO
ALTER DATABASE WrongDeletesDatabase SET OFFLINE WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE WrongDeletesDatabase SET ONLINE 
GO
RESTORE DATABASE WrongDeletesDatabase FROM DISK = 'c:\temp\Logs\Full.bak' WITH NORECOVERY,REPLACE
RESTORE LOG WrongDeletesDatabase FROM DISK = 'c:\temp\Logs\log1.trn' WITH NORECOVERY
RESTORE LOG WrongDeletesDatabase FROM DISK = 'c:\temp\Logs\log2.trn' WITH NORECOVERY
RESTORE LOG WrongDeletesDatabase FROM DISK = 'c:\temp\Logs\log3.trn' WITH RECOVERY
GO
USE WrongDeletesDatabase
GO

उनके जवाब में अंतिम क्वेरी चल रही है

SELECT
    u.[name] AS UserName
    , l.[Begin Time] AS TransactionStartTime
FROM
    fn_dblog(NULL, NULL) l
INNER JOIN
    (
    SELECT
        [Transaction ID]
    FROM 
        fn_dblog(NULL, NULL) 
    WHERE
        AllocUnitName LIKE @TableName + '%'
    AND
        Operation = 'LOP_DELETE_ROWS'
    ) deletes
ON  deletes.[Transaction ID] = l.[Transaction ID]
INNER JOIN
    sysusers u
ON  u.[sid] = l.[Transaction SID]

मेरे लिए परिणाम (sysadmin)

UserName    TransactionStartTime
dbo 2019/08/09 17:14:10:450
dbo 2019/08/09 17:14:10:450
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.