目标: PG中存在多个会话试图同时访问同一数据库的情况,
并发控制的目标就是保证所有会话高效地访问, 同时维护数据库的完整性.
不能.
在PG中也有表和行级别的锁定机制, 因为MVCC并不能解决所有的并发控制情况,
所以还需要使用传统的数据库中的锁机制保证事务的并发.
另外, PG还提供了会话锁机制, 利用它可以扩大锁的使用范围,
即一次对某个对象加锁可以保证对于多个事务都有效.
共3个:
脏读
不可重复读
幻读
脏读: 一个事务读取了另一个未提交的并行事务写的数据.
不可重复读: 一个事务重新读取前面读取过的数据,
发现该数据已经被另一个已提交的事务修改过.
幻读: 一个事务重新执行了一个查询, 返回一套符合查询条件的数据,
发现这些数据因为其他最近提交的事务而发生了改变.
备注: 实际上幻读可以算是”不可重复读”的一种子情况.
上面所述的”不可重复读”算是下面所述的”虚读”.
不可重复读(Non-repeatable
Reads):一个事务对同一行数据重复读取两次,但是却得到了不同的结果。
包括以下情况:
(1)
虚读:事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。
(2) 幻读(Phantom
Reads):事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据或者缺少了第一次查询中出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另外一个事务插入数据造成的。
https://zhidao.baidu.com/question/1498699183609661299.html
不可重复读与幻读比较相似,都是在一个事务中多次读取到不同的数据。网络上的总结如下
不可重复读:所谓的虚读,也就是大家经常说的不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
一种更易理解的说法是:在一个事务内,多次读同一个数据。在这个事务还没有结束时,另
一个事务也访问该同一数据。那么,在第一个事务的两次读数据之间。由于第二个事务的修改,那么第一个事务读到的数据可能不一样,这样就发生了在一个事务内
两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复。
所谓幻读,是指事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,然后再提交。
幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也
修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一
样.一般解决幻读的方法是增加范围锁RangeS,锁定检锁范围为只读,这样就避免了幻读。简单来说,幻读是由插入或者删除引起的。
大致的区别在于不可重复读是由于另一个事务对数据的更改所造成的,而幻读是由于另一个事务插入或删除引起的
在数据库中, 为了有效保证并发读取数据库的正确性, 提出的”事务隔离级别”.
参考:
https://baike.baidu.com/item/事务隔离级别/2638091?fr=aladdin
为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。
未授权读取
也称为读未提交(Read
Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。
授权读取
也称为读提交(Read
Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。
可重复读取(Repeatable Read)