PostgreSQL 等效于 SQLServer 的 NoLock 提示
Posted
技术标签:
【中文标题】PostgreSQL 等效于 SQLServer 的 NoLock 提示【英文标题】:PostgreSQL Equivalent of SQLServer's NoLock Hint 【发布时间】:2010-03-06 23:56:12 【问题描述】:在 SQLServer 中,您可以使用语法“(nolock)”来确保查询不会锁定表或不会被锁定同一表的其他查询阻塞。 例如
SELECT * FROM mytable (nolock) WHERE id = blah
Postgres 中的等效语法是什么?我在 PG (http://www.postgresql.org/docs/8.1/interactive/sql-lock.html) 中找到了一些关于表锁定的文档,但这一切似乎都是针对如何锁定一个表,而不是确保它没有锁定。
【问题讨论】:
等等,让我看看我是否明白这一点。有一个选项可以忽略表上的锁???如果为真,那么在验证新约束时可以选择忽略现有行,这是一个坏主意。 @Matthew Wood:总的来说,我倾向于同意。但是,忽略锁在某些情况下很有用,例如当您想要检查表的内容时进行调试,即使它处于非常大的更新过程中。最好忽略锁定,而不是等待几分钟/几小时以完成更新。 【参考方案1】:SELECT 不会锁定 PostgreSQL 中的任何表,除非您想要锁定:
SELECT * FROM tablename FOR UPDATE;
PostgreSQL 使用MVCC 来最小化锁争用,以便在多用户环境中实现合理的性能。读者不会与作者或其他读者发生冲突。
【讨论】:
这是错误的,它相当于带有提示WITH(UPDLOCK)
的显式锁定,但问题是如何获得无锁定! @matthew-wood 的回答更相关。
@BogdanMart 这是他使用锁进行选择的示例,因为它隐式不锁定。【参考方案2】:
我做了一些研究,似乎 SQL Server 中的 NOLOCK
提示与 READ UNCOMMITTED
事务隔离级别大致相同。在 PostgreSQL 中,您可以设置READ UNCOMMITTED
,但它会默默地将级别升级到READ COMMITTED
。不支持READ UNCOMMITTED
。
事务隔离的 PostgreSQL 8.4 文档:http://www.postgresql.org/docs/8.4/static/transaction-iso.html
【讨论】:
一小段引述只是为了强调原因:PostgreSQL 只提供两个隔离级别的原因是,这是将标准隔离级别映射到多版本并发控制的唯一明智方法架构。 @dezso:+1,但在 9.1 中添加了 SERIALIZABLE,因此文档已更新为“......提供三个隔离级别......”但其他方面相同。【参考方案3】:这是一个老问题,但我认为实际问题尚未得到解答。
SELECT 查询(不包含for update
子句)永远不会锁定任何行(或表),也不会阻止对表的并发访问。并发 DML(INSERT、UPDATE、DELETE)也不会阻塞 SELECT 语句。
简单地说:Postgres 中不需要(nolock)
。
读者从不阻止作者,作者从不阻止读者
【讨论】:
是的,你需要。默认隔离级别可能与 READ COMMITTED 不同,READ UNCOMMITED 的实现可能会进一步改变 @serge: 不,你根本不需要 Postgres(或 Oracle)中的(nolock)
提示。读者从不阻止作者,作者从不阻止读者。【参考方案4】:
nolock 或 readpast 的目的是查看记录是否被当前锁定。用户可以在更新中使用它来查看标识的记录是否已更改(行受影响);如果记录未被锁定,则 therowsaffected 将为 1;如果为o,则记录被锁定
根据该结果,用户可以使用 select for update 将其锁定以供自己使用。
【讨论】:
问题是要知道 Postgres 的 等价物 是什么,而不是 nolock 的目的。【参考方案5】:每个 SQL 语句都是一个隐式事务。 NOLOCK
提示对应于 READ UNCOMMITTED
(DIRTY READ
) transaction isolation level。
BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT COUNT(1) FROM my_table;
END;
实际上,这段代码与BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED
的作用相同,但进一步保证了预期的行为。
也避免使用 COUNT(*),除非你真的需要它
【讨论】:
Postgres 不支持未提交的读取 - 它永远不会允许脏读。此外,声称count(*)
比count(1)
慢的说法对于每个 DBMS 来说都是错误的。事实上,在 Postgres 中 count(1)
甚至会稍微慢一些。
count(*)
和 count(1)
在 what 上完全相同。您可能想阅读this 以了解有关count(1)
更快的(错误)神话的详细信息。此外,从您引用的链接中:“在 PostgreSQL 中,READ UNCOMMITTED 被视为 READ COMMITTED。” - 所以你永远不会在 Postgres 中获得 read uncommitted
但是隔离级别不会改变 Postgres 中的锁定行为。而且我不是在谈论空值。我说的是count(*)
和count(1)
之间的区别,它们完全没有功能上的区别。你读过blog post吗?
这不是假设。很明显,Postgres 中没有read uncommitted
。并且清楚地记录了读者不会阻止其他读者。读者不会屏蔽作者,作者也不会屏蔽读者。
所以有文件证明没有 READ UNCOMITTED - 你自己说的。以上是关于PostgreSQL 等效于 SQLServer 的 NoLock 提示的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL plpgsql try catch 块等效
Redgate SQL Prompt等效于PostgreSQL数据库
PostgreSql中是不是有等效于sp_getapplock,sp_releaseapplock的?
MySQL MATCH() AGAINST() 等效于 SQL Server