AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题

问题[locking](dba)

Martin Hope
Quốc Khánh Bùi
Asked: 2023-02-02 23:35:47 +0800 CST

两阶段锁定如何确保可序列化?

  • 7

我读过很多资料,他们说在数据库中实现可序列化的方法之一是使用两阶段锁定。但是我真的不明白在Jim Gray 的这个例子中两阶段锁定如何确保可序列化。

一个例子是我们在数据库中有两行,一行的值为white,另一行的值为black。我有两笔交易:

  • TX1 会将白色的值更新为黑色
  • TX2 会将黑色的值更新为白色

如果TX1和TX2同时执行,则TX1获取值为white的行锁,TX2获取值为black的行锁。所以没有锁定冲突,最终,值被交换了。

locking
  • 1 个回答
  • 30 Views
Martin Hope
John
Asked: 2022-10-11 12:11:17 +0800 CST

写入者在快照隔离级别下相互锁定的更好点

  • 3

SQL Server 中的已提交读快照和快照隔离级别取消了大多数锁定,除了一个:写入者仍然锁定其他写入者。

文档蹑手蹑脚地说了这么多,随后没有记录任何其他非常有趣的内容:

它真的只是一个被独占锁定的修改行吗?或者它也可以是不相关的行(例如,在索引中相邻)或页面?

我确实查看了锁,sys.dm_tran_locks并且我只在未提交的事务期间看到修改行上的排他锁 - 页面仅锁定为IX.

我还测试了两个事务是否可以在一个非常小的表中的两个未提交事务期间同时修改两个不同的行,该表可能适合一页并且效果也很好。

如果确实只有修改的行被独占锁定,那么如果它确保没有两个连接同时写入同一行,那么这将为具有对数据库的独占访问权限的应用程序提供无锁写入的保证。

这在我想到的场景中是可能的——但是如果页面锁定起作用,几乎没有办法做这样的事情,因为无法预测哪些行会受到影响。

sql-server locking
  • 1 个回答
  • 115 Views
Martin Hope
Dolphin
Asked: 2022-07-27 21:18:38 +0800 CST

是否有可能永远不会在 PostgreSQL 中运行vacuum full

  • 0

由于VACUUM FULL锁表,在我们的生产环境中对我们来说是不可接受的。

是否可以只在生产系统上运行VACUUM而从不运行?VACUUM FULL

是否VACUUM使新空间可重复使用INSERT?

postgresql locking
  • 2 个回答
  • 81 Views
Martin Hope
GG.
Asked: 2022-05-27 17:35:38 +0800 CST

ALTER TABLE … ADD COLUMN on a small table 需要很长时间,pg_stat_activity 不显示此表上的任何查询

  • 0

所以这是永远挂起的查询:

ALTER TABLE tasks
ADD COLUMN in_progress BOOLEAN NOT NULL DEFAULT FALSE;

该表的tasks行数少于 20,000 行,每 5 分钟左右查询一次。

我检查了pg_stat_activity10 次,它从未显示任何锁定表的查询:

SELECT *
FROM pg_stat_activity
WHERE query LIKE '%tasks%';

--- No results

我尝试了真空吸尘器,但没有帮助:

VACUUM (VERBOSE, ANALYZE) tasks;

我还尝试添加没有约束和默认值的列,我希望它在这样的表上几乎是即时的,但是当我停止查询时它运行了 1 分钟:

ALTER TABLE tasks
ADD COLUMN in_progress BOOLEAN;

我在同一时间段内对另一个表(约 1000 行)运行了查询,它是即时的。

任何想法?

PostgreSQL 11.13

通过 DBeaver 执行的查询(我多次无效/重新连接以防万一)。

postgresql locking
  • 1 个回答
  • 329 Views
Martin Hope
auxdevelopment
Asked: 2022-05-18 12:37:10 +0800 CST

将 (LEFT) JOIN 与 SELECT FOR UPDATE 组合时数据不一致

  • 3

我最近偶然发现了SELECT ... FOR UPDATE与(LEFT) JOIN. 这是表结构以及重现结果的场景:

表结构

create table counter (
  counter_id serial primary key,
  current_counter int not null default 0
);

create table diff (
  diff_id serial primary key,
  diff_increase int not null default 0,
  counter_id serial references counter(counter_id) not null
);

设想

有两个并发事务 A 和 B,都执行相同的查询。

  1. 事务 A 以该查询开始,并且能够获取锁并继续。
select *
  from counter
  left join diff on counter.counter_id = diff.counter_id
 where counter.counter_id = 1
 order by diff.diff_id desc
 limit 1
   for update of counter
