我在实时服务器 (SQL Server 2008 R2) 上创建了一个非聚集索引,但结果却没有提供我所希望的性能优势。所以我想再次删除索引。
不幸的是,我无法锁定正在使用的索引。它可能总是会被使用。重新启动 SQL Server 并不是一个真正的选择。
过去我想重建索引时也遇到过同样的问题,我不得不通过重新组织来解决这个问题(有时效率很低)。
有没有办法告诉 SQL Server 停止使用索引?或者是否可以运行一个查询来尝试获取索引的排他锁,无限期等待,然后删除索引?还有其他选择吗?或者我是否只需要等到出现某种中断,然后希望我记得在一切恢复联机之前将其删除?
所以我两天来一直在努力解决这个问题,但我找不到解决方案。我正在运行一个脚本来暂存大量数据。这个脚本需要大约 3500 万个锁才能完成;这意味着需要 3.36GB 的内存可用于锁定。我在配置的值中将锁的数量设置为 3700 万,但是在重新启动后,运行值只允许 16,695,296 个锁。
这相当于大约 14% 的可用内存。由于 SQL Server 2012 可以将 40% 的可用内存用于锁定,我应该有足够的空间,但我没有。我的问题是:为什么 SQL Server 不能利用额外的 26% 的可用锁内存?我读过的一切都说它应该能够。
此外,我确实尝试在动态上运行锁,但由于相同的原因和相同的错误代码也失败了:错误 1204,实例无法获得锁资源。我知道这是服务器配置而不是脚本,因为我运行了完全相同的脚本,在旧服务器(SQL Server 2008)上使用完全相同的数据集没有问题。
向数据库管理员求助;帮助我哦伟大的人!
编辑:这是故障转移群集上的 VM,该 VM 分配了 16 GB 内存。我为 SQL Server 提供了 12GB 的空间,并为主机操作系统留下了 4GB 的空间。
我认为自己是 Sql Server 锁定的初学者。
我的理解是,在使用 RCSI 时,Sql Server 不需要发出 S 锁,因为它使用行版本控制(在大多数情况下)。从http://technet.microsoft.com/en-us/library/jj856598(v=sql.110).aspx我们可以阅读以下关于 U 锁的信息:
用于可以更新的资源。防止在多个会话读取、锁定和稍后可能更新资源时发生的常见死锁形式。
知道了这一点,为什么Sql Server 需要发出U 锁(使用RCSI 时)?在我看来,Sql Server 可以简单地读取行,并在必须执行更新时直接请求 X 锁。
我一直在考虑这个的原因是因为我在更新同一个表的 2 个会话中遇到了死锁。像这样(为了清楚起见而简化):
第 1 节:
BEGIN TRAN
UPDATE t1 SET col1 = col1 + 100 WHERE col2 = value1
UPDATE t1 SET col1 = col1 + 100 WHERE col2 = value2
UPDATE t1 SET col1 = col1 + 100 WHERE col2 = value3
Run Code Online (Sandbox Code Playgroud)
第 2 节:
BEGIN TRAN
UPDATE t1 SET col1 = col1 …Run Code Online (Sandbox Code Playgroud) sql-server deadlock locking isolation-level snapshot-isolation
这是我的表:
CREATE TABLE [dbo].[Trackers] (
[IdTracker] INT IDENTITY (1, 1) NOT NULL,
[IMEI] NVARCHAR (16) NULL,
[CreationDate] DATETIME NULL,
[SuppressionDate] DATETIME NULL,
[LastUpdateDate] DATETIME NULL,
[BuyDate] DATETIME NOT NULL,
[Status] INT NOT NULL,
[LastTrackerUpdateDate] DATETIME NULL,
[IdLastTrackerPosition] INT NULL,
PRIMARY KEY CLUSTERED ([IdTracker] ASC)
);
CREATE TABLE [dbo].[TrackerPositions] (
[IdTrackerPosition] INT IDENTITY (1, 1) NOT NULL,
[TrackerId] INT NOT NULL,
[Position] [sys].[geography] NULL,
[Date] DATETIME NOT NULL,
[Speed] REAL NULL,
[NbSatellites] TINYINT NULL,
[Direction] REAL NULL,
[HDOP] REAL NULL,
PRIMARY …Run Code Online (Sandbox Code Playgroud) 我从文档中读到,在RELEASE_LOCK从持有锁的连接调用之后分发由许多连接请求的锁的行为是未定义的。我很好奇:假设我有一个p1请求锁定的过程,GET_LOCK("lock", 0);以便对该过程的多次调用不会相互干扰。该过程在终止之前释放锁。我有另一个程序p2使用GET_LOCK("lock", 10);.
假设有大量对 的调用p1,并且在中间的某个地方p2被调用,如下所示:
...
CALL p1();
CALL p1();
CALL p2();
CALL p1();
#lock released here from first p1() call: who gets it?
...
Run Code Online (Sandbox Code Playgroud)
理论上,第二个过程不应该受到太大影响:它等待锁被释放,因为GET_LOCKinp1的超时为 0,p2应该是唯一一个在释放时请求锁的过程。但是,我认为我不能期望这种理想的行为是真实的。GET_LOCK从第一个过程开始,当然会花费一些小但非零的时间,并且由于锁不是按请求顺序分配的,是否有可能将锁传递给连续调用p1并p2必须等待?
我有一个大表(58+ 百万条记录),它表示第二个表中两条记录(玩家和目标)之间的关系。
不幸的是,设计我们模式的人并没有考虑周全,而是选择使用用户名来表示这种关系,而不是用户记录的数字 ID。随着事情的进展(就像他们通常所做的那样),我们的用户名不再是玩家的有效唯一表示,因此我需要将这些关系转换为使用数字 ID。
多亏了 Percona Toolkit,在不加锁的情况下添加字段很容易,它提供了 pt-online-schema-change 可以在实时表上进行 ALTER。但是,填充表格可能会更棘手。
表格看起来像这样(我已经剥离了不相关字段的创建),两个未填充的字段是player_id和target_id:
CREATE TABLE `player_targets` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`player` varchar(20) NOT NULL,
`player_id` int(10) unsigned DEFAULT NULL,
`target` varchar(20) NOT NULL,
`target_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=58000000 DEFAULT CHARSET=latin1;
CREATE TABLE 'player_uuids' (
`id`int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=600000 DEFAUL CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)
我打算用这样的查询填充两个新字段:
UPDATE player_targets t
INNER JOIN player_uuids u1
ON …Run Code Online (Sandbox Code Playgroud) 昨晚将我们的数据库从 9.3.5 升级到 9.4.1 后,服务器遇到了高 CPU 峰值。升级是通过 pg_dump 完成的。于是把数据库转成SQL,再导入9.4。
在 CPU 峰值期间,日志中有很多这样的消息:
process X still waiting for ExclusiveLock on extension of relation Y of database Z
after 1036.234 ms
Run Code Online (Sandbox Code Playgroud)
和:
process X acquired ExclusiveLock on extension of relation Y of database Z
after 2788.050 ms
Run Code Online (Sandbox Code Playgroud)
看起来可疑的是,有时在完全相同的毫秒内有几个完全相同的关系号的“获取”消息。
为什么 Postgres 会在同一毫秒内将一个表增长两次?它可能是一个具有高填充因子的索引吗?
欢迎任何有关如何解决此问题的建议。
PS 我也在Postgres 邮件列表上问过这个问题,如果不行,请告诉我。
昨天我们遇到了一个关键问题,其中一个 1 秒的存储过程开始需要几分钟才能执行。我目前还不知道业务逻辑,但是想了解使用sp_GetAppLock.
所以场景是:
调用存储过程usp_abc,无参数
存储过程中的代码如下所示:
BEGIN
BEGIN TRANSACTION
sp_getapplock @Resource = usp_abc, @LockMode = 'Exclusive'
with cte_1
( SELECT TOP 1 ID FROM tbl1 WHERE Status = 'OK')
UPDATE tbl1
SET Status = 'Complete'
WHERE ID = (SELECT ID FROM cte_1)
COMMIT TRAN
END
Run Code Online (Sandbox Code Playgroud)
这个存储过程是从同一个应用程序调用的,但是在来自两个不同应用程序服务器的负载平衡器上。存储过程不断执行,昨天因为积压,我们遇到了更多问题(每秒多次)。
我昨天在查询 sp_who2 时看到的是存储过程的执行被较早的执行阻止了。大约有 5 个 SPID 在做同样的事情。我追溯了第一个 SPID 以查看资源等待。它在SOS_SCHEDULER_YIELD和 APPLICATION:5.0 " usp_abc"之间波动- 基本上是它本身。
看起来它自己陷入了一个令人讨厌的循环,但有时执行确实完成了。在没有锁定的情况下自行运行更新时,它按预期运行亚秒。
一旦负载平衡器关闭并且请求来自单一来源,问题就在查询中消失了。
这不是我们的代码,但是我们想就如何阻止这种情况再次发生提出建议。据我所知,开发人员出于并发原因并可能避免死锁而将其设置到位。
然而,根据代码判断,在这种情况下,本机 sql 读取提交应该就足够了,因为它应该锁定正在更新的数据,这意味着不可能两次更新同一条记录。我认为这个查询不会出现死锁问题。
你怎么看?
我有一个 .NET 应用程序,它正在获取 SQL 更新超时,我相信正在发生某种阻塞/锁定,这导致了这种情况。我在数据库上运行了一个阻塞进程报告,发现了一些潜在的罪魁祸首:17 秒的阻塞。
下面是这样的日志(有很多类似的):
<blocked-process-report>
<blocked-process>
<process id="process308898748" taskpriority="0" logused="0" waitresource="OBJECT: 99:774293818:0 " waittime="17146" ownerId="66317995993" transactionname="UPDATE" lasttranstarted="2015-06-15T12:59:05.817" XDES="0x3bc9cd970" lockMode="IX" schedulerid="7" kpid="11204" status="suspended" spid="161" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2015-06-15T12:59:05.817" lastbatchcompleted="2015-06-15T12:59:05.817" clientapp=".Net SqlClient Data Provider" hostname="WORKFLOWG10" hostpid="6832" loginname="WorkflowStateUpdaterSP" isolationlevel="read committed (2)" xactid="66317995993" currentdb="99" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame line="1" stmtstart="16" sqlhandle="0x02000000cb1bb914fe051a308bd33cb2b873948749c2a96d"/>
<frame line="1" sqlhandle="0x0200000075c8f5236facd1f18bca0258f9d4babad99091d6"/>
</executionStack>
<inputbuf>
UPDATE [ScheduDB].[dbo].[SP_ScheduleEvent] set DateLastProcessed = GETDATE() where ScheduleEventID = 3111573 </inputbuf>
</process>
</blocked-process>
<blocking-process>
<process status="suspended" waitresource="OBJECT: 99:774293818:0 " waittime="17182" spid="278" sbid="0" ecid="0" …Run Code Online (Sandbox Code Playgroud) 我一直在阅读 Paul White 撰写的关于SQL Server 隔离级别的一系列文章,并遇到了一个短语:
为了强调这一点,无论发生什么并发修改,用 T-SQL 编写的伪约束都必须正确执行。应用程序开发人员可能会使用 lock 语句来保护敏感操作。T-SQL 程序员最接近风险存储过程和触发器代码的工具是相对很少使用的
sp_getapplock系统存储过程。这并不是说它是唯一的,甚至是首选的选择,只是它存在并且在某些情况下可能是正确的选择。
我正在使用sp_getapplock,这让我想知道我是否正确使用它,或者有更好的方法来获得所需的效果。
我有一个 C++ 应用程序,可以 24/7 全天候循环处理所谓的“构建服务器”。有一个包含这些建筑物服务器列表的表格(大约 200 行)。可以随时添加新行,但这种情况并不经常发生。行永远不会被删除,但它们可以被标记为不活动。处理一个服务器可能需要几秒到几十分钟,每个服务器都不一样,有的“小”,有的“大”。一旦服务器被处理,应用程序必须等待至少 20 分钟才能再次处理它(服务器不应过于频繁地轮询)。应用程序启动 10 个并行执行处理的线程,但我必须保证没有两个线程试图同时处理同一个服务器. 两个不同的服务器可以而且应该同时处理,但每个服务器的处理频率不能超过 20 分钟一次。
下面是一个表的定义:
CREATE TABLE [dbo].[PortalBuildingServers](
[InternalIP] [varchar](64) NOT NULL,
[LastCheckStarted] [datetime] NOT NULL,
[LastCheckCompleted] [datetime] NOT NULL,
[IsActiveAndNotDisabled] [bit] NOT NULL,
[MaxBSMonitoringEventLogItemID] [bigint] NOT NULL,
CONSTRAINT [PK_PortalBuildingServers] PRIMARY KEY CLUSTERED
(
[InternalIP] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS …Run Code Online (Sandbox Code Playgroud) locking ×10
sql-server ×7
index ×2
mysql ×2
auto-growth ×1
blocking ×1
deadlock ×1
fill-factor ×1
memory ×1
myisam ×1
postgresql ×1
t-sql ×1
update ×1