最近发现在SQL Server数据库(目前测试过SQL Server 2008, 2012,2014,2016各个版本)中,即使数据库处于脱机(OFFLINE)状态,但是sys.master_files中依然显示是联机状态。本文测试环境为Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) 。具体测试过程如下所示:

  1.  

  1. USE master;

  1. GO

  1. ALTER DATABASE TEST SET OFFLINE WITH ROLLBACK IMMEDIATE;

  1. GO

  1.  

  1.  

  1. SELECT  name ,

  1.         physical_name ,

  1.         state ,

  1.         state_desc

  1. FROM    sys.master_files

  1. WHERE   database_id = DB_ID('test');

  1.  

  1.  

  1. SELECT  name ,

  1.         state ,

  1.         state_desc

  1. FROM    sys.databases

  1. WHERE   name = 'test';

如上所示,sys.databases系统视图正确的显示数据库处于脱机状态(OFFLINE),但是系统视图sys.master_files显示的依然是联机(ONLINE),我们可以获取系统视图sys.master_files的定义,如下所示(至于如何获取视图定义,如果你不清楚,可以参考我的博客SQL Server查看视图定义总结),

  1. SET QUOTED_IDENTIFIER ON

  1. SET ANSI_NULLS ON

  1. GO

  1.  CREATE VIEW sys.master_files AS

  1.     SELECT

  1.         database_id         = f.dbid,

  1.         file_id             = f.fileid,

  1.         file_guid           = f.fileguid,

  1.         type                = f.filetype,

  1.         type_desc           = ft.name,

  1.         data_space_id       = f.grpid,

  1.         name                = f.lname,

  1.         physical_name       = f.pname,

  1.         state               = convert(tinyint, case f.filestate        -- Map enum EMDFileState to AvailablityStates

  1.                                 when 0 then 0 when 10 then 0    -- ONLINE

  1.                                 when 4 then 7    -- DEFUNCT

  1.                                 when 5 then 3 when 9 then 3    -- RECOVERY_PENDING

  1.                                 when 7 then 1 when 8 then 1 when 11 then 1    -- RESTORING

  1.                                 when 12 then 4    -- SUSPECT

  1.                                 else 6 end),    -- OFFLINE

  1.         state_desc          = st.name,

  1.         f.size,

  1.         max_size            = f.maxsize,

  1.         f.growth,

  1.         is_media_read_only  = sysconv(bit, f.status & 8),        -- FIL_READONLY_MEDIA

  1.         is_read_only        = sysconv(bit, f.status & 16),    -- FIL_READONLY

  1.         is_sparse           = sysconv(bit, f.status & 256),    -- FIL_SPARSE_FILE

  1.         is_percent_growth   = sysconv(bit, f.status & 32),    -- FIL_PERCENT_GROWTH

  1.         is_name_reserved    = sysconv(bit, case f.filestate when 3 then 1 else 0 end), -- x_efs_DroppedReusePending

  1.         create_lsn          = GetNumericLsn(f.createlsn),

  1.         drop_lsn            = GetNumericLsn(f.droplsn),

  1.         read_only_lsn       = GetNumericLsn(f.readonlylsn),

  1.         read_write_lsn      = GetNumericLsn(f.readwritelsn),

  1.         differential_base_lsn     = GetNumericLsn(f.diffbaselsn),

  1.         differential_base_guid    = f.diffbaseguid,

  1.         differential_base_time    = nullif(f.diffbasetime, 0),

  1.         redo_start_lsn            = GetNumericLsn(f.redostartlsn),

  1.         redo_start_fork_guid      = f.redostartforkguid,

  1.         redo_target_lsn           = GetNumericLsn(f.redotargetlsn),

  1.         redo_target_fork_guid     = f.forkguid,

  1.         backup_lsn                = GetNumericLsn(f.backuplsn),

  1.         credential_id             = cr.credential_id

  1.     FROM sys.sysbrickfiles f

  1.     LEFT JOIN sys.syspalvalues st ON st.class = 'DBFS' AND st.value = f.filestate

  1.     LEFT JOIN sys.syspalvalues ft ON ft.class = 'DBFT' AND ft.value = f.filetype

  1.     LEFT JOIN sys.credentials cr ON f.pname LIKE cr.name + N'%' COLLATE database_default

  1.     WHERE f.dbid < 0x7fff -- consistent with sys.databases

  1.         AND f.pruid = 0

  1.         AND f.filestate NOT IN (1, 2)    -- x_efs_Dummy, x_efs_Dropped

  1.         AND has_access('MF', 1) = 1

  1.  

  1. GO

