隔离级别
Read Uncommitted(读未提交)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果,在多用户数据库中,脏读是非常危险的,在并发情况下,查询结果非常不可控,即使不考虑结果的严谨性只追求性能,它的性能也并不比其他事务隔离级别好多少,可以说脏读没有任何好处。所以未提交读这一事务隔离级别很少用于实际应用。
Read Committed(读已提交)
这是PostgreSQL的默认隔离级别,它满足了一个事务只能看见已经提交事务对关联数据所做的改变的隔离需求。
Repeatable Read(可重复读)
确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。
Serializable(可序列化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
PostgreSQL隔离级别:
PostgreSQL的读未提交和读已提交的行为模式相同,默认读已提交。
并发控制
基于锁
排它锁
:被加锁的对象只能被持有锁的事务读取和修改,其他事务无法在该对象上加其他锁,也不能读取和修改该对象。
共享锁
:被加锁的对象可以被持锁事务读取,但是不能被修改,其他事务也可以在上面再加共享锁。
封锁对象的大小称为
封锁粒度(Granularity)
。封锁的对象可以是逻辑单元,也可以是物理单元。以关系数据库为例子,封锁对象可以是这样一些逻辑单元:属性值、属性值的集合、元组、关系、索引项、整个索引项甚至整个数据库;也可以是这样的一些物理单元:页(数据页或索引页)、物理记录等。
封锁的策略是一组规则,这些规则阐明了事务何时对数据项进行加锁和解锁,通常称为封锁协议(Locking Protocol)。由于采用了封锁策略,一次只能执行一个事务,所以只会产生串行调度,迫使事务只能等待前面的事务结束之后才可以开始,所以基于锁的并发控制机制导致性能低下,并发程度低,所以pg的策略是提供一系列锁由用户自行调用。
Advisory Lock(咨询锁)是postgresql特有的锁,有十多种类,按照生效范围、锁类型、申请和释放。
基于版本
基于锁的并发控制机制要么延迟一项操作,要么中止发出该操作的事务来保证可串行性。如果每一数据项的旧值副本保存在系统中,这些问题就可以避免。这种基于多个旧值版本的并发控制即MVCC。
一般把基于锁的并发控制机制称成为悲观机制,而把MVCC机制称为乐观机制。这是因为锁机制是一种预防性的机制,读会阻塞写,写也会阻塞读,当封锁粒度较大,时间较长时并发性能就不会太好;而MVCC是一种后验性的机制,读不阻塞写,写也不阻塞读,等到提交的时候才检验是否有冲突,由于没有锁,所以读写不会相互阻塞,避免了大粒度和长时间的锁定,能更好地适应对读的响应速度和并发性要求高的场景,大大提升了并发性能。
常见的数据库如Oracle、PostgreSQL、MySQL(Innodb)都使用MVCC并发控制机制。在MVCC 中,每一个写操作创建一个新的版本。当事务发出一个读操作时,并发控制管理器选择一个版本进行读取。也就是为数据增加一个关于版本的标识,在读取数据时,连同版本号一起读出,在更新时对此版本号加一。
读写相互不阻塞:读只会读当前事务能可见的版本,而写是在新版本上面操作。