在内部,OpenRowset(TABLE ...) 是如何工作的?

Eva*_*oll 9 sql-server database-internals

我看到很多内部视图,例如sys.syscomments调用CROSS APPLY OpenRowset(TABLE, oid). 我想知道这个函数是如何运作的以及它从什么地方读取的。让我们看一个例子TABLE SQLSRC

  • sys.syscomments
    • OpenRowset(TABLE SQLSRC, o.id, 0)(osys.sysschobjs$)
    • OpenRowset(TABLE SQLSRC, c.object_id, c.column_id)(csys.computed_columns)
    • OpenRowset(TABLE SQLSRC, p.object_id, p.procedure_number)(psys.numbered_procedures)
  • sys.all_extended_procedures
    • OpenRowset(TABLE SQLSRC, o.object_id, 0)(osys.all_objects)
  • sys.sys全文目录
    • OpenRowset(TABLE SQLSRC, o.id, 0)(osys.sysschobjs$)

看起来它正在存储程序的源代码,但在内部它们读取的是TABLE SQLSRC什么,又是什么?我猜这是一个外线键值存储?

我知道我可以使用object_definition(这是sys.sql_modules内部调用),但我想了解数据库的工作方式以及存储位置。

而且,不仅SQLSRCTABLE对以下内容的引用,