可以看出sys.master_files的state值来自于系统基表sys.sysbrickfiles的filestate字段,我们从DAC模式去查看,发现TEST数据库(dbid=21)的filestat为0,这个值应该为6才对,另外,还有一个让人意外的是,这个系统表里面关于TEST数据库有两个事务日志文件记录,实际上只有一个(其实这个是前阵子写这篇博客“MS SQL 事务日志管理小结”时,测试添加、删除数据事务日志文件遗留下来的记录,不清楚是Bug还是什么问题导致在系统基表还存在这样的一条记录)

那么我们接下来看看sys.sysbrickfiles的具体定义,如下所示:

  1. SET QUOTED_IDENTIFIER ON

  1. SET ANSI_NULLS ON

  1. GO

  1. CREATE VIEW sys.databases AS

  1.     SELECT d.name, d.id AS database_id,

  1.         r.indepid AS source_database_id,

  1.         d.sid AS owner_sid,

  1.         d.crdate AS create_date,

  1.         d.cmptlevel AS compatibility_level,

  1.         -- coll.value = null means that a collation wasn't specified for the DB and the server default is used instead

  1.         convert(sysname, case when serverproperty('EngineEdition') = 5 AND d.id = 1 then serverproperty('collation')

  1.                                  else CollationPropertyFromID(convert(int, isnull(coll.value, p.cid)), 'name') end) AS collation_name,

  1.         p.user_access, ua.name AS user_access_desc,

  1.         sysconv(bit, d.status & 0x400) AS is_read_only,            -- DBR_RDONLY

  1.         sysconv(bit, d.status & 1) AS is_auto_close_on,            -- DBR_CLOSE_ON_EXIT

  1.         sysconv(bit, d.status & 0x400000) AS is_auto_shrink_on,        -- DBR_AUTOSHRINK

  1.         case when (serverproperty('EngineEdition') = 5) AND (sysconv(bit, d.status & 0x00000020) = 1) then cast (1 as tinyint) -- RESTORING

  1.              when (serverproperty('EngineEdition') = 5) AND (sysconv(bit, d.status & 0x00000080) = 1) then cast (7 as tinyint) -- COPYING

  1.              when (serverproperty('EngineEdition') = 5) AND (sysconv(bit, d.status & 0x00000100) = 1) then cast (4 as tinyint) -- SUSPECT

  1.              else p.state

  1.              end AS state, -- 7 is COPYING and 4 is SUSPECT state for database copy (UNDO: Need to have a clean way to set states in dbtable for a user db)

  1.         case when (serverproperty('EngineEdition') = 5) AND (sysconv(bit, d.status & 0x00000020) = 1) then 'RESTORING'

  1.              when (serverproperty('EngineEdition') = 5) AND (sysconv(bit, d.status & 0x00000080) = 1) then 'COPYING'

  1.              when (serverproperty('EngineEdition') = 5) AND (sysconv(bit, d.status & 0x00000100) = 1) then 'SUSPECT'

  1.              else st.name

  1.              end AS state_desc,

  1.         sysconv(bit, d.status & 0x200000) AS is_in_standby,        -- DBR_STANDBY

  1.         case when serverproperty('EngineEdition') = 5 then convert(bit, 0) else p.is_cleanly_shutdown end AS is_cleanly_shutdown,

  1.         sysconv(bit, d.status & 0x80000000) AS is_supplemental_logging_enabled,    -- DBR_SUPPLEMENT_LOG

  1.         p.snapshot_isolation_state, si.name AS snapshot_isolation_state_desc,

  1.         sysconv(bit, d.status & 0x800000) AS is_read_committed_snapshot_on,        -- DBR_READCOMMITTED_SNAPSHOT

  1.         p.recovery_model, ro.name AS recovery_model_desc,

  1.         p.page_verify_option, pv.name AS page_verify_option_desc,

  1.         sysconv(bit, d.status2 & 0x1000000) AS is_auto_create_stats_on,            -- DBR_AUTOCRTSTATS

  1.         sysconv(bit, d.status2 & 0x00400000) AS is_auto_create_stats_incremental_on,    -- DBR_AUTOCRTSTATSINC

  1.         sysconv(bit, d.status2 & 0x40000000) AS is_auto_update_stats_on,        -- DBR_AUTOUPDSTATS

  1.         sysconv(bit, d.status2 & 0x80000000) AS is_auto_update_stats_async_on,    -- DBR_AUTOUPDSTATSASYNC

  1.         sysconv(bit, d.status2 & 0x4000) AS is_ansi_null_default_on,            -- DBR_ANSINULLDFLT

  1.         sysconv(bit, d.status2 & 0x4000000) AS is_ansi_nulls_on,                -- DBR_ANSINULLS

  1.         sysconv(bit, d.status2 & 0x2000) AS is_ansi_padding_on,                    -- DBR_ANSIPADDING

  1.         sysconv(bit, d.status2 & 0x10000000) AS is_ansi_warnings_on,            -- DBR_ANSIWARNINGS

  1.         sysconv(bit, d.status2 & 0x1000) AS is_arithabort_on,                    -- DBR_ARITHABORT

  1.         sysconv(bit, d.status2 & 0x10000) AS is_concat_null_yields_null_on,        -- DBR_CATNULL

  1.         sysconv(bit, d.status2 & 0x800) AS is_numeric_roundabort_on,            -- DBR_NUMEABORT

  1.         sysconv(bit, d.status2 & 0x800000) AS is_quoted_identifier_on,            -- DBR_QUOTEDIDENT

  1.         sysconv(bit, d.status2 & 0x20000) AS is_recursive_triggers_on,            -- DBR_RECURTRIG

  1.         sysconv(bit, d.status2 & 0x2000000) AS is_cursor_close_on_commit_on,    -- DBR_CURSCLOSEONCOM

  1.         sysconv(bit, d.status2 & 0x100000) AS is_local_cursor_default,            -- DBR_DEFLOCALCURS

  1.         sysconv(bit, d.status2 & 0x20000000) AS is_fulltext_enabled,            -- DBR_FTENABLED

  1.         sysconv(bit, d.status2 & 0x200) AS is_trustworthy_on,                -- DBR_TRUSTWORTHY

  1.         sysconv(bit, d.status2 & 0x400) AS is_db_chaining_on,                -- DBR_DBCHAINING

  1.         sysconv(bit, d.status2 & 0x08000000) AS is_parameterization_forced,    -- DBR_UNIVERSALAUTOPARAM

  1.         sysconv(bit, d.status2 & 64) AS is_master_key_encrypted_by_server,    -- DBR_MASTKEY

  1.         sysconv(bit, d.status2 & 0x00000010) AS is_query_store_on,            -- DBR_QDSENABLED

  1.         sysconv(bit, d.category & 1) AS is_published,

  1.         sysconv(bit, d.category & 2) AS is_subscribed,

  1.         sysconv(bit, d.category & 4) AS is_merge_published,

  1.         sysconv(bit, d.category & 16) AS is_distributor,

  1.         sysconv(bit, d.category & 32) AS is_sync_with_backup,

  1.         d.svcbrkrguid AS service_broker_guid,

  1.         sysconv(bit, case when d.scope = 0 then 1 else 0 end) AS is_broker_enabled,

  1.         p.log_reuse_wait, lr.name AS log_reuse_wait_desc,

  1.         sysconv(bit, d.status2 & 4) AS is_date_correlation_on,         -- DBR_DATECORRELATIONOPT

  1.         sysconv(bit, d.category & 64) AS is_cdc_enabled,

  1.         sysconv(bit, d.status2 & 0x100) AS is_encrypted,                    -- DBR_ENCRYPTION

  1.         convert(bit, d.status2 & 0x8) AS is_honor_broker_priority_on,                -- DBR_HONORBRKPRI

  1.         sgr.guid AS replica_id,

  1.         sgr2.guid AS group_database_id,

  1.         ssr.indepid AS resource_pool_id,

  1.         default_language_lcid = case when ((d.status2 & 0x80000)=0x80000 AND p.containment = 1) then convert(smallint, p.default_language) else null end,

  1.         default_language_name = case when ((d.status2 & 0x80000)=0x80000 AND p.containment = 1) then convert(sysname, sld.name) else null end,

  1.         default_fulltext_language_lcid = case when ((d.status2 & 0x80000)=0x80000 AND p.containment = 1) then convert(int, p.default_fulltext_language) else null end,

  1.         default_fulltext_language_name = case when ((d.status2 & 0x80000)=0x80000 AND p.containment = 1) then convert(sysname, slft.name) else null end,

  1.         is_nested_triggers_on = case when ((d.status2 & 0x80000)=0x80000 AND p.containment = 1) then convert(bit, p.allow_nested_triggers) else null end,

  1.         is_transform_noise_words_on = case when ((d.status2 & 0x80000)=0x80000 AND p.containment = 1) then convert(bit, p.transform_noise_words) else null end,

  1.         two_digit_year_cutoff = case when ((d.status2 & 0x80000)=0x80000 AND p.containment = 1) then convert(smallint, p.two_digit_year_cutoff) else null end,

  1.         containment = sysconv(tinyint, (d.status2 & 0x80000)/0x80000), -- DBR_IS_CDB

  1.         containment_desc = convert(nvarchar(60), cdb.name),

  1.         p.recovery_seconds AS target_recovery_time_in_seconds,

  1.         p.delayed_durability,

  1.         case when (p.delayed_durability = 0) then CAST('DISABLED' AS nvarchar(60)) -- LCOPT_DISABLED

  1.              when (p.delayed_durability = 1) then CAST('ALLOWED' AS nvarchar(60)) -- LCOPT_ALLOWED

  1.              when (p.delayed_durability = 2) then CAST('FORCED' AS nvarchar(60)) -- LCOPT_FORCED

  1.              else NULL

  1.              end AS delayed_durability_desc,

  1.         convert(bit, d.status2 & 0x80) AS is_memory_optimized_elevate_to_snapshot_on                -- DBR_HKELEVATETOSNAPSHOT

  1.     FROM sys.sysdbreg d OUTER APPLY OpenRowset(TABLE DBPROP, (case when serverproperty('EngineEdition') = 5 then DB_ID() else d.id end)) p

  1.     LEFT JOIN sys.syssingleobjrefs r ON r.depid = d.id AND r.class = 96 AND r.depsubid = 0    -- SRC_VIEWPOINTDB

  1.     LEFT JOIN sys.syspalvalues st ON st.class = 'DBST' AND st.value = p.state

  1.     LEFT JOIN sys.syspalvalues ua ON ua.class = 'DBUA' AND ua.value = p.user_access

  1.     LEFT JOIN sys.syspalvalues si ON si.class = 'DBSI' AND si.value = p.snapshot_isolation_state

  1.     LEFT JOIN sys.syspalvalues ro ON ro.class = 'DBRO' AND ro.value = p.recovery_model

  1.     LEFT JOIN sys.syspalvalues pv ON pv.class = 'DBPV' AND pv.value = p.page_verify_option

  1.     LEFT JOIN sys.syspalvalues lr ON lr.class = 'LRWT' AND lr.value = p.log_reuse_wait

  1.     LEFT JOIN sys.syssingleobjrefs agdb ON agdb.depid = d.id AND agdb.class = 104 AND agdb.depsubid = 0    -- SRC_AVAILABILITYGROUP

  1.     LEFT JOIN master.sys.syssingleobjrefs ssr ON ssr.class = 108 AND ssr.depid = d.id -- SRC_RG_DB_TO_POOL

  1.     LEFT JOIN master.sys.sysclsobjs  ag ON ag.id = agdb.indepid AND ag.class = 67 -- SOC_AVAILABILITY_GROUP

  1.     LEFT JOIN master.sys.sysguidrefs sgr ON sgr.class = 8 AND sgr.id = ag.id AND sgr.subid = 1 -- GRC_AGGUID / AGGUID_REPLICA_ID

  1.     LEFT JOIN master.sys.sysguidrefs sgr2 ON sgr2.class = 9 AND sgr2.id = ag.id AND sgr2.subid = d.id -- GRC_AGDBGUID

  1.     LEFT JOIN sys.syspalvalues cdb ON cdb.class = 'DCDB' AND cdb.value = CASE WHEN (d.status2 & 0x80000)=0x80000 THEN 1 ELSE 0 END

  1.     LEFT JOIN sys.syslanguages sld ON sld.lcid = p.default_language

  1.     LEFT JOIN sys.fulltext_languages slft ON slft.lcid = p.default_fulltext_language

  1.     LEFT JOIN sys.sysobjvalues coll ON coll.valclass = 102 AND coll.subobjid = 0 AND coll.objid = d.id    -- SVC_DATACOLLATION

  1.     WHERE d.id < 0x7fff

  1.         AND has_access('DB', (case when serverproperty('EngineEdition') = 5 then DB_ID() else d.id end)) = 1

  1.  

  1. GO

 

 

