标签: sql-server

来自更远调用堆栈的 DB_ID 上下文

在 SQL Server 中,是否可以DB_ID从调用堆栈更远的上下文中获取 ?

我的目标是在开发沙箱数据库中创建一些方便的(并且公认的 hacky)实用程序函数,使获取对象的完全限定名称变得简单而简洁,给定它们的短名称或碎片名称,另外删除使用相同短名称的对象. 这些实用程序函数将位于单个实用程序数据库中,但会从同一服务器上的其他数据库调用。

从我从测试中可以看出:

  • ORIGINAL_DB_NAME()按预期返回连接字符串中的任何内容,而不是当前上下文(由 设置USE [dbname])。
  • 在函数中调用时,DB_NAME()返回定义该函数的数据库的名称。另一种说法是,函数或存储过程内的上下文是定义它的数据库的上下文

我知道引擎会跟踪调用堆栈上下的每个数据库上下文(请参见下面的证明)。那么有没有办法访问这些信息呢?

我希望能够在调用者数据库的上下文中查找和操作对象,即使执行代码不在同一个数据库中。例如:

use SomeDB
EXEC util.dbo.frobulate_table 'my_table'
Run Code Online (Sandbox Code Playgroud)

我知道我能做到

EXEC util.dbo.frobulate_table 'SomeDB.dbo.my_table'
Run Code Online (Sandbox Code Playgroud)

但我真的很好奇是否可以通过这种方式查询调用堆栈。

更新/注意

我确实从Gabriel McAdams 的博客中阅读并下载了代码。这提供了堆栈上下调用过程 ID 的记录,但仍然假设所有内容都在同一个数据库中。

证明 SQL Server 记住了数据库上下文上下调用堆栈

示例:在具有数据库 TestDB1 和 TestDB2 的开发服务器上

use TestDB1
GO
CREATE FUNCTION dbo.ECHO_DB_NAME() RETURNS nvarchar(128) BEGIN RETURN DB_NAME() END
GO

use TestDB2
GO
CREATE PROCEDURE dbo.ECHO_STACK AS 
BEGIN
    DECLARE @name nvarchar(128)
    SET @name = DB_NAME()
    PRINT …
Run Code Online (Sandbox Code Playgroud)

sql-server

11
推荐指数
1
解决办法
510
查看次数

更详细的事务日志文件的内容

我有一个关于事务日志(我们简称为 LDF)内容的问题。我假设一个具有完整恢复模型的数据库。

我已经读过 LDF 文件包含(记录)对数据库的每个操作(即处于完全恢复模式)。它与记录期间有什么不同BEGIN TRAN; COMMAND(s); COMMIT?我问是因为显然您可以回滚事务,但不能回滚标准命令(在完全恢复模式下)。

我猜在事务期间记录到 LDF 文件中的内容与常规完整恢复日志记录中的内容不同。那正确吗?有什么不同?是否只包含每个动作的“撤消”操作?

在相关说明中,我听说有一些商业工具可以使用完整的恢复 LDF 文件“回滚/撤消”标准查询。他们是怎么做到的呢?他们是否分析 LDF 内容并尝试提出逆/撤消操作?

sql-server recovery transaction-log

11
推荐指数
2
解决办法
5624
查看次数

为什么 SQL Server 查询使用的磁盘 I/O 不超过 7MB/秒

我有一个 SSD,使用 IOmeter 测试,显示性能超过 200MB/s。但是,当我从本地机器运行任何 SQL 查询时,Windows 资源监视器永远不会显示超过 7MB/秒的磁盘 IO。即使对于运行时间超过 2 分钟的查询也是如此。瓶颈是什么,它仅使用 SSD 的 7MB/秒?

我在跑:

  • Windows Server 2012 标准版
  • SQL Server 2008 r2
  • 英特尔 i7 3820
  • 32GB 内存
  • 磁盘固态硬盘

sql-server sql-server-2008-r2 hardware

11
推荐指数
1
解决办法
1826
查看次数

从不同版本/版本的备份文件恢复数据库

我了解到,出于向后兼容性的原因,只要您从旧版本恢复到新版本,就可以在 SQL Server 中恢复数据库。

有谁知道您是否可以从不同版本的 SQL Server 的 *.bak 文件还原数据库?我们正在通过 FTP 移动一个非常大的数据库,这需要几天时间,所以我们宁愿只做一次。如果在我们通过 FTP 传输数据库时没有人响应,我们显然会尝试一下,通过测试看看它是否有效,然后回答我们自己的问题。

