标签: sql-server

SQL Server 数据库何时准备好接受查询?

在 SQL Server 错误日志文件中,我发现了以下几行:

2018-02-22 14:10:58.95 spid17s     Starting up database 'msdb'.
2018-02-22 14:10:58.95 spid16s     Starting up database 'ReportServer'.
2018-02-22 14:10:58.95 spid18s     Starting up database 'ReportServerTempDB'.
2018-02-22 14:10:58.95 spid19s     Starting up database 'XYZ'.
Run Code Online (Sandbox Code Playgroud)

如果我在此之前检查数据库 XYZ 的状态,则ONLINE使用以下语句:

SELECT state_desc FROM sys.databases WHERE name='XYZ'
Run Code Online (Sandbox Code Playgroud)

...但是当我尝试使用 C# 应用程序连接到该数据库时,它无法连接到该数据库。

错误是:

用户“asd”登录失败。
原因:无法打开明确指定的数据库。

我尝试了三个不同的用户(为应用程序定义的 Windows 用户、sa、SQL Server 用户)。当我在操作系统启动时运行应用程序时会出现问题,但是如果我在启动后手动启动它,则不会发生错误,因此我认为所有 SQL Server 设置和防火墙设置都是正确的。

在此之前,我还检查了服务状态是否正在运行。

我还应该检查什么以确保数据库实际上在线并准备好进行查询?

我正在寻找一个密钥,它告诉我可以查询数据库,而不是延迟一段时间(甚至不是基于明确的原因)。

我想扫描文本“启动数据库'XYZ'”的错误日志,但这意味着我必须为SQL Server错误日志的路径添加应用程序的设置。这也意味着多次阅读文件,直到我找到这句话。

sql-server-2008 sql-server startup

12
推荐指数
1
解决办法
2572
查看次数

以不妨碍并行的方式模拟用户定义的标量函数

我想看看是否有办法欺骗 SQL Server 为查询使用某个计划。

1. 环境

想象一下,您有一些在不同进程之间共享的数据。因此,假设我们有一些占用大量空间的实验结果。然后,对于每个过程,我们知道我们想要使用哪一年/哪月的实验结果。

if object_id('dbo.SharedData') is not null
    drop table SharedData

create table dbo.SharedData (
    experiment_year int,
    experiment_month int,
    rn int,
    calculated_number int,
    primary key (experiment_year, experiment_month, rn)
)
go
Run Code Online (Sandbox Code Playgroud)

现在,对于每个过程,我们都将参数保存在表中

if object_id('dbo.Params') is not null
    drop table dbo.Params

create table dbo.Params (
    session_id int,
    experiment_year int,
    experiment_month int,
    primary key (session_id)
)
go
Run Code Online (Sandbox Code Playgroud)

2. 测试数据

让我们添加一些测试数据:

insert into dbo.Params (session_id, experiment_year, experiment_month)
select 1, 2014, 3 union all
select 2, 2014, 4 
go

insert into …
Run Code Online (Sandbox Code Playgroud)

performance sql-server functions sql-server-2016 query-performance

12
推荐指数
2
解决办法
1003
查看次数

授予 ALTER TABLE 权限有多危险?

想象以下场景

CREATE DATABASE test

GO

USE test;    

CREATE TABLE dbo.Customer
  (
     CustomerId   INT,
     Email        VARCHAR(100),
     SensitiveData VARCHAR(20)
  );

INSERT INTO dbo.Customer
VALUES     (1,'abc@foo.com','12346789');
Run Code Online (Sandbox Code Playgroud)

在某些时候,编写了一个 ETL 过程,在test数据库中执行一些活动。

CREATE USER etlUser WITHOUT LOGIN; /*For demo purposes*/

CREATE TABLE dbo.StagingTable
  (
     StagingTableId INT,
     SomeData       VARCHAR(100),
  )

GRANT UPDATE,INSERT,DELETE,SELECT,ALTER ON dbo.StagingTable TO etlUser;

DENY SELECT ON dbo.Customer TO etlUser;
DENY SELECT ON dbo.Customer (SensitiveData) TO etlUser; /*For good measure*/
Run Code Online (Sandbox Code Playgroud)

etlUser 不应该对Customer表(当然也不是对SensitiveData列)具有权限,因此上面明确拒绝了这些权限。

ETL 过程会截断,dbo.StagingTable因此被授予ALTER表权限。

这在安全审计期间被标记。这个场景有多危险?

sql-server permissions

12
推荐指数
2
解决办法
9161
查看次数

备份检测到损坏,但 CHECKDB 没有

我有一个数据库,当我运行备份命令时

