我的理解是更新锁定一个元组,将其标记为已删除,然后添加一个新元组。
换句话说,更新 = 删除 + 插入。
或者我曾经相信。但在 MVCC 中,更新与删除 + 插入之间似乎存在一些根本不同。
设置:
CREATE TABLE example (a int PRIMARY KEY, b int);
INSERT INTO example VALUES (1, 1);
Run Code Online (Sandbox Code Playgroud)
方法一:更新
CREATE TABLE example (a int PRIMARY KEY, b int);
INSERT INTO example VALUES (1, 1);
Run Code Online (Sandbox Code Playgroud)
方法二:删除插入
-- session A session B
BEGIN;
UPDATE example SET b = 2 WHERE a = 1;
DELETE FROM example WHERE a = 1;
COMMIT;
-- now there are 0 rows in table example (1 row was …
Run Code Online (Sandbox Code Playgroud) 在最简单的情况下,当我们向表中插入新行(并且事务提交)时,它将对所有后续事务可见。请参阅xmax
此示例中的 0:
CREATE TABLE vis (
id serial,
is_active boolean
);
INSERT INTO vis (is_active) VALUES (FALSE);
SELECT ctid, xmin, xmax, * FROM vis;
ctid ?xmin ? xmax ? id ? is_active
?????????????????????????????????????
(0,1) ?2699 ? 0 ? 1 ? f
Run Code Online (Sandbox Code Playgroud)
当我们更新它时(因为该标志是FALSE
偶然设置的),它会发生一些变化:
UPDATE vis SET is_active = TRUE;
SELECT ctid, xmin, xmax, * FROM vis;
ctid ? xmin ? xmax ? id ? is_active
?????????????????????????????????????
(0,2) ? 2700 ? 0 ? 1 ? t
Run Code Online (Sandbox Code Playgroud)
根据PostgreSQL 使用的 …
我知道 PostgreSQL 为并发控制提供了多种锁定模式。当我通读他们的文件时,我不明白为什么ACCESS EXCLUSIVE
在任何情况下都需要锁。EXCLUSIVE
锁和ACCESS EXCLUSIVE
锁之间的唯一区别似乎是ACCESS EXCLUSIVE
锁不允许从表中读取。
但是,人们能够阅读不是一件好事吗?在什么情况下应该阻止用户阅读?在文档中,我看到通常DROP TABLE
等会使用ACCESS EXCLUSIVE
锁,但为什么呢?我在想,也许当您删除表时,当您尝试读取时,数据已经部分消失,因此结果将被破坏。但是后来我意识到由于 Postgres 中的所有内容都是事务性的,DROP TABLE
因此在提交之前不应该生效。所以我的猜测应该是错误的。
我还是很困惑。ACCESS EXCLUSIVE
当您将它与EXCLUSIVE
锁定进行比较时,为什么又需要锁定?我最好的猜测是用ACCESS EXCLUSIVE
锁替换锁EXCLUSIVE
不会破坏 PostgreSQL。只是有时人们不希望别人阅读。我错过了什么?
阅读 IBM 网站HERE上发布的 CouchDB 的旧概述,我惊讶地发现以下内容:
大多数现代数据库已经开始从锁定机制转向 MVCC,包括 Oracle(自 V7 起)、MySQL(与 InnoDB 一起使用时)和 Microsoft® SQL Server 2005 及更高版本。
我目前使用 SQL Server 相当多(V2012)并且从未考虑过可能存在任何形式的 MVCC。我之前也在with (tablock, holdlock)
存储过程中使用过。
SQL Server 是否真的在任何地方实现了 MVCC,它如何与是否实现的想法相协调with (tablock, holdlock)
?
如果我创建一个表。
CREATE TABLE foo AS
SELECT CASE WHEN random() > 0.5 THEN x END AS x
FROM generate_series(1,10) AS x;
Run Code Online (Sandbox Code Playgroud)
然后我在事务中运行以下命令
BEGIN;
SELECT count(*)
FROM foo
WHERE x IS NOT NULL;
--time
SELECT count(*)
FROM foo
WHERE x IS NOT NULL;
END;
Run Code Online (Sandbox Code Playgroud)
在什么交易级别下我的结果保证在交易中保持不变?
据我了解 InnoDB 支持
行级锁定
锁定用于当多个作者试图更新相同的行时。一次只有一个作者可以更新一行,第一个更新行的人会锁定它,直到他们提交更改。其他作家必须等到第一个作家提交。但至少对于行级锁定,它们只有在更新同一行时才会发生争用。
读锁可用于防止其他用户读取正在更新的记录(或页面),以便其他用户不会对即将过时的信息采取行动。
多版本并发控制
作家不会阻止读者
读者不会屏蔽任何人,也不会被任何人屏蔽。
这两者是相反的。
我的问题是:锁定或 mvcc 何时发生?我需要在哪里指定数据库应该使用哪一个?
由于读者不会阻止编写者,编写者也不会阻止读者就是 MVCC 的全部内容,那么 postgresql 如何防止正在将更改提交到块/页面的编写者阻止读者读取这些不一致的数据呢?
因此,根据我对 PostgreSQL MVCC 的理解,每个表都表示为一个堆文件,每个堆文件包含页面/块的集合,这些页面/块是 8 kb 的信息段。
所以说两个事务T1
并发T2
运行并T1
决定对block1
. 因此,首先,在内存中T1
读取并对其进行修改,当最终完成时,它决定提交;block1
即实际上将这些内存中的更改写回block1
. 所以我知道xmax
它修改的先前条目被设置为id(T1)
,并且创建了一个新条目并xmin
设置为id(T1)
。现在我发现困难的是,当实际的提交过程发生时T1
,比如说T2
读取(而写入T1
已经开始但尚未结束)。此案如何处理?
任何答案将不胜感激
mvcc ×7
postgresql ×5
concurrency ×2
locking ×2
transaction ×2
acid ×1
innodb ×1
mysql ×1
sql-server ×1