以下是获取 SQL Server 版本详细信息的查询。该productversion格式为{major revision}.{minor revision}.{release revision}.{build number}。在我的情况下,源和目标{release revision}的值为。所以看起来没问题。然而,情况不同。55005512edition

询问:

SELECT 
  SERVERPROPERTY('productversion'), 
  SERVERPROPERTY('productlevel'), 
  SERVERPROPERTY('edition')
Run Code Online (Sandbox Code Playgroud)

源数据库:

10.0.5500.0
SP3
Developer Edition (64-bit)
Run Code Online (Sandbox Code Playgroud)

目标数据库:

10.0.5512.0
SP3
Enterprise Edition (64-bit)
Run Code Online (Sandbox Code Playgroud)

sql-server compatibility-level

11
推荐指数
1
解决办法
2万
查看次数

由于索引锁定顺序,SQL Server 在两次更新上死锁

我有两个更新——一个先锁定 CI,然后锁定 NCI(状态),因为状态列也在更新。另一个已经拥有 NCI 上的 U 锁,因为它知道它正在更改,然后尝试在 CI 上获得 U 锁。

强制这些序列化的最简单方法是什么?使用 TABLE 级提示似乎很奇怪,因为这是一个内部索引问题——只涉及一个表——UPDLOCK、HOLDLOCK 是否会自动应用于该表所需的所有索引,从而强制它被序列化?

以下是查询:

UPDATE htt_action_log
SET status = 'ABORTED', CLOSED = GETUTCDATE()
WHERE transition_uuid = '{F53ADDDA-E46B-4726-66D8-D7B640B66597}'
AND status = 'OPEN';
Run Code Online (Sandbox Code Playgroud)

该 X 锁定 CI 中的行(在 CREATED 列上),然后尝试 X 锁定包含状态列的 NCI。

UPDATE htt_action_log
SET status = 'RUNNING {36082BCD-EB52-4358-E3D3-4D96FD5B9F0F} 1360094342'
WHERE action_uuid = (SELECT TOP 1 action_uuid
                     FROM htt_action_log
                     WHERE transition_uuid = '{F53ADDDA-E46B-4726-66D8-D7B640B66597}'
                         AND status = 'OPEN'
                     ORDER BY action_seq)
Run Code Online (Sandbox Code Playgroud)

这个 U 锁定相同的 NCI - 我猜是嵌套查询,然后去锁定 CI 以进行更新。

因此订单产生了死锁。 …

sql-server deadlock

11
推荐指数
1
解决办法
1万
查看次数

处理使用 insert-exec 块调用的存储过程中的异常

我有一个在 insert-exec 块中调用的存储过程:

insert into @t
    exec('test')
Run Code Online (Sandbox Code Playgroud)

如何处理存储过程中生成的异常并继续处理?

下面的代码说明了这个问题。我想要做的是根据内部exec()调用的成功或失败返回0或-1 :

alter procedure test -- or create
as
begin try
    declare @retval int;
    -- This code assumes that PrintMax exists already so this generates an error
    exec('create procedure PrintMax as begin print ''hello world'' end;')
    set @retval = 0;
    select @retval;
    return(@retval);
end try
begin catch
    -- if @@TRANCOUNT > 0 commit;
    print ERROR_MESSAGE();
    set @retval = -1;
    select @retval;
    return(@retval);
end catch;
go

declare @t table (i int); …
Run Code Online (Sandbox Code Playgroud)

sql-server-2008 sql-server

11
推荐指数
1
解决办法
3万
查看次数

某些用户的查询速度很慢

我有几个从 C# .NET web 应用程序调用的查询,它们对我来说总是很快(我是 SQL Server 的本地管理员),但对于一组用户(具有所需权限的域组),查询速度非常慢它在应用程序中超时的点。

什么会导致完全相同的查询对不同的用户以不同的方式运行?

更多信息:

  • 查询是 C# 代码中的内联 SQL,而不是存储过程
  • 该应用程序使用域身份验证,用户和我自己都通过该应用程序运行查询
  • 似乎这个问题是不同的计划,一个被缓存了,所以这就是为什么它对不同的用户是不同的。某些事情正在影响缓存,因为现在通过应用程序查询对我来说很慢,而在 SQL Server Management Studio 中查询速度很快。

performance sql-server-2008 sql-server t-sql

11
推荐指数
2
解决办法
6589
查看次数

限制 Windows 管理员访问

正如SQL Server 最佳实践所说,“ Windows 身份验证模式比 SQL 身份验证更安全”。现在我想知道:有没有办法保护 SQL Server 免受具有 Windows 管理员权限的用户的攻击?

sql-server-2008 security sql-server

11
推荐指数
1
解决办法
8364
查看次数

表达式中的类型转换可能会影响查询计划选择中的“CardinalityEstimate”?

我维护一个存档数据库,该数据库将历史数据存储在分区视图中。分区列是日期时间。视图下的每个表存储一个月的数据。

我们使用日期时间列上的检查约束来约束每个表上的事件。这允许优化器限制为在事件日期时间列上过滤的查询而搜索的表。

检查约束的名称是由 SQL Server 生成的,因此通过查看名称很难知道它们的作用。

我希望约束名称的形式为“CK_TableName_Partition”。

我可以使用此查询生成重命名脚本并从 sql_text 列复制数据。WHERE 子句匹配名称看起来像是由 SQL Server 生成的检查约束:

SELECT
  checks.name AS check_name,
  tabs.name AS table_name,
  skemas.name AS schema_name,
  cols.name AS column_name,
  N'
EXECUTE sys.sp_rename
  @objname = N''' + skemas.name + N'.' + checks.name + N''',
  @newname = N''CK_' + tabs.name + N'_Partition'',
  @objtype = ''OBJECT'';' AS sql_text
FROM sys.check_constraints AS checks
INNER JOIN sys.tables AS tabs ON
  tabs.object_id = checks.parent_object_id
INNER JOIN sys.schemas AS skemas ON
  skemas.schema_id = tabs.schema_id
INNER JOIN sys.columns AS cols …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization cardinality-estimates

11
推荐指数
1
解决办法
1万
查看次数

日志传送 - RESTORE WITH STANDBY - 在 SQL Server 2012 上不断中断

我们正在使用日志传送并RESTORE WITH STANDBY在 SQL Server 2012 上以只读模式恢复数据库以用于报告目的。但是,在完成一两个日志备份的还原后,日志传送设置不断中断。日志传送仅在运行时中断RESTORE WITH STANDBYRESTORE WITH NORECOVERY不会造成任何问题。

我对此的唯一直觉是主数据库不是那么动态。因此,当没有交易时,这可能会导致RESTORE流程出现问题?

任何想法,已知的修复?

通过运行在两个表上进行大量更新的常规作业,我让它工作了几天。当作业停止运行时,日志传送设置很快失败,无法处理 .trn 文件。我重置了日志传送,并试图通过只做一个小的更新来查看它是否会继续运行,更改表中一个记录的一列的值,无论它仍然失败。

感谢您的所有回复。

PS:摘自我们的日志

02/25/2013 13:00:00,LSRestore_DBDB01-A_BulldogDB,进行中,1,DBREPORTS,LSRestore_DBDB01-A_BulldogDB,日志传送恢复日志作业步骤.,2013-02-25 13:00:12:31无法将日志备份文件“\\dbsan01\DBBackups\LSBackup_BulldogDB\BulldogDB_20130225180000.trn”应用到辅助数据库“BulldogDB”。(Microsoft.SqlServer.Management.LogShipping)***
2013-02-25 13:00:12.31 *** 错误:处理数据库“BulldogDB”的日志时出错。如果可能,从备份中恢复。如果备份不可用,则可能需要重建日志。
恢复期间发生错误,导致数据库“BulldogDB”(8:0) 无法重新启动。诊断恢复错误并修复它们或从已知良好的备份恢复。如果未纠正或预期错误,请联系技术支持。
RESTORE LOG 异常终止。
为文件 1 上的数据库“BulldogDB”文件“BulldogDB”处理了 0 页。
为文件 1.(.Net SqlClient 数据提供程序) 上的数据库 'BulldogDB' 文件 'BulldogDB_log' 处理了 1 页 ***
2013-02-25 13:00:12.32 *** 错误:无法记录历史记录/错误消息。(Microsoft.SqlServer.Management.LogShipping)***
2013-02-25 13:00:12.32 *** 错误:ExecuteNonQuery 需要打开且可用的连接。连接的当前状态是关闭的。(System.Data) ***
2013-02-25 13:00:12.32 跳过辅助数据库“BulldogDB”的日志备份文件“\\dbsan01\DBBackups\LSBackup_BulldogDB\BulldogDB_20130225180000.trn”,因为无法验证该文件。
2013-02-25 13:00:12.32 *** 错误:无法记录历史记录/错误消息。(Microsoft.SqlServer.Management.LogShipping)***
2013-02-25 13:00:12.32 *** 错误:ExecuteNonQuery 需要打开且可用的连接。连接的当前状态是关闭的。(System.Data) ***
2013-02-25 13:00:12.33 …

sql-server sql-server-2012 log-shipping

11
推荐指数
1
解决办法
2万
查看次数