翻译如何通过页ID知道表名
2014-10-11 10:58
148 查看
翻译如何通过页ID知道表名
原文:Finding a table name from a page ID
原文地址:http://www.sqlskills.com/blogs/paul/finding-table-name-page-id/
译者:如果在一些特殊情况下只知道页ID,如何知道这是哪个表的页呢?本文主要解决这个问题。
正文:
想象一下某个早晨,你回去工作发现在夜间有一些新行插入到msdb.dbo.suspect_pages表中。通常你做的第一件事是运行DBCC CHECKDB,但是如果你的数据库有几个TB,这样可能得运行几个小时才能知道问题出在哪里——哪个表丢失了数据。但是你想到尽快找到哪个表,这样你可以选择灾难恢复方案。
另一个情形是:你在找出性能差的查询——运行我的脚本,用sys.dm_os_waiting_tasks来查看当前等待的线程,你看到许多PAGELATCH_EX等待,你需要通过sys.dm_os_waiting_tasks的resource_description列中的页ID知道哪个表。
回到第一种情形,通过suspect_pages表得到数据比较简单:
要发现表名,首先需要使用DBCC PAGE。DBCC PAGE语法如下:
你可以只使用PRINT OPTION 0,这样只是显示表头。你同时必须使用TRACE FLAG 3604来获得DBCC PAGE的输出——这相当安全。你们使用suspect_pages的输出,DBCC PAGE的返回如下:
我们感兴趣的是从metadata开始的部分。这些字段并不存放在数据本身之中。当初为SQL SERVER 2005重写DBCC PAGE时,我加入了metadata输出部分——这样比较容易找到该页所属的对象ID和索引ID(就像在SQL SERVER 7.0和2000中m_objId和m_indexId一样)。
Metadata:objectId就是我们想要的。如果你看到它是99,那么请打住——因为这意味着损坏页是分配系统的一部分——并不是一个表的页,你需要等待DBCC CHECKDB结束来知道哪个区(extent)坏了。
如果你看到ObjectId是0,这意味着没有发现metadata数据。这可能是以下原因:
1) 自从损坏被记录后,表所包含的该页已经被删除。
2) 系统目录由于某种原因损坏。
3) 页损坏,所以导致不正确的值用来查找metadata(当然查不到了)。
不管上面的什么哪一种情况,你必须等待DBCC CHECKDB结束来知道哪个区(extent)发生了破坏。
如果ObjectId不是0或者99,你可以将该值放到OBJECT_NAME函数中来获得表名:
如果你得到上面的结果,那么可能有两种原因:
你使用了错误的数据库上线文
数据库的元数据(metadata)已经被损坏,所以你只好等待DBCC CHECKDB结束。
根据我的经验,很有可能使第一种情况。你可以在suspect_pages输出的database_id,然后将它带入到DB_NAME得到数据库名称,在正确的数据库上下文中,再试一次:
原文:Finding a table name from a page ID
原文地址:http://www.sqlskills.com/blogs/paul/finding-table-name-page-id/
译者:如果在一些特殊情况下只知道页ID,如何知道这是哪个表的页呢?本文主要解决这个问题。
正文:
想象一下某个早晨,你回去工作发现在夜间有一些新行插入到msdb.dbo.suspect_pages表中。通常你做的第一件事是运行DBCC CHECKDB,但是如果你的数据库有几个TB,这样可能得运行几个小时才能知道问题出在哪里——哪个表丢失了数据。但是你想到尽快找到哪个表,这样你可以选择灾难恢复方案。
另一个情形是:你在找出性能差的查询——运行我的脚本,用sys.dm_os_waiting_tasks来查看当前等待的线程,你看到许多PAGELATCH_EX等待,你需要通过sys.dm_os_waiting_tasks的resource_description列中的页ID知道哪个表。
回到第一种情形,通过suspect_pages表得到数据比较简单:
SELECT * FROM [msdb].[dbo].[suspect_pages]; GO database_id file_id page_id event_type error_count last_update_date ----------- ----------- -------------------- ----------- ----------- ----------------------- 6 1 295 2 2 2014-09-25 01:18:22.910 |
dbcc page ( {'dbname' | dbid}, filenum, pagenum [, printopt={0|1|2|3} ]) |
DBCC TRACEON (3604); DBCC PAGE (6, 1, 295, 0); DBCC TRACEOFF (3604); GO PAGE: (1:295) BUFFER: BUF @0x00000004FD8C7980 bpage = 0x00000004A2D14000 bhash = 0x0000000000000000 bpageno = (1:295) bdbid = 6 breferences = 0 bcputicks = 0 bsampleCount = 0 bUse1 = 55116 bstat = 0x809 blog = 0x15ab215a bnext = 0x0000000000000000 PAGE HEADER: Page @0x00000004A2D14000 m_pageId = (1:295) m_headerVersion = 17 m_type = 17 m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x8200 m_objId (AllocUnitId.idObj) = 84 m_indexId (AllocUnitId.idInd) = 256 Metadata: AllocUnitId = 72057594043432960 Metadata: PartitionId = 72057594039042048 Metadata: IndexId = 0 Metadata: ObjectId = 245575913 m_prevPage = (0:0) m_nextPage = (0:0) pminlen = 8008 m_slotCnt = 1 m_freeCnt = 83 m_freeData = 8107 m_reservedCnt = 0 m_lsn = (35:200:9) m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = 1093512791 DB Frag ID = 1 Allocation Status GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED PFS (1:1) = 0x64 MIXED_EXT ALLOCATED 100_PCT_FULL DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED |
Metadata:objectId就是我们想要的。如果你看到它是99,那么请打住——因为这意味着损坏页是分配系统的一部分——并不是一个表的页,你需要等待DBCC CHECKDB结束来知道哪个区(extent)坏了。
如果你看到ObjectId是0,这意味着没有发现metadata数据。这可能是以下原因:
1) 自从损坏被记录后,表所包含的该页已经被删除。
2) 系统目录由于某种原因损坏。
3) 页损坏,所以导致不正确的值用来查找metadata(当然查不到了)。
不管上面的什么哪一种情况,你必须等待DBCC CHECKDB结束来知道哪个区(extent)发生了破坏。
如果ObjectId不是0或者99,你可以将该值放到OBJECT_NAME函数中来获得表名:
SELECT OBJECT_NAME (245575913); GO ---------------------------------------------------------------------------------------- NULL |
你使用了错误的数据库上线文
数据库的元数据(metadata)已经被损坏,所以你只好等待DBCC CHECKDB结束。
根据我的经验,很有可能使第一种情况。你可以在suspect_pages输出的database_id,然后将它带入到DB_NAME得到数据库名称,在正确的数据库上下文中,再试一次:
USE [company]; GO SELECT OBJECT_NAME (245575913); GO -------------------------------------------------------------------------------------------------------------------------------- CustomerNames |
相关文章推荐
- 如何通过页ID知道表名
- 如何通过JAVASCRIPT知道指定元素内容区域宽度的像素值?
- 如何通过RTP接口类,在.Net中创建你自己的广播系统(原创翻译,有源码)
- 通过分析块设备驱动的框架,知道如何来写驱动
- 用DS播放一个视频时,如何通过编程知道GRAPH加载的FILTER的组件所在的路径??
- 学习ASP.NET Core,你必须知道“中间件”是什么?中间件如何注册?请求处理管道是如何通过中间件构建的?
- 【微信技能】如何通过微信号知道对方微信的二维码
- [翻译]如何通过Flex SDK或者Flash Professional来开发测试Incubator
- 【翻译】如何通过使用两台电脑变得更加有效率
- 如何才能规范写作呢?-通过翻译老外的文章是不错的想法!
- 【微信技能】如何通过微信号知道对方微信的二维码
- 如何通过程序知道有哪些计算机与自己的电脑连接
- 【翻译】我如何才能知道自己已经成为一名黑客?
- 知道一个div的宽高背景色,如何不通过写在行间样式的办法更改样式?currentStyle(只兼容ie),getComeputedStyle(兼容)-->获取非行间样式
- 【微信技能】如何通过微信号知道对方微信的二维码
- 【微信技能】如何通过微信号知道对方微信的二维码
- Java中如何通过代码知道某个方法或某个类是否在声明时被标注为deprecated?
- 如何通过command line知道自己电脑信息
- 通过分析块设备驱动的框架,知道如何来写驱动
- Fusionchart官方API 由谷歌浏览器翻译通过(加我备注)如何更改chart错误信息