;
  1. 事务 B 尝试执行相同的查询,但无法获取锁,因此等待。

  2. 事务 A 将执行以下查询:

update counter
   set current_counter = current_counter + 100
 where counter_id = 1
;

insert into diff (diff_increase, counter_id) values (100, 1)
;

commit;
  1. 事务 A 已完成,数据库的状态现在应如下所示:
-- counter table
counter_id | current_counter
------------------------------
1          | 200

-- diff table
diff_id | diff_increase | counter_id
--------------------------------------
1       | 50            | 1
2       | 50            | 1
3       | 100           | 1

预期行为

事务 B 看到更新的计数器 ( current_counter = 200) 和最后的差异 ( diff_id = 3)。

实际行为

事务 B 继续使用counter表的新状态(意思是current_counter = 200),而diff_id仍然是 2 而不是 3。

这种行为是预期的吗?如果是这样,为什么同一个查询会看到数据库的不同状态?这不违反READ COMMITTED隔离级别的保证吗?

在 Linux 上使用 PostgreSQL 13 进行测试。

postgresql locking
  • 2 个回答
  • 117 Views
Martin Hope
the Ben B
Asked: 2022-05-18 06:54:46 +0800 CST

最小化表锁的持续时间

  • 5

我有一个需要每天更新的 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 xml raw)) as row_hash
    into #final
    from #base main

select @c = count(*) from #final
if @c >0 begin

merge [The_Table_Staging] as target
using #final as source
on source.ID = target.ID

--New rows
when not matched by target then
insert (    RunDate,
            ID, 
            Reference, 
            StartDate, 
            EndDate, 
            Description,
            SomeCode,
            Row_Hash
        ) values (
            @d,
            source.ID, 
            source.Reference, 
            source.StartDate,
            source.EndDate, 
            source.Description,
            source.SomeCode,
            source.row_hash)

--Existing changed rows
when matched and source.row_hash != target.row_hash then update set
     target.RunDate         = @d
    ,target.Reference       = source.Reference
    ,target.StartDate       = source.StartDate
    ,target.EndDate         = source.EndDate
    ,target.Description     = source.Description
    ,target.SomeCode        = source.SomeCode
    ,target.row_hash        = source.row_hash

--Deleted rows
when not matched by source then delete;

--Existing unchanged rows
update [The_Table_Staging] set RunDate = @d where RunDate != @d

--Commit changes
begin transaction

exec sp_rename 'The_Table_Live', 'The_Table_Staging_T'
exec sp_rename 'The_Table_Staging', 'The_Table_Live'
exec sp_rename 'The_Table_Staging_T', 'The_Table_Staging'

commit transaction
end

这个想法是为了减少不必要的行更新,同时也尽量减少对活动表的锁定。我不太喜欢重命名表,但更新/插入需要 5-10 秒,而表重命名几乎是即时的。

所以我的问题是:这种方法可以吗,和/或我可以改进它吗?

谢谢!

编辑以回应 JD:

嗨,JD,请不要道歉 - 我在这里接受建设性的批评。

  1. 我不知道MERGE有问题。我自己从来没有遇到过问题,但是谢谢
  2. 我可能会将这部分重写为单独的INSERT/UPDATE/DELETE语句
  3. 我通常同意。我这样做的原因是,如果我TRUNCATE/INSERT在那个时候从 staging 开始,它需要 6-10 秒,而sp_rename需要不到一秒。所以锁定表的时间更少
  4. 这不会影响表锁定,因为它首先将数据放入临时表。我别无选择,只能使用链接服务器或 SSIS,在这种情况下,我更喜欢链接服务器将所有 SQL 保存在一个地方
  5. 我总是使用XML而不是CONCAT因为否则 'a', 'bc' 的哈希值与 'ab', 'c' 相同,这是不正确的

从登台到填充活动表的所有处理都很好 - 我只想尽量减少最终活动表的锁定时间,

sql-server locking
  • 1 个回答
  • 313 Views
Martin Hope
variable
Asked: 2022-05-06 05:42:01 +0800 CST

是否使用 nolock 块写入器从堆(没有聚集索引的表)中选择数据?

  • 3

我尝试复制这里给出的场景:https ://www.sqlskills.com/blogs/paul/the-curious-case-of-the-bulk_operation-lock-during-a-heap-nolock-scan/

创建了 2 个表 - 带有聚集索引的 table1,没有任何索引的 table2。

