同时执行select * from table for update;和insert into table values ...的问题

第一个session执行:select * from table for update;
第二个session执行:insert into table values ...
比如这个表最初只有3条数据,那我在执行第一个session时,同时执行第二个session,插入一条新数据,但第一个session执行的结果只有最初的3条记录,可以解释下原因么?是碰巧还是数据库的机制保证了select同时insert,此时select出的记录肯定是insert之前的记录集?谢谢高手指点!谢谢!
我的做法可能和以下两位的说法不太一致。

我的做法:
在proc中写一个SELECT FOR UPDATE的逻辑,执行这个程序,例如现在表中有3条数据,程序中会先将SELECT FOR UPDATE的结果集放到一个cursor中,然后我将这三条数据打印到屏幕上,但每次打印都间隔5秒。

与此同时,我执行insert并commit操作,这个过程直接在plsql中进行,不超过1s。

待程序打印出3条记录后就结束了,此时打印的是insert之前的3条记录,所以我上面的提问是否成立呢?

----------------------------------------

就是说即使在select开始到select结束之间,如果有insert操作及commit操作,到select结束时也不会显示insert的数据?对于多个session同时对一个表进行操作时,难道不会出现这种情况?
session1:select开始 ---------------- select结束
session2: insert-commit

执行时你是手工同时执行的,但数据库系统是按每个语句单独执行的,实际就是先执行select ,在执行select时,insert还没有执行,所以select执行的结果是insert以前的数据

对同一个表的操作只能是一个先执行,另一个后执行。
这样说,在你做select 操作时,系统给这个表加了一把锁,就不允许其它操作。只有当select 结束,这个锁才能打开,再进行下一个操作。

数据打印到屏幕上,但每次打印都间隔5秒-----这只是个显示时间问题,不代表这个select 需要5秒才完成。
温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2018-05-10
对于楼主的这个场景,可以作如下的分析:
第一个session在执行select * from table for update时,查询已有数据库中的数据,并上锁,第二个session执行insert语句时,向表中增加新的数据,但是,因为还没有commit,所以,数据没有真正的反映到数据库中。

也就是说,如果你先执行第二个session的insert语句,然后再执行第一个session的select * from table for update,其结果是一样的,关键是你的insert还没有commit,只有当你的insert语句commit之后,在执行select * from table for update,其结果才会包含你insert的数据。

-------------------------
补充:
对于数据库来说,你的两个请求肯定有个先后顺序的,如果insert先到达,同时,commit的指令也比select的指令先到达的话,你的select肯定就包含insert之后的内容,否则就不会包含insert之后的内容。不知道楼主是否明白了。时间再怎么短也是有个先后的。微观上是串行,宏观上是并行。 语句间(即上面的指令)是一个原子操作,而你的insert 和commit并不是原子操作,insert之后,可能还没有commit,而已经开始了select操作。

------
select的操作是一个原子操作,上面的理解应该有点问题,应该下面得比较好:
场景1:session2: insert ---------------- commit
session2:select
场景2:session2: insert ---------------- commit
session2: select
场景3:session2: insert ---------------- commit
session2: select

场景1和场景2的select结果都是不包含insert的数据的,而场景3是包含insert的数据。本回答被提问者和网友采纳
相似回答