ACTIVE_TRANSACTIONS
ALUCOUNT
APRC_EVENT
BLOB_CONTAINER_ACCESSOR
BUILTINPERMISSIONS
CFGPROP
CHARSET
CHILDINSTANCES
COLLATIONS
COLUMNSTORE_OPERATIONAL_STATS
COLUMNSTORE_ROW_GROUPS
COLUMNSTORE_TUPLE_MOVER
DATABASEENCRYPTIONKEYS
DATABASE_AUTOMATIC_TUNING_ADVISOR_OPTIONS
DATABASE_AUTOMATIC_TUNING_MODE
DATABASE_FILESTREAM_OPTIONS
DATABASE_TRANSACTIONS
DATABASE_TUNING_RECOMMENDATIONS
DBLOG
DBMIRROR
DBMIRROR_AUTO_PAGE_REPAIR
DBMIRROR_PAST_ACTIONS
DBMIRROR_WITNESS
DBPROP
DBRECOVER
DBSCRIPTLEVEL
DB_SCOPED_CONFIG
DB_STORAGE_VOLUME_PROPS
DIAGLOG_CONFIGS
DMF_SP_DESCRIBE_FIRST_RESULT_SET_OBJECT
DMF_SP_DESCRIBE_FIRST_RESULT_SET_STRING
DM_AUDIT_ACTIONS
DM_AUDIT_CLASS_TYPE_MAP
DM_AVAILABILITY_DATABASES_CLUSTER
DM_AVAILABILITY_GROUPS
DM_AVAILABILITY_GROUPS_CLUSTER
DM_CDC_ERRORS
DM_CDC_LOGSCAN_SESSIONS
DM_CLOUD_PHYSICAL_SEEDING_STATS
DM_CLR_APPDOMAINS
DM_CLR_LOADED_ASSEMBLIES
DM_CLR_PROPERTIES
DM_CLR_TASKS
DM_COLUMNSTORE_OBJECT_POOL_STATS
DM_CRYPTO_PROVIDER_PROPS
DM_DB_DATABASE_ALLOCATIONS
DM_DB_FILE_SPACE_USAGE
DM_DB_LOG_SPACE_USAGE
DM_DB_LOG_STATS
DM_DB_MODULE_CONTAINMENT_BREACHING_FEATURES
DM_DB_RDA_MIGRATION_STATUS
DM_DB_RDA_SCHEMA_UPDATE_STATUS
DM_DB_SEQUENCES
DM_DB_SESSION_SPACE_USAGE
DM_DB_STATS_HISTOGRAM
DM_DB_STATS_PROPERTIES
DM_DB_TASK_SPACE_USAGE
DM_DB_VLF_INFO
DM_EXEC_BACKGROUND_JOB_QUEUE
DM_EXEC_BACKGROUND_JOB_QUEUE_STATS
DM_EXEC_CURSORS
DM_EXEC_PARALLEL_WORKERS
DM_EXEC_QE_GRANTSINFO
DM_EXEC_QE_RESSEM
DM_EXEC_QUERY_PROFILES
DM_EXEC_QUERY_STATS_XML
DM_EXEC_TEXT_QUERY_PLAN
DM_EXEC_XML_HANDLES
DM_EXTSCRIPT_EXEC_STATS
DM_EXTSCRIPT_REQUESTS
DM_FILESTREAM_FILE_IO_HANDLES
DM_FILESTREAM_FILE_IO_REQUESTS
DM_FILESTREAM_NON_TRANSACTED_HANDLES
DM_HADR_AUTOMATIC_SEEDING
DM_HADR_AUTO_PAGE_REPAIR
DM_HADR_AVAILABILITY_REPLICA_CLUSTER_NODES
DM_HADR_AVAILABILITY_REPLICA_CLUSTER_STATES
DM_HADR_CLUSTER
DM_HADR_CLUSTER_MEMBERS
DM_HADR_CLUSTER_NETWORKS
DM_HADR_DATABASE_REPLICA_CLUSTER_STATES
DM_HADR_DATABASE_REPLICA_STATES
DM_HADR_INSTANCE_NODE_MAP
DM_HADR_INTERNAL_AG_LISTENERS
DM_HADR_INTERNAL_AG_LISTENER_ADDRESSES
DM_HADR_INTERNAL_AG_READONLY_ROUTING_LIST
DM_HADR_INTERNAL_AVAILABILITY_GROUP_STATES
DM_HADR_INTERNAL_AVAILABILITY_REPLICA_STATES
DM_HADR_INTERNAL_TRANSPORT_PARTNERS
DM_HADR_INTERNAL_WSFC_AGS
DM_HADR_INTERNAL_WSFC_AG_DB_REPLICAS
DM_HADR_INTERNAL_WSFC_AG_LOGICAL_DBS
DM_HADR_INTERNAL_WSFC_AG_REPLICAS
DM_HADR_NAME_ID_MAP
DM_LOGCONSUMER_CACHEBUFFERREFS
DM_LOGCONSUMER_PRIVATECACHEBUFFERS
DM_LOGPOOLMGR_FREEPOOLS
DM_LOGPOOLMGR_RESPOOLSIZE
DM_LOGPOOLMGR_STATS
DM_LOGPOOL_CONSUMERS
DM_LOGPOOL_HASHENTRIES
DM_LOGPOOL_SHAREDCACHEBUFFERS
DM_LOGPOOL_STATS
DM_OS_BPOOLEXTENSION_CONFIG
DM_OS_DISPATCHERPOOLS
DM_OS_DISPATCHERS
DM_OS_ENUM_FILESYSTEM
DM_OS_ENUM_FIXED_DRIVES
DM_OS_FILE_EXISTS
DM_OS_HOST_INFO
DM_OS_MEMORYNODEACCESSSTATS
DM_OS_MEMORY_BROKERS
DM_OS_MEMORY_BROKER_CLERKS
DM_OS_MEMORY_NODES
DM_OS_MEMORY_POOLS
DM_OS_NODES
DM_OS_PROCESS_MEMORY
DM_OS_SPINLOCKSTATS
DM_OS_SUBLATCHES
DM_OS_SYS_MEMORY
DM_OS_WINDOWS_INFO
DM_QO_GATES
DM_REPL_ARTICLES
DM_REPL_SCHEMAS
DM_REPL_TRANHASH
DM_REPL_TRANINFO
DM_RG_CONFIGURATION
DM_RG_EXTPOOLS
DM_RG_EXTPOOL_AFFINITY
DM_RG_GROUPS
DM_RG_POOLS
DM_RG_POOL_AFFINITY
DM_RG_POOL_VOLUMES
DM_SERVER_AUDIT_STATUS
DM_SERVER_MEMORY_DUMPS
DM_SERVER_REGISTRY
DM_SERVER_SERVICES
DM_SQL_REFERENCED_ENTITIES
DM_TRAN_ACTIVE_SNAPSHOT_DATABASE_TRANSACTIONS
DM_TRAN_CURRENT_SNAPSHOT
DM_TRAN_CURRENT_TRANSACTION
DM_TRAN_TRANSACTIONS_SNAPSHOT
DM_TRAN_VERSION_STORE
DM_TRAN_VERSION_STORE_SPACE_USAGE
DM_XE_MAP_VALUES
DM_XE_OBJECTS
DM_XE_OBJECT_COLUMNS
DM_XE_PACKAGES
DM_XE_SESSIONS
DM_XE_SESSION_EVENTS
DM_XE_SESSION_EVENT_ACTIONS
DM_XE_SESSION_OBJECT_COLUMNS
DM_XE_SESSION_TARGETS
DSIPOP
EXPAND_EVENTS
FCI_CONFIGS
FILETABLES
FNGETPLANATTRIBS
FNGETQUERYPLAN
FNGETSQL
FN_DB_BACKUP_FILE_SNAPSHOTS
FN_GET_AUDIT_FILE
FN_HADR_DISTRIBUTED_AG_DB_REPLICA
FN_HADR_DISTRIBUTED_AG_REPLICA
FN_MSXE_READ_EVENT_STREAM
FN_XE_PREDICATE_XML
FN_XE_READ_FILE_TARGET_FILE
FTBATCHES
FTCATALOGS
FTCATCOMPONENTS
FTCOMPINDEX
FTCRAWLRANGES
FTCRAWLS
FTFDHOST
FTMATCHQUERY
FTMEMBUFFERS
FTMEMPOOLS
FTSYSSTPWD
FTTHESAURUSFILES
FTWORDBREAKER
FUNCTION_STATS
GLOBAL_TRANSACTIONS
GLOBAL_TRANSACTIONS_ENLISTMENTS
GLOBAL_TRANSACTIONS_LOG
GLOBAL_TRANSACTIONS_RECOVERY
HKCS_DICTIONARIES
HKCS_SEGMENTS
HK_HOST_BLOCKALLOC
INDEXCOUNT
INDEXPROP
INDEX_RESUMABLE_OPERATIONS
LOGINDEXSTATS
LOGINROLESANDGROUPS
MISSING_IDX_COLUMNS
MISSING_IDX_DETAILS
MISSING_IDX_GROUPS
NETGROUPGETMEMBERS
NETUSERGETGROUPS
OPENKEYS
OPENTAPES
OPTIMIZERINFO
PARTITIONCOUNTS
PLANGUIDES
PROC_STATS
QUERY_STATS
QUERY_STORE_CONTEXT_SETTINGS
QUERY_STORE_OPTIONS
QUERY_STORE_PLAN_IN_MEM
QUERY_STORE_QUERY_IN_MEM
QUERY_STORE_QUERY_TEXT_IN_MEM
QUERY_STORE_RUNTIME_STATS_INTERVAL
QUERY_STORE_RUNTIME_STATS_IN_MEM
QUERY_STORE_SQL_STATEMENT_HANDLE
QUERY_STORE_WAIT_STATS_IN_MEM
RSCPROP
SBACTIVATEDTASKS
SBCONNECTIONENDPOINTS
SBFORWARDEDMESSAGES
SBQUEUEMONITORS
SECURABLECLASSES
SELECTIVE_XML_INDEX_PATHS
SERVERSHAREDDRIVES
SERVERSHAREDVALIDPATHS
SQLSRC
SYSBUFFERDESCRIPTORS
SYSCOMMITTABLE
SYSCONNECTIONS
SYSCURSORCOLS
SYSCURSORREFS
SYSCURSORS
SYSCURSORTBLS
SYSDMEXECCACHEDPLANDEPENDENTOBJECTS
SYSDMEXECCACHEDPLANS
SYSDMEXECSESSIONWAITSTATS
SYSERRORS
SYSFULLTEXTLANGUAGES
SYSHOSTS
SYSINFO
SYSINPUTBUFFER
SYSIOS
SYSLANG
SYSLATCHSTATS
SYSLOCKINFO
SYSLOCKINFORMATION
SYSMEMALLOCS
SYSMEMCLERKS
SYSMEMORYCACHECLOCKHANDS
SYSMEMORYCACHECOUNTERS
SYSMEMORYCACHEENTRIES
SYSMEMORYCACHEHASHTABLES
SYSMEMORYOBJECTS
SYSMODULES
SYSNOTIFICATIONSUBS
SYSPROCESSES
SYSREF
SYSREQUESTS
SYSRINGBUFFERS
SYSRULESTATS
SYSSCHEDULERS
SYSSEMANTICLANGUAGES
SYSSESSIONS
SYSSTACKS
SYSTASKS
SYSTCPLISTENER
SYSTEM_REFERENCES
SYSTHREADS
SYSTRACECATEGORIES
SYSTRACECOLUMNS
SYSTRACEEVENTBINDINGS
SYSTRACEEVENTS
SYSTRACES
SYSTRACESUBCLASSVALUES
SYSVADUMP
SYSWAITS
SYSWAITSTATS
SYSWORKERS
SYSWORKERTLS
SYS_PERFORMANCE_COUNTERS
SYS_RG_EXTERNAL_POOL_AFFINITY
SYS_RG_POOL_AFFINITY
TAPE_STATUS
TEMPSTATS
TIME_ZONE_INFO
TRACEEVENTINFO
TRACEFILTERINFO
TRACEINFO
TRANSLATEPERMISSIONS
TRCDATA
TRCTABLE
TRIGGER_STATS
TRUSTED_ASSEMBLIES
USERROLES
VALIDATEPLANGUIDE
VALID_USE_HINTS
VIRTUALFILESTATS
VIRTUALSERVERNODES
WORDBREAK
XTP_BFC
XTP_CACHED_PLANS
XTP_CHECKPOINTS
XTP_CKPT
XTP_CKPTV2
XTP_CKPT_FILES
XTP_CKPT_FILESV2
XTP_EP_CRITICAL_REGIONS
XTP_GC_CYCLE_STATS
XTP_GC_QUEUE_STATS
XTP_HASH_IDX_STATS
XTP_INDEX_STATS
XTP_MERGE_REQUEST_TABLE
XTP_MM_CONSUMER
XTP_MM_TABLE_USAGE
XTP_PERFORMANCE_COUNTERS
XTP_PROCESS_LOG_REC
XTP_PROC_STATS
XTP_RANGE_INDEX_STATS
XTP_STMT_STATS
XTP_STORAGE
XTP_SYSTEM_GC_STATS
XTP_SYSTEM_STATS
XTP_TABLE_STATS
XTP_THREADS
XTP_TOMBSTONE
XTP_TRANSACTIONS
XTP_TRANSACTION_RECENT_ROWS
dm_tran_session_transactions
event_notification_event_types
persisted_sku_features
Run Code Online (Sandbox Code Playgroud)