当我在 table1 上编写选择查询with (lock)时,应用了 Sch-S 锁。同样,当我在 table2 上编写相同的查询时,它也有一个 Sch-S 锁。

两种情况都没有应用 S 锁,如上面的链接所示。

要检查锁,我使用以下查询:

SELECT * FROM sys.dm_tran_locks
  WHERE resource_database_id = DB_ID()
  AND resource_associated_entity_id = OBJECT_ID(N'dbo.table1');

是否使用 nolock 块写入器从堆(没有聚集索引的表)中选择数据?

sql-server locking
  • 2 个回答
  • 111 Views
Martin Hope
George Menoutis
Asked: 2022-03-31 23:02:45 +0800 CST

更新期间持有哪些锁

  • 3

当我有一个包含多个查询的事务时,我可以通过使用waitfor和检查dm_tran_locks.

但我不能将一个查询“暂停”一半。具体来说,我想知道这个查询将如何持有锁:

update my_table set column1=new_value
where column2=filter_value

这会从一开始就需要更新锁定吗?或者它会在确定指定的行之前使用共享锁where,然后请求 U 锁?

sql-server locking
  • 1 个回答
  • 585 Views
Martin Hope
George Menoutis
Asked: 2022-03-16 03:11:43 +0800 CST

普通 IX 锁死锁

  • 1

我试图弄清僵局。有问题的表mytb仅用于以下查询:

delete mytb with (uplock,holdlock) where key_value=@value

通过 sp_executesql 调用。后面提到的两个进程都使用相同的代码,除了键值。

我正在使用跟踪标志 1222,这是服务器日志中的资源列表部分:

resource-list
objectlock lockPartition=0 objid=1433553235 subresource=FULL dbid=16 objectname=mydb.dbo.mytb id=lock5620a3480 mode=IX associatedObjectId=1433553235
owner-list
owner id=process4bd94c8 mode=IX
waiter-list
waiter id=process4c85288 mode=X requestType=convert
objectlock lockPartition=0 objid=1433553235 subresource=FULL dbid=16 objectname=mydb.dbo.mytb id=lock5620a3480 mode=IX associatedObjectId=1433553235
owner-list
owner id=process4c85288 mode=IX
waiter-list
waiter id=process4bd94c8 mode=X requestType=convert

我的理解如下:两个进程(让我们从它们的最后两个 id 字符中称它们为“c8”和“88”)设法在表上获得相同的 IX 锁,然后尝试变成 X 锁以删除必要的行,但一个进程阻塞了另一个进程。

我的理解正确吗?如果是,为什么进程共享 IX 锁?系统是否不应该拒绝访问 IX 锁来限制竞争条件的进程,这将导致第一个进程首先完成,然后第二个进程可以开始?

发表评论补充:在挖掘更多时,我发现where条件上的索引不存在,而我希望它是聚集的主键。没有这个索引会不会是死锁的原因?

sql-server locking
  • 1 个回答
  • 136 Views
Martin Hope
CSharpie
Asked: 2022-02-05 02:13:29 +0800 CST

不返回记录的查询挂在锁上

  • 5

我们注意到这种奇怪的情况,即不返回记录的查询将在指定时等待锁定WITH(UPDLOCK)。

查询很简单

SELECT primaryKey FROM someTable WITH(UPDLOCK) 
WHERE columA = 'A' 
      AND columnB BETWEEN 6 AND 8 
      AND columnC != 'C' ;

运行此查询的系统使用隔离级别read uncommitted,我们无法更改。

有没有一种方法,例如提示,不会让这个等待,但如果它会产生结果,仍然会锁定记录?

我注意到索引使用在其中起作用,因为其他查询没有这种行为。但遗憾的是,定义索引也不在可能的范围内。

我想出的唯一解决方案是IF EXISTS在执行实际查询之前在其中抛出一个,但由于竞争条件,它仍然可能发生。

类似的问题已在此处得到解答:为什么 UPDLOCK 会导致 SELECTs 挂起(锁定)?

如果没有索引来定位要锁定的行,所有测试的行都将被锁定,并且对符合条件的行的锁定将一直保持到事务完成。

但我不认为那里提供的答案适用于我的问题版本,因为查询不会返回行来“限定”。

遗憾的是,我无法访问该系统。我们只能对某些表运行查询。

目的是锁定和读取记录(如果存在)并最终更新它。如果丢失,请插入。

UPDLOCK之所以使用它,是因为在我的理解中,当锁定未提交的读取隔离时,这是正确的。

该表有一个主键,但未在 where 子句中使用。

sql-server locking
  • 1 个回答
  • 348 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve