oracle 幻读, 不可重复读是如何避免的?

2021-09-06 15:52:52 +08:00
 stach

lz 经常在 v 站评论帮助他人, 很少发帖, 这次借贵宝地, 请教路过的各位大佬谈谈看法, 解答一下疑惑:

oracle 在具体实践中是否会考虑 "不可重复读", "幻读" 问题, 又是如何去解决的呢?


下面是楼主做的准备工作:


楼主查过 oracle 官网的文档, 似乎也没有具体的答案, db2 的资料多一些, 直接修改隔离级别为 "序列化读" 也不现实.

1625 次点击
所在节点    数据库
6 条回复
sun1991
2021-09-06 16:39:00 +08:00
给个具体点的例子吧?
stach
2021-09-06 17:01:17 +08:00
@sun1991

这里有个 MySQL 的例子: https://segmentfault.com/a/1190000016566788, 我这里是没有 oracle 的.
lz 是互联网从业者, 几乎都使用 MySQL 数据库, 所以疑惑 oracle 从业者的实践姿势
stach
2021-09-06 19:27:21 +08:00
可能 v 站大多是用 MySQL 的兄弟吧, 这个问题石沉大海了 :(
sun1991
2021-09-07 09:42:32 +08:00
以下是我的个人理解:

Oracle 一共只有两种隔离级别 (抛开 readonly 不谈). Serialize 一般不用. 常用的也就是 read committed.

Oracle 的锁是加在物理 row 上面, 也就是说, 如果 row 不存在, 那么就不能加锁. 所以 Oracle 没有 MySQL 那么多的弯弯绕. 如果你要应对不可重复读, 幻读问题, 那么老老实实地用 serialize 隔离级别.

Oracle 的 serialize 隔离级别其实是一种乐观锁, 它限制的是自己的 session 而非其它 session 的写操作, 意思是当检测到自己 session 违反了 serialize 隔离级别的限制, 就报错.

总之, Oracle 的优化目标是尽可能使得所有的 read 操作尽快完成, 所以能不锁的一概不锁.
stach
2021-09-07 10:33:38 +08:00
@sun1991
赞同老哥的说法, 不能用 MySQL 的理论去套 oracle, 开启事务的时候设定隔离级别为 serialize 不失为解决 不可重复读, 幻读的好方法.

其实 MySQL 官方的 Python Connector 库开启事务的时候, 就有指定隔离级别的参数, 只是我们几乎都习惯了固定为 REPEATABLE READ.

```python
def start_transaction(self, consistent_snapshot=False,
isolation_level=None, readonly=None):
"""Start a transaction

This method explicitly starts a transaction sending the
START TRANSACTION statement to the MySQL server. You can optionally
set whether there should be a consistent snapshot, which
isolation level you need or which access mode i.e. READ ONLY or
READ WRITE.

For example, to start a transaction with isolation level SERIALIZABLE,
you would do the following:
>>> cnx = mysql.connector.connect(..)
>>> cnx.start_transaction(isolation_level='SERIALIZABLE')

Raises ProgrammingError when a transaction is already in progress
and when ValueError when isolation_level specifies an Unknown
level.
"""
```
Hozzz
2021-09-11 01:21:29 +08:00
select for update

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/800182

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX