1
fkdog 2022-08-08 13:14:26 +08:00 1
RC 级别,一个事务里每次 select 可以获取到其他事务已经提交的数据。
RR 级别,一个事务里每次 select 获取的数据都是快照,可以重复读。 update 、delete 、select .... for update 里 where 后边的查询都是取得当前读,也就是最新的数据。 我觉得你的困惑是,RC 级别下,可以读取其他事务已经提交的数据是不是违反了数据库的隔离性。 其实数据库的隔离性不是 100%完全隔离的,规范里定了 4 中隔离级别,根据自己的业务需求和使用场景来选择。 实际上大部分的需求都是可以通过乐观锁、悲观锁等手段来实现数据隔离。 |
2
tairan2006 2022-08-08 13:27:57 +08:00 1
我觉得这里的问题其实是,你清空 db 用的是`delete from`还是`truncate`语句,后者在某些 db 里是不能放在事务里的,它会导致事务立刻提交。
如果确认可以放在事务里,那么另外一个读取的事务是不可能读到空表的,无论是 RR 还是 RC 。 |
3
7911364440 2022-08-08 13:47:23 +08:00 1
delete 语句会加行锁的,如果是 delete from t 会对所有行加锁,这个时候读操作应该会被阻塞吧,所以应该不会读到空表。
|
4
nothingistrue 2022-08-08 13:54:21 +08:00 1
原子性是针对当前事务的多个语句的,要么全部执行要么全部不执行,对于当前事务的多个语句执行过程中,是否有其他事务也在执行,它不管,即使是执行的同一条数据。隔离性是针对修改同一个地方数据的不同事务的,不同的隔离级别有不同的表现,最高的序列隔离级别,能保证同一条数据当前只能被最多一个事务读写。
当你是查询和修改已存在数据的时候,可重复读级别就能保证不发生并发不一致问题。但如果是查询和新增数据(比如值为 max + 1 的列)的时候,即使是最高级别的序列隔离性,也不能保证绝不发生并发不一致,因为这时候要想并发一致就得锁表,但为了性能基本上不会物理锁表只能是变通锁表,这个变通锁表就容易漏掉一些场景。 对于你的需求,事务是解决不了并发不一致的。既然你要清空表了,那么最简单的实现就是手动锁表。 |
5
yjhatfdu2 2022-08-08 14:21:43 +08:00 1
如果用的是 truncate ,那么有可能读到空表,因为 truncate 一般不支持事务。
如果使用的是 read uncommitted ( mysql 下是这样,pg 下不会),也可能是读到空表 其他情况不应该读到空表 |
6
CRVV 2022-08-08 14:41:49 +08:00 1
> 事务的原子性是否指: "执行若干条 sql, 是原子的?"
这个问题问得,原子性是不是指它是原子的。等于没问。 原子性是指执行若干条 SQL 只能都成功或者都不成功。 > 如果我用事务约束. 是否会有某个时刻, 读了一张空表? 如果 START TRANSACTION; DELETE FROM table; INSERT INTO table VALUES..; COMMIT; 那么空表的状态没有 commit. 如果你用的是 Read uncommitted ,就有可能读到,否则不会。 |
7
chaleaochexist OP |
8
chaleaochexist OP @nothingistrue 谢谢回复.学到很多.
序列隔离级别 难道不是锁表吗? 事务按照顺序执行.也就是说同时只有一个事务在执行. |
9
exonuclease 2022-08-08 15:27:02 +08:00 1
@chaleaochexist 在 Read Committed 级别或者以上是不可能的 插入五条数据还没提交以前对别的事务不可见
|
10
yjhatfdu2 2022-08-08 15:32:59 +08:00 1
@chaleaochexist pg 下,序列化隔离等级,也不会锁表,依然是读写无冲突,但是会带来额外开销,降低性能。其他常用数据库不支持序列化隔离等级
|
11
yjhatfdu2 2022-08-08 15:34:37 +08:00 1
建议把 pg 的隔离等级文档看一下,就比较清楚了 http://www.postgres.cn/docs/12/transaction-iso.html
|
12
CRVV 2022-08-08 16:22:10 +08:00 1
|
13
nothingistrue 2022-08-09 09:27:59 +08:00 1
@chaleaochexist #8 不是同时只有一个事务在执行,而是针对一个数据主体同时只有一个事务在执行。如果操作不涉及插入行,那么数据主体通常是已存在的行,这时候只锁行就行了。如果操作涉及插入行,那么数据主体理论上是全表,但实际上可能不是,因为锁表开销太大了,这方面各数据库都有自己的实现。
|
14
qingtengmuniao 2022-08-11 15:04:45 +08:00 1
|