BACKUP DATABASE [MyDatabase] TO     
DISK =  'G:\Backup\MyDatabase_01_01_2018.bak'   
WITH    NOFORMAT, NOSKIP, COMPRESSION, INIT, BUFFERCOUNT = 100
Run Code Online (Sandbox Code Playgroud)

我收到错误消息

消息 3043,级别 16,状态 1,第 8 行
BACKUP 'MyDatabase' 在文件 'F:\Data\MyDatabase_1.ndf' 中的页面 (1:745345) 上检测到错误。
消息 3013,级别 16,状态 1,第 8 行
BACKUP DATABASE 异常终止。

我运行了一个完整的 CHECKDB,但它回来了。我确实注意到页面验证选项已设置为 NONE(不是我做的),因此我将其更改为 CHECKSUM 并重建数据库中的所有索引以使其写入所有页面并生成校验和。在此之后备份仍然失败并且 checkdb 仍然显示干净(所以没有变化)。

DBCC CHECKDB('MyDatabase') WITH NO_INFOMSGS, ALL_ERRORMSGS,
DATA_PURITY, EXTENDED_LOGICAL_CHECKS;
Run Code Online (Sandbox Code Playgroud)

从 SQL 日志:

xxx 执行的 DBCC CHECKDB (MyDatabase) WITH all_errormsgs, no_infomsgs, data_purity 发现 0 个错误并修复了 0 个错误。已用时间:0 小时 21 分 46 秒。内部数据库快照具有分割点 LSN = 000ab776:0000112f:0001 和第一个 LSN …

sql-server corruption dbcc-checkdb

12
推荐指数
1
解决办法
1358
查看次数

查询挑战:基于度量而不是行数创建大小均匀的存储桶

我将用尽可能均匀地装载固定数量的卡车订单来描述问题。

输入:

@TruckCount - the number of empty trucks to fill
Run Code Online (Sandbox Code Playgroud)

一套:

OrderId, 
OrderDetailId, 
OrderDetailSize, 
TruckId (initially null)
Run Code Online (Sandbox Code Playgroud)

Orders由一个或多个组成OrderDetails。

这里的挑战是TruckId为每条记录分配一个。

单个订单不能跨卡车拆分。

卡车应尽可能均匀*装载,以sum(OrderDetailSize).

* 均匀:装载最少的卡车和装载最多的卡车之间可实现的最小增量。根据这个定义,1,2,3 比 1,1,4 分布更均匀。如果有帮助,请假装您是统计算法,创建均匀的高度直方图。

没有考虑最大卡车负载。这些是神奇的弹性卡车。然而,卡车的数量是固定的。

有一个明显的迭代解决方案 - 循环分配订单。

但是它可以作为基于集合的逻辑来完成吗?

我的主要兴趣是 SQL Server 2014 或更高版本。但其他平台的基于集合的解决方案也可能很有趣。

这感觉就像 Itzik Ben-Gan 领土 :)

我的实际应用程序将处理工作负载分配到多个存储桶中,以匹配逻辑 CPU 的数量。因此每个桶没有最大大小。统计更新,特别是。我只是认为将问题抽象为卡车作为构建挑战的一种方式会更有趣。

CREATE TABLE #OrderDetail (
OrderId int NOT NULL,
OrderDetailId int NOT NULL PRIMARY KEY,
OrderDetailSize tinyint NOT NULL,
TruckId tinyint NULL)

-- Sample Data

INSERT #OrderDetail (OrderId, OrderDetailId, …
Run Code Online (Sandbox Code Playgroud)

sql-server query sql-server-2014

12
推荐指数
1
解决办法
1768
查看次数

何时将`nvarchar/nchar` 与 SQL Server 2019 一起使用?

在 SQL Server 2019 中,Microsoft 引入了对和数据类型的UTF-8 支持,并表示:CHARVARCHAR

此功能可显着节省存储空间,具体取决于使用的字符集。例如,使用支持 UTF-8 的归类将带有 ASCII 字符串的现有列数据类型从 NCHAR(10) 更改为 CHAR(10),意味着存储需求减少了近 50%。这种减少是因为 NCHAR(10) 需要 22 个字节的存储空间,而 CHAR(10) 需要 12 个字节来存储相同的 Unicode 字符串。

UTF-8似乎支持每个脚本,所以基本上我们就可以开始在存储Unicode数据varchar和char列。正如文档中所说,这可以减少表和索引的大小,从那里我们可以获得更好的性能,因为读取的数据量更少。

我想知道这是不是意味着我们可以停止使用nvarchar和nchar列,它实现UTF-16?

任何人都可以指出一个场景和原因,不要使用带有UTF编码的 char 数据类型并继续使用 n-chars数据类型吗?

sql-server datatypes utf-8 unicode sql-server-2019

12
推荐指数
2
解决办法
2362
查看次数

为什么批处理模式窗口聚合产量算术溢出?

以下查询SUM对列存储表执行窗口化处理1500 total rows,每个表的值为 0 或 1,并溢出INT数据类型。为什么会这样?

SELECT a, p, s, v, m, n,
    SUM(CASE WHEN n IS NULL THEN 0 ELSE 1 END)
        OVER (PARTITION BY s, v, a ORDER BY p) AS lastNonNullPartition
FROM (
    SELECT a, p, s, v, m, n,
        RANK() OVER (PARTITION BY v, s, a, p ORDER BY m) AS rank
    FROM #t /* A columnstore table with 1,500 rows */
)  x
WHERE x.rank = 1
--Msg 8115, …
Run Code Online (Sandbox Code Playgroud)

sql-server columnstore window-functions batch-mode sql-server-2016

12
推荐指数
1
解决办法
243
查看次数

如何限制 SQL 存储过程一次只能由一个人运行?

我有一个存储过程,它基本上从一个表中选择值并将它们插入到另一个表中,这是一种归档。我想避免多人同时这样做。

当这个程序正在运行时,我不希望其他人能够启动它,但是我不希望序列化,另一个人在我完成后运行该程序。

我想要的是其他人在我运行该程序时尝试启动它以获取错误。

我尝试过使用 sp_getapplock,但是我无法完全阻止该人运行该程序。

我还尝试使用 sys.dm_exec_requests 查找过程并阻止该过程,虽然这确实有效,但我认为这不是最佳选择,因为在某些服务器上我没有运行 sys.dm_exec_sql_text(sql_handle) 的权限。

我这样做的最佳方法是什么?

sql-server stored-procedures t-sql sql-server-2012

12
推荐指数
3
解决办法
6250
查看次数

为什么要使用master来创建数据库?

我有一个简短的问题,为什么要使用use master;创建数据库?这是Microsoft 文档中的示例

USE master ;
GO
CREATE DATABASE Sales
ON
( NAME = Sales_dat,
    FILENAME = 'C:\Program Files\...\saledat.mdf',
    SIZE = 10,
    MAXSIZE = 50,
    FILEGROWTH = 5 )
LOG ON
( NAME = Sales_log,  
    FILENAME = 'C:\Program Files\...\salelog.ldf',
    SIZE = 5MB,
    MAXSIZE = 25MB,
    FILEGROWTH = 5MB ) ;
Run Code Online (Sandbox Code Playgroud)

sql-server t-sql ddl master-system-database

12
推荐指数
2
解决办法
9104
查看次数

为什么这个流聚合是必要的?

看看这个查询。它非常简单(有关表和索引定义以及重现脚本,请参见文章末尾):

SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);
Run Code Online (Sandbox Code Playgroud)

注意:“AND 1 = (SELECT 1) 只是为了防止此查询被自动参数化,我觉得这使问题变得混乱 - 尽管有或没有该子句,它实际上获得了相同的计划

这是计划(粘贴计划链接):

使用流 agg 进行计划

由于那里有一个“top 1”,我很惊讶地看到流聚合运算符。对我来说似乎没有必要,因为保证只有一行。

为了测试这个理论,我尝试了这个逻辑上等效的查询:

SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;
Run Code Online (Sandbox Code Playgroud)

这是那个计划(粘贴计划链接):

没有流 agg 的计划

果然,group by 计划能够在没有流聚合操作符的情况下通过。

请注意,两个查询都从索引的末尾“向后”读取并执行“前 1”以获得最大修订。

我在这里缺少什么? 流聚合是否在第一个查询中真正起作用,还是应该能够消除它(这只是优化器的一个限制,它不是)?

顺便说一下,我意识到这不是一个非常实际的问题(两个查询都报告 0 毫秒的 CPU 和经过时间),我只是对这里展示的内部/行为感到好奇。


这是我在运行上述两个查询之前运行的设置代码:

DROP TABLE IF EXISTS dbo.TheOneders;
GO

CREATE TABLE dbo.TheOneders
(
    Id INT NOT NULL,
    Revision SMALLINT NOT NULL,
    Something NVARCHAR(23),

    CONSTRAINT PK_TheOneders PRIMARY KEY NONCLUSTERED …
Run Code Online (Sandbox Code Playgroud)

sql-server aggregate database-internals group-by sql-server-2017

12
推荐指数
1
解决办法
691
查看次数