Joh*_* N. 6

我认为这篇文章是您最接近确定引擎盖下发生的事情的文章:

SQL Server 在哪里存储存储过程的源?(改进.dk)

Mark S. Rasmussen 在他的文章中深入研究了几个(SQL Server)内部视图从哪里检索基本定义。Mark 通过分析自己创建的程序来实现这一点XYZ

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        
-- Create date: 
-- Description:   
-- =============================================
CREATE PROCEDURE XYZ
  AS
BEGIN
  -- SET NOCOUNT ON added to prevent extra result sets from
  -- interfering with SELECT statements.
  SET NOCOUNT ON;

  -- Insert statements for procedure here
  SELECT 'AABBCC' AS Output
END
Run Code Online (Sandbox Code Playgroud)

然后他从sys.procedures表中检索该过程的信息:

select * from sys.procedures
Run Code Online (Sandbox Code Playgroud)

...并开始sys.sql_modules查看:

select * from sys.sql_modules where object_id = <insert_object_id_of_procedure>
Run Code Online (Sandbox Code Playgroud)

这显示了新程序的源代码XYZ

但是系统在哪里存储sys.sql_modules视图的定义呢?这可以通过发出以下命令来检索:

 select object_definition(object_id('sys.sql_modules'))
Run Code Online (Sandbox Code Playgroud)

这将揭示一些重要信息。的sys.sql_modules视图依赖于object_definition系统的功能。在这里,马克撞到了一堵墙,必须通过sys.syscomments视图(已弃用)绕圈以显示:

...
CROSS APPLY
    OpenRowset(TABLE SQLSRC, c.object_id, c.column_id) s  
...
Run Code Online (Sandbox Code Playgroud)

Mark 之前通过分离数据库并使用 HEX 编辑器查找程序字符串来查找内部信息的努力AABBCC。然后使用十六进制偏移量来计算页面的 ID,然后通过DBCC PAGE显示ObjectID他正在搜索的项目的名称,在这种情况下是 then sys.sysobjvalues

从那里他sys.sysobjvalues通过语句从拳头中检索数据:

select * from sys.sysobjvalues where objid = 2105058535
Run Code Online (Sandbox Code Playgroud)

...另外通过:

select convert(varchar(max), imageval) from sys.sysobjvalues where objid = 2105058535
Run Code Online (Sandbox Code Playgroud)

_2105058535 是他的程序的 object_id_

我的沉思

现在,如果您使用 Mark 的分析检索到的信息并将其与使用...OPENROWSET(TABLE...代码的原始语句进行比较,那么假设以下内容可能是安全的:

OpenRowset(TABLE SQLSRC, p.object_id, p.procedure_number) s类似于/相关,sys.sysobjvalues因为检索到的数据包含XYZ包含字符串的虚拟过程的源代码AABBCC

选择
    o.id AS id,  
    convert(smallint, case when o.type in ('P', 'RF') then 1 else 0 end) AS number,  
    s.colid,
    s.状态,  
    转换(varbinary(8000),s.text)AS ctext,  
    convert(smallint, 2) AS 文本类型,  
    convert(smallint, 0) AS 语言,  
    sysconv(bit, 0) AS 加密,  
    sysconv(bit, 0) AS 压缩,  
    文本  
从
    sys.sysobjrdb
交叉申请
    OpenRowset(TABLE SQLSRC, o.id, 0) s  
在哪里
    db_id() = 1 AND 
    o.type IN ('P','V','X','FN','IF','TF')

s.text上面的值与以下相同imageval

选择 convert(varchar(max), imageval) from sys.sysobjvalues where objid = 2105058535

什么究竟 OpenRowset(TABLE SQLSRC, o.id, 0)做可能是对象的内部呼叫在sqlserver.exe进程或其链接库之一。