数据库数据修复
来源:互联网 发布:藏头诗 魂归大海知乎 编辑:程序博客网 时间:2024/06/05 17:00
简要记录背景:
1. 数据库由于硬盘问题完整性被破坏了,使用dbcc checkdb完全没有效果
2. 经检查发现,有两张使用最频繁的表无法进行任何操作,其他表正常
3. 通过某数据库修复工具,可以查看到那两张坏掉的表中的数据【估计还是不全】,但由于没有授权,只能查看,数据导不出来
在此基础上,我们按如下办法来尽可能对数据库进行修复,修复办法如下:
1. 想办法重建立一个新库,除了两张坏掉的表,其他表以复制的形式重建
由于坏的表无法删除,导致整个库都无法使用,我们只能将好的数据进行转移,重建数据库。
我们在将表结构建立好后,使用如下脚本,生成了库中所有需要导入的表的记录
use ChargeDECLARE @TableName varchar(255);DECLARE @ColumnName varchar(255);DECLARE @ColumnNames varchar(2550);declare @currentDbName varchar(255)declare @sourceDbName varchar(255)set @currentDbName = 'newdb'set @sourceDbName = 'brokendb'DECLARE Table_Cursor CURSOR FOR SELECT [name] FROM sysobjects WHERE xtype='U'; OPEN Table_Cursor;FETCH NEXT FROM Table_Cursor INTO @TableName; WHILE(@@FETCH_STATUS=0) BEGIN if(@TableName <> 'Tbl_Customer' and @TableName <> 'Tbl_Company' )begin print '/*---------------------------------------------------------------' print @TableName print '---------------------------------------------------------------*/' begin set @ColumnNames = '' DECLARE Column_Cursor CURSOR FOR select name from syscolumns where id=object_id(@TableName)OPEN Column_Cursor;FETCH NEXT FROM Column_Cursor INTO @ColumnName;WHILE(@@FETCH_STATUS=0)beginset @ColumnNames = @ColumnNames + '[' + @ColumnName + ']' + ','FETCH NEXT FROM Column_Cursor INTO @ColumnName;end CLOSE Column_Cursor DEALLOCATE Column_Cursor; end set @ColumnNames = left(@ColumnNames, len(@ColumnNames) -1)print 'use ' + @currentDbNameprint 'begin try'print 'Set IDENTITY_INSERT ' + @TableName + ' ON'print 'truncate table ' + @TableNameprint 'INSERT INTO ['+ @currentDbName +'].[dbo].[' + @TableName + '](' + @ColumnNames + ') select ' + @ColumnNames + ' from [' + @sourceDbName + '].[dbo].[' + @TableName + ']'print 'end try'print 'begin catch'print 'print ''' + @TableName + ' run error'''print 'end catch'print 'begin try'print 'Set IDENTITY_INSERT ' + @TableName + ' OFF'print 'end try'print 'begin catch'print 'end catch'end FETCH NEXT FROM Table_Cursor INTO @TableName; END CLOSE Table_Cursor; DEALLOCATE Table_Cursor; GO
2. 执行上述脚本,生成了可以导入整个库中想要的表的数据,自动生成的脚本如下:
/*---------------------------------------------------------------Tbl_Order---------------------------------------------------------------*/use newdbbegin trySet IDENTITY_INSERT Tbl_Order ONtruncate table Tbl_OrderINSERT INTO [newdb].[dbo].[Tbl_Order]([OrderId],[EuId],[CardId]) select [OrderId],[EuId],[CardId] from [brokendb].[dbo].[Tbl_Order]end trybegin catchprint 'Tbl_Order run error'end catchbegin trySet IDENTITY_INSERT Tbl_Order OFFend trybegin catchend catch/*---------------------------------------------------------------Tbl_CancelCharge---------------------------------------------------------------*/use newdbbegin trySet IDENTITY_INSERT Tbl_CancelCharge ONtruncate table Tbl_CancelChargeINSERT INTO [newdb].[dbo].[Tbl_CancelCharge]([CancelId],[EuId],[ECharacterID],[Type],[Num],[CreateDate]) select [CancelId],[EuId],[ECharacterID],[Type],[Num],[CreateDate] from [brokendb].[dbo].[Tbl_CancelCharge]end trybegin catchprint 'Tbl_CancelCharge run error'end catchbegin trySet IDENTITY_INSERT Tbl_CancelCharge OFFend trybegin catchend catch
3. 通过SPY++监视发现,原来第三方的数据库修复软件是通过系统的 SysListView32 来显示的数据库数据,这样我们就可以利用读取外部进程控件数据的办法,将其能读取的数据读取出来,获取其窗口句柄及读取行列数据的代码分别如下:
/************************************************************************//* *//************************************************************************/HWND CWindowFind::GetChildWindow(HWND hwnd,int iIndex){HWND hwndChind = NULL;CString strTemp = "";int i = 1;hwndChind = GetWindow(hwnd,GW_CHILD);CWnd *pWnd = CWnd::FromHandle(hwndChind);while (pWnd){hwndChind = pWnd->GetSafeHwnd();if (i == iIndex){return hwndChind;}pWnd = pWnd->GetNextWindow(GW_HWNDNEXT);i++;}return hwndChind;}接下来找到列表句柄及获取行数:
HWND hwndParent = ::FindWindow(NULL, "MSSQL数据库修复大师 专业版");hwndParent = gl_find.GetChildWindow(hwndParent, 1);hwndParent = gl_find.GetChildWindow(hwndParent, 2);HWND hwnd = gl_find.GetChildWindow(hwndParent, 1);int nTotalCount = (int) ::SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0L);
获取某行列的字符串:
CString CCListCtrlExportDlg::GetListItemText(HWND hwnd,int iItem,int iSubItem){LVITEM lvitem, *plvitem;char ItemBuf[512],*pItem;DWORD PID;HANDLE hProcess;CString strRet = "";GetWindowThreadProcessId(hwnd, &PID);hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,PID);if (!hProcess){return "";}plvitem=(LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);pItem=(char*)VirtualAllocEx(hProcess, NULL, 512, MEM_COMMIT, PAGE_READWRITE);if ((!plvitem)||(!pItem)){CloseHandle(hProcess);return "";}else {lvitem.cchTextMax=512;lvitem.iSubItem=iSubItem;lvitem.pszText=pItem;WriteProcessMemory(hProcess, plvitem, &lvitem, sizeof(LVITEM), NULL);::SendMessage(hwnd,LVM_GETITEMTEXT, (WPARAM)iItem,(LPARAM)plvitem);ReadProcessMemory(hProcess, pItem, ItemBuf, 512, NULL);strRet.Format("%s",ItemBuf);}VirtualFreeEx(hProcess, plvitem, 0, MEM_RELEASE);VirtualFreeEx(hProcess, pItem, 0, MEM_RELEASE);CloseHandle(hProcess);return strRet;}这样每一行每一列的值已经都可以拿到了,接下来只需要将读取到的数据组合成相应的SQL脚本,再到查询分析器中执行,即可将丢失的数据插入到数据库中。【这里我导出成文本文件,再导入到SQL SERVER中时,遇到一些时间格式问题,所以直接使用SQL】
通过以上步骤,一个完整的数据库已经得到复制,并且将丢失的部分数据找回。【有些数据还是丢失了,在第三方软件上也没有显示】
- 数据库数据修复
- Android Sqlite 数据库修复及数据导出
- SQL数据修复,SQL数据库修复,SQL数据库修复软件,SQL数据库恢复,SQL数据库日志恢复软件
- 修复数据库
- 修复数据库
- 修复数据库
- 修复数据库
- 数据库修复
- MSSQL修复数据库登录与数据用户之间关联
- 20120820两个数据库间数据不一致,修复存过
- Mysql数据库修复,Ibdata1文件删除数据恢复成功
- 用友U8数据库“具有不一致的元数据”的修复
- 修复数据库和修复表
- sql server 数据库修复,mdf 损坏 修复 直接从物理文件 抽取数据 生成新的数据库
- SQL数据库修复/数据库置疑修复
- mdf数据库文件数据修复/误删除格式化重装系统覆盖数据库数据恢复
- 修复MYSQL数据库
- sql数据库修复技术
- Windows XP硬盘安装Ubuntu 12.04 LTS的分区过程
- AD帳號解鎖(C#)
- android调用WebService进行天气查询
- 实例演示div+css的绝对定位和相对定位布局
- Javascript
- 数据库数据修复
- jsp开发中的request传值问题
- 设计模式-组合模式
- Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案
- 提示No Launcher activity found
- JavaScript
- Windows XP硬盘安装Ubuntu 12.04双系统图文详解
- 近期工作小结(吐槽文)
- JavaScript