EngineEdition

服务器上安装的 数据库引擎 实例的 SQL Server版本。

1 = Personal 或 Desktop Engine(不适用于 SQL Server 2005?和更高版本。)

2 = Standard(对 Standard、Web 和 Business Intelligence 返回该值。)

3 = Enterprise(对 Enterprise、Developer 以及两个 Enterprise 版本返回该值。)

4 = Express(对 Express、Express with Tools 和 Express with Advanced Services 返回该值)

5 = SQL Database

6 = SQL 数据仓库

8 = 托管实例

基本数据类型:int

因为当前数据库版本为标准版,所以stated的值来自OpenRowset(TABLE DBPROP, (case when serverproperty('EngineEdition') = 5 then DB_ID() else d.id end)) p

我们可以在单用户专用连接服务器模式下查看相关记录的值。如下截图所示:

其实发现这个问题(其实我更愿意称其为一个bug)是一次查询时的意外发现。实验测试让我有点吃惊。居然这么多版本都是这种情况! 这到底是一个“bug”还是数据库什么内部机制呢?

SQL Server系统视图sys.master_files不能正确显示数据库脱机状态的更多相关文章

  1. SQL Server 系统视图

    SQL Server系统视图非常的多,因此不可能一个一个地写,我最近一直在想,对于数据库的系统视图应该如何学,但是看了一下目录之后,我呆了,我觉得每个写一次,可能都要花费1个星期的时间,如果对每一个返 ...

  2. SQL Server系统视图 [不定期更新]

    1.sys.objects:在数据库中创建的每个用户定义的架构作用域内的对象(如表.视图.约束.默认值.日志.规则存储过程等,但不包括DDL触发器)在该表中均对应一行. 列名 说明 name 对象名. ...

  3. sql server 系统表系统视图 及作用说明

    sql server 系统视图,可分为: 目录视图   兼容性视图    动态管理视图和函数    信息架构视图    复制视图 系统表: sysaltfiles主数据库 保存数据库的文件 sysch ...

  4. sql server系统存储过程大全

    关键词:sql server系统存储过程,mssql系统存储过程 xp_cmdshell --*执行DOS各种命令,结果以文本行返回. xp_fixeddrives --*查询各磁盘/分区可用空间 x ...

  5. SQL Server 系统表简介

    SQL Server 系统表简介 系统目录是由描述SQL Server 系统的数据库.基表.视图和索引等对象的结构的系统表组成.SQL Server 经常访问系统目录,检索系统正常运行所需的必要信息. ...

  6. SQL Server查看视图定义总结

      在SQL Server中如何查看数据库视图的定义呢? 其实官方文档已经有一个较详细的总结了,这里在官方文档的基础上,我们再深入展开分析一下,例如如何获取系统视图的定义.知其然知其所以然吗. 1:使 ...

  7. Sql server 系统表

    sql server系统表详细说明 SQL Server 用户库中系统表说明 名称 说明 备注 syscolumns 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行.   sys ...

  8. SQL Server系统函数:元数据函数

    原文:SQL Server系统函数:元数据函数 1.列的长度.列名 --列的长度 select COL_LENGTH('dbo.wct', --表名 'wcid') --列名 --列名 select ...

  9. 关于SQL Server系统数据库详解

    介绍这里我们介绍SQL Sever内部的系统数据库的作用和用户数据库之间联系,关于SQL Sever如何管理用户数据库的原理,对于每个数据库开发人员和DBA都是必须掌握的. SQL Sever系统数据 ...

