隔离级别仅适用于SELECTS而不是更新吗?
为SELECTS展示不同隔离行为的场景
1) 0:00 Thread A runs a query that returns 1000 rows that takes 5 minutes to complete
2) 0:02 Thread B runs a query that returns the same 1000 rows
3) 0:05 Thread A updates the last 1 rows in this result set and commits them
4) 0:07 Thread B's query returns*
根据隔离级别,#4中的结果集将包含线程A的更改,或者不包含. UPDATES也是如此吗?
以下是一个示例场景:
Thread A: UPDATE ... WHERE primary_key = 1234 AND version = 5
Thread B: UPDATE ... WHERE primary_key = 1234 AND version = 5
如果线程A和线程B同时进入它们的事务,并且线程B在线程A之后执行其更新,则线程B的更新将失败还是它将“看到”具有版本5的记录,因此成功?
它取决于数据库吗?例如Oracle vs MysqL vs Postgresql?
解决方法:
假设您打算显示许多ORM使用的“乐观锁定”模式,例如:
Thread A: UPDATE ... SET ..., version = 6 WHERE primary_key = 1234 AND version = 5
Thread B: UPDATE ... SET ..., version = 6 primary_key = 1234 AND version = 5
然后在所有合理的隔离级别(我不是100%确定READ UNCOMMITTED – 大多数DB甚至不支持它)线程B将不匹配任何行并且没有效果.
例如,在Postgresql中,线程B最初将匹配与A相同的行,但在行更新锁定时阻塞,直到线程A提交或回滚.此时它将重新检查条件并发现如果线程A已提交则不再匹配,因此它将不执行任何操作.行锁定意味着序列化冲突在这种特定情况下永远不会起作用.
在任何理智的数据库中,只有两个更新中的一个会成功 – 第二个将匹配零行或中止序列化失败,具体取决于隔离级别和数据库实现.甚至在InnoDB(see detailed explanation and demo in this answer)至少5.5的MysqL中也是如此.如果你正在使用MyISAM,那么正确性和可靠性显然不是你的大问题;-)
我不知道有任何数据库对UPDATEs和SELECTs应用不同的隔离规则.毕竟,UPDATE需要为其WHERE子句,子查询等提供相同的隔离保证作为SELECT. UPDATEs可以解锁哪些SELECT不能(在Postgresql中;显然它们可以在MysqL InnoDB中).与SELECT不同,UPDATE在SERIALIZABLE隔离模式下会受到序列化失败的影响 – 但它们具有相同的可见性规则.
Postgresql在concurrency control上的文档很好地解释了这一点.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。