根据https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html,在 MySQL 8 中删除索引是就地的,而不是即时的。据我了解,INPLACE 意味着可能涉及一些表锁定。我们希望从 80M 行表中删除一些不再需要的索引。对数据库的暂存副本进行的测试显示索引在几百毫秒内被删除,因此操作可能非常快。它是否有可能导致每秒读取次数很多且平均每秒写入次数约为 1 次的生产表上出现大量锁定(超过几秒)?如果是这样,我们应该注意哪些条件可能会导致这种情况?(重申一下,这些索引不被任何查询使用。)
我们注意到这种奇怪的情况,即不返回任何记录的查询将在WITH(UPDLOCK)指定时等待锁定。
查询很简单
SELECT primaryKey FROM someTable WITH(UPDLOCK)
WHERE columA = 'A'
AND columnB BETWEEN 6 AND 8
AND columnC != 'C' ;
Run Code Online (Sandbox Code Playgroud)
运行此查询的系统使用隔离级别read uncommissed,我们无法更改该级别。
有没有一种方法,例如提示,不会让这个等待,但如果它会产生结果,仍然锁定记录?
我注意到索引的使用在其中发挥了作用,因为其他查询没有这种行为。但遗憾的是,定义索引也不可能。
我想出的唯一解决方案是IF EXISTS在执行实际查询之前在其中抛出一个,但由于竞争条件,它仍然可能发生。
类似的问题已在这里得到解答:Why does UPDLOCK Causes SELECTs tohang (lock)?
如果没有索引来定位要锁定的行,则所有测试行都将被锁定,并且合格行上的锁将被保留,直到事务完成。
但我不认为那里提供的答案适用于我的问题版本,因为查询不会返回“合格”的行。
遗憾的是我无法访问该系统。我们只能对某些表运行查询。
目的是锁定并读取记录(如果存在)并最终更新它。如果缺失则插入。
UPDLOCK使用它是因为根据我的理解,当锁定读未提交隔离时,这是正确的。
该表有主键,但在 where 子句中未使用它。
我有一个需要每天更新的 SQL 表。更新发生时可能会或可能不会对该表进行查询。大约有 500,000 行。
我们遇到一个问题,当更新表的作业与针对表的查询同时运行时,会出现锁定冲突。
所以我重写了更新表的流程如下:
ALTER procedure [dbo].[Table_Generate] as
declare @d datetime = getdate(), @c as int
--Check temp tables
IF OBJECT_ID('tempdb..#final') IS NOT NULL
DROP TABLE #final
IF OBJECT_ID('tempdb..#base') IS NOT NULL
DROP TABLE #base
--Get source data from linked server
select
ID,
Reference,
StartDate,
EndDate,
Description,
SomeCode
into #base
from [LinkedServer].[Database].dbo.[A_View]
--Generate row_hash
select
ID,
Reference,
StartDate,
EndDate,
Description,
SomeCode,
hashbytes('SHA2_256',(
select
ID,
Reference,
StartDate,
EndDate,
Description,
SomeCode
from #base sub where sub.ID = main.ID for …Run Code Online (Sandbox Code Playgroud) 作为客户端的试运行,我试图在我的开发服务器上启用“锁定内存中的页面”设置,但无论我如何更改,我都无法在 SQL 中显示“使用锁定的页面作为缓冲池”服务器日志。在为客户做这件事之前,我想确保我能正确地做到这一点。
我们的开发服务器是带有 4 GB RAM 的 Windows 2003,SQL Server 2008 R2 标准版 32 位。
以下是我尝试过的:
选中“使用 AWE 分配内存”。
设置“最大服务器内存”设置。
在 SQL Server 服务配置中添加启动参数 -T845。
SQL Server 服务在 LocalSystem 帐户上运行,因此根据我所阅读的内容,我不需要在“内存中的锁定页面”特权中输入帐户。但是,我确实尝试将服务更改为在“管理员”登录名下运行,并将该登录名添加到“锁定内存中的页面”特权中。
重新启动 SQL Server 服务。
我所做的一切都不会放
使用锁定页面作为缓冲池
进入我的 SQL Server 日志,但当我运行 DBCC TRACESTATUS 时,845 跟踪似乎已打开。
任何人都知道为什么我所做的一切似乎都没有打开它?
客户希望我们的应用程序更快地处理更多数据,因此安排与他们的 dba 会面以讨论选项。
此应用程序会生成大量用于报告的数据。在每次运行之前,删除该项目的旧数据,执行计算,然后插入新数据。在繁忙时期,用户会排队数百个这样的生成任务,我们同时运行多达 30 个。每次运行可能会创建 60K 行。
dba 建议我们可以将应用程序更改为使用 30 个分区(例如,每个线程一个)以减少插入和删除期间线程之间的锁定。他们建议在标准 sql 中我们可以做类似的事情
INSERT INTO schema.table.partition (...) VALUES (...)
Run Code Online (Sandbox Code Playgroud)
我在msdn 文档中没有看到这种语法,这意味着更改这个应用程序很痛苦,但是否有可能做到这一点?据我了解,我们会改为使用分区函数基于表的列进行分区?
我已经阅读了创建分区函数文档,但我不完全确定如何创建一个函数来满足我们的需求。更糟糕的是,我还没有企业版来尝试这个,所以我为不正确的语法道歉。
我在想,例如,如果我们有一个 items 表和一个包含该项目数据的 itemdata 表,我们可能会通过基于类似的函数拆分数据来对 itemdata 表进行分区itemid mod 30。这会将项目 1 放在分区 1 中,将项目 2 放在分区 2 中,等等。我不确定我们是否可以在分区函数、方案、表声明中执行此操作,或者我们是否需要创建一个计算列并使用价值观条款?也不确定我们是否会看到任何性能改进?
这就是我认为我们可以实现的方式:
CREATE PARTITION FUNCTION SplittingItemIds_PFunc(decimal(18,0)) AS
RANGE LEFT FOR VALUES
(0,1,2,3, ... ,29)
CREATE PARTITION SCHEME SplittingItemIds_Scheme
AS PARTITION SplittingItemIds_PFunc
ALL TO ([PRIMARY]);
CREATE TABLE ItemData
(
Id decimal(18,0),
ItemId decimal(18,0),
...
)
ON …Run Code Online (Sandbox Code Playgroud) 这是一个非常奇怪的问题,所以请耐心等待。我有一个存储过程,可以进行一些繁重的处理。当它运行良好时,它通常需要几分钟的时间,具体取决于服务器负载,但有时它似乎卡住了。
我查看了 sp_who2 的结果,我看到该进程没有被阻塞,它仍然列为“RUNNABLE”,但磁盘 IO 中的值保持不变。一旦进程进入这种状态,它就永远不会完成。如果我终止进程并重新执行存储过程,我通常会得到相同的结果。
有时重新执行存储过程是可行的,但我最终不得不重新启动 SQL Server。不理想......重新启动后,存储过程按预期执行。有没有人遇到过这样的问题?任何建议将不胜感激。
更多的上下文。我正在执行的存储过程如下所示:
delete
from table1
insert into table1
select columns
from
(
select columns
from giant_table_1 WITH (NOLOCK)
where condition
group by columns
UNION
select columns
from giant_table_2 WITH (NOLOCK)
where condition
group by columns
)
where condition
more crud on table1
.
.
.
Run Code Online (Sandbox Code Playgroud)
如果我将一些日志语句插入到存储过程中,我可以看到它挂起时它挂在插入/选择上。想知道这是否可能是 NOLOCK 语句的奇怪结果。我们(我的意思是我的老板 :))添加了 nolock,因为 Giant_table_1 和 Giant_table_2 不断变化。如果没有 nolock,我们的 sproc 会被其他长时间运行的进程阻塞很多,反之亦然。
提前致谢!
看着
update MyTable
set Status = 1
where Status = 0
Run Code Online (Sandbox Code Playgroud)
当然 -where在实际更新之前计算。
但是这个过滤(where Status = 0)也在锁里面吗?
我的意思是锁在哪里?
这里 : update ...
或在这里: filter and update...
给出以下代码:
Set conn = CreateObject("ADODB.Connection")
Set RS = CreateObject("ADODB.Recordset")
conn.BeginTrans
...
//This is the line it is about
RS.Open "SELECT a,b FROM c FOR UPDATE", conn, adOpenDynamic, adLockPessimistic
...
RS.Close
conn.CommitTrans
conn.Close
Run Code Online (Sandbox Code Playgroud)
我使用时有什么区别:
RS.Open "SELECT a,b FROM c (UPDLOCK)", conn, adOpenDynamic, adLockPessimistic
Run Code Online (Sandbox Code Playgroud)
更新:
现在我们使用 FOR UPDATE 但看起来表没有锁定。SQL Profiler 向我们展示了这一点:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
declare @p1 int set @p1=NULL declare @p3 int set @p3=229378 declare @p4 int set @p4=163842 declare @p5 int set @p5=NULL exec sp_cursoropen @p1 output,N'SELECT a,b FROM …Run Code Online (Sandbox Code Playgroud) 我取消了一个耗时太长的查询。之后,SQL-Server 数据库被锁定。重新启动 SQL Server 后,我的数据库模式为“恢复中”。现在我不能再访问我的数据库了。如果查看属性,则会收到以下错误消息(我是域管理员):
属性大小对数据库 X 不可用。此对象可能不存在此属性,或者可能由于访问权限不足而无法检索。
如果我访问视图,我将收到以下消息:
超出锁定请求超时期限
SQL Server 版本:SQLServer 2008 R2
有人可以帮我吗?这个数据库明天应该被转移到生产中。
当连接因任何原因关闭时,我可以告诉 SQL Server“做某事”(例如释放应用程序级锁)吗?
背景:我想在应用程序级别而不是数据库级别锁定记录。但是,当应用程序崩溃时,我无法释放锁定。基本上,我在我的应用程序中实现以下算法:
function editRecord(recordId):
begin transaction
if (select lockedBy from myTable where id = recordId) is not empty:
commit
show "Sorry, record already in use by ..."
else
update myTable set lockedBy = current_user() where id = recordId
commit
show UI window to let user edit and update record
update myTablet set lockedBy = empty where id = recordId
Run Code Online (Sandbox Code Playgroud)
我试图找出是否有一种简单的方法可以在连接崩溃时摆脱应用程序级锁定。
locking ×10
sql-server ×8
blocking ×1
ddl ×1
index ×1
memory ×1
merge ×1
mysql ×1
partitioning ×1
performance ×1
t-sql ×1