随机推荐

  1. FontAwesome 图标字体库的使用

    在前端开发中,许多新手常会遇见一个问题,参考的网页上有类似下图的图标,但在资源里却找不到对应的文件,这是因为这些网页使用了图标库.这里介绍一种常见的图标库——FontAwesome的使用. 1.登录F ...

  2. 【Android】OkHttp3总结与封装

    开始使用 在app目录下的build.gradle中添加依赖: implementation 'com.squareup.okhttp3:okhttp:3.13.1' implementation ' ...

  3. 一目了然呀的VS2017 Live Test

    刚刚试用了一下VS2017中的单元测试,发现,这一次,覆盖测试会自动标记出来.不用像以前一样要他细检查了.这次会自动帮你全部标记出来. 新建单元测试,使用MS的单元测试方案(VSTS使用的时候方便.) ...

  4. 函数声明 和 var声明的优先级

    function demo() { console.log(5) } var demo = function(){ console.log(4) } console.log(demo()) var d ...

  5. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  6. 打开ubantu报错(invalid environment block. Press any key to continue)

    今天向往常一样打开ubantu ,却无法正常打开,如下图 意思是无效的环境模块,随意按键继续,按任意键后如下图 折腾了许久问题也没有得到解决,后来在某篇博客中找到了答案 https://blog.cs ...

  7. [Swift]LeetCode1035.不相交的线 | Uncrossed Lines

    We write the integers of A and B (in the order they are given) on two separate horizontal lines. Now ...

  8. Ubuntu 安装php+mysql+nginx

    0x01 安装PHP https://blog.csdn.net/Msmile_my/article/details/73647809   1.添加php的仓库 sudo apt-get instal ...

  9. LindDotNetCore~Ocelot实现微服务网关

    回到目录 网关在硬件里有自己的定义,而在软件架构里也有自己的解释,它就是所有请求的入口,请求打到网关上,经过处理和加工,再返回给客户端,这个处理过程中当然就是网关的核心,也是Ocelot的核心,我们可 ...

  10. 【带着canvas去流浪】(2)绘制折线图

    目录 一. 任务说明 二. 重点提示 三. 示例代码 3.1 一般折线图 3.2 用贝塞尔曲线绘制平滑折线图 四. 大数据量场景 示例代码托管在:https://github.com/dashnowo ...