翻译如何通过页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表得到数据比较简单:


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。DBCC PAGE语法如下:

dbcc page ( {‘dbname‘ | dbid}, filenum, pagenum [, printopt={0|1|2|3} ])

你可以只使用PRINT OPTION 0,这样只是显示表头。你同时必须使用TRACE FLAG 3604来获得DBCC PAGE的输出——这相当安全。你们使用suspect_pages的输出,DBCC PAGE的返回如下:


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开始的部分。这些字段并不存放在数据本身之中。当初为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函数中来获得表名:


SELECT OBJECT_NAME (245575913);

GO

----------------------------------------------------------------------------------------

NULL

如果你得到上面的结果,那么可能有两种原因:

  1. 你使用了错误的数据库上线文
  2. 数据库的元数据(metadata)已经被损坏,所以你只好等待DBCC CHECKDB结束。

根据我的经验,很有可能使第一种情况。你可以在suspect_pages输出的database_id,然后将它带入到DB_NAME得到数据库名称,在正确的数据库上下文中,再试一次:


USE [company];

GO

SELECT OBJECT_NAME (245575913);

GO

--------------------------------------------------------------------------------------------------------------------------------

CustomerNames

时间: 2025-01-10 09:28:37

翻译如何通过页ID知道表名的相关文章

如何通过页ID知道表名

通过后面这篇译文,我们大概也了解了前一篇译文的原理了. 如何通过页ID知道表名称呢? 在页头部有m_objid和m_indexId,通过这两者可以计算出分配单元ID(allocation unit id),然后通过查询就可以知道表名称了(DBCC PAGE为我们的查询做了一半工作:找出了OBJECT ID).      m_objId和m_indexId---计算--->allocation unit id---查询--->objectId-->表名称    如果此时对象已经释放分配单元

[转载] SQL获取所有数据库名、表名、储存过程以及参数列表

查询一个数据库中所有表字段属性的sql语句 1.获取所有用户名: SELECT name FROM Sysusers where status='2' and islogin='1' islogin='1'表示帐户 islogin='0'表示角色 status='2'表示用户帐户 status='0'表示糸统帐户 2.获取所有数据库名: SELECT Name FROM Master..SysDatabases ORDER BY Name 3.获取所有表名 SELECT Name FROM Da

SQL获取所有数据库名、表名、储存过程以及参数列表

SQL获取所有数据库名.表名.储存过程以及参数列表 1.获取所有用户名:SELECT name FROM Sysusers where status='2' and islogin='1'islogin='1'表示帐户islogin='0'表示角色status='2'表示用户帐户status='0'表示糸统帐户2.获取所有数据库名:SELECT Name FROM Master..SysDatabases ORDER BY Name3.获取所有表名SELECT Name FROM Databas

SQL 查找表名 字段名

转载:http://www.accessoft.com/article-show.asp?id=6135 经常碰到一些忘记表名称的情况,此时只记得个大概,此时可通过查询系统表Sysobjects找到所要的表名,如要查找包含用户的表名,可通过以下SQL语句实现, Select * From sysobjects Where name like '%user%' 如果知道列名,想查找包含有该列的表名,可加上系统表syscolumns来实现,如想查找列名中包含有user的所有表名,可通过以下SQL语句

SQLserver查询数据库所有字段-表名

SELECT * FROM INFORMATION_SCHEMA.columns WHERE TABLE_NAME='Account' SELECT (case when a.colorder=1 then d.name else '' end) as 表名,--如果表名相同就返回空 a.colorder as 字段序号, a.name as 字段名, (case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '√'else '' e

SQL获取数据库名,表名,列名,说明等信息

由于最近工作涉及SQL语句较多,对一些不常见的SQL函数.及存储过程下面进行整理和描述,供大家分享: /************************************************************************************************************** 1.获取所有用户名: islogin='1' :表示帐户 islogin='0' :表示角色 status='2' :表示用户帐户 status='0' :表示系统帐户 **

查询数据库里所有表名和字段名的语句

查询数据库里所有表名和字段名的语句SQL 查询所有表名:SELECT NAME FROM SYSOBJECTS WHERE TYPE='U'mysql: SELECT * FROM INFORMATION_SCHEMA.TABLES查询表的所有字段名:SELECT NAME FROM SYSCOLUMNS WHERE ID=OBJECT_ID(' 表名' )SELECT * FROM INFORMATION_SCHEMA.TABLESSELECT * FROM INFORMATION_SCHEM

【翻译自mos文章】在不使用par file的情况下,export or import 含有大小写表名的表

在不使用par file的情况下,export or import 含有大小写表名的表 参考原文: How to Export or Import Case Sensitive Tables Without Using a Par File (Doc ID 1622134.1)1 适用于: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 11.2.0.4 [Release 10.2 to 11.2] Information i

ASP函数:根据表和ID和字段名,返回内容

'//根据表和ID和字段名,返回内容Function dsf_fieldValueFromTable(fTable,id,fieldName) dim rs,sql set rs=server.createobject("adodb.recordset") sql="select * from " & fTable & " where id=" & id rs.open sql,conn,1,1 if not rs.eof