PostgreSQL基础(十):PostgreSQL的并发问题-LMLPHP

文章目录

PostgreSQL的并发问题

一、事务的隔离级别

二、MVCC


PostgreSQL的并发问题

一、事务的隔离级别

在不考虑隔离性的前提下,事务的并发可能会出现的问题:

  • 脏读:读到了其他事务未提交的数据。(必须避免这种情况)

  • 不可重复读:同一事务中,多次查询同一数据,结果不一致,因为其他事务修改造成的。(一些业务中这种不可重复读不是问题)

  • 幻读:同一事务中,多次查询同一数据,因为其他事务对数据进行了增删吗,导致出现了一些问题。(一些业务中这种幻读不是问题)

针对这些并发问题,关系型数据库有一些事务的隔离级别,一般用4种。

  • READ UNCOMMITTED:读未提交(啥用没用,并且PGSQL没有,提供了只是为了完整性)

  • READ COMMITTED:读已提交,可以解决脏读(PGSQL默认隔离级别)

  • REPEATABLE READ:可重复读,可以解决脏读和不可重复读(MySQL默认是这个隔离级别,PGSQL也提供了,但是设置为可重复读,效果还是串行化)

  • SERIALIZABLE:串行化,啥都能解决(锁,效率慢)

PGSQL在老版本中,只有两个隔离级别,读已提交和串行化。在PGSQL中就不存在脏读问题。

二、MVCC

首先要清楚,为啥要有MVCC。

如果一个数据库,频繁的进行读写操作,为了保证安全,采用锁的机制。但是如果采用锁机制,如果一些事务在写数据,另外一个事务就无法读数据。会造成读写之间相互阻塞。 大多数的数据库都会采用一个机制 多版本并发控制 MVCC 来解决这个问题。

比如你要查询一行数据,但是这行数据正在被修改,事务还没提交,如果此时对这行数据加锁,会导致其他的读操作阻塞,需要等待。如果采用PostgreSQL,他的内部会针对这一行数据保存多个版本,如果数据正在被写入,包就保存之前的数据版本。让读操作去查询之前的版本,不需要阻塞。等写操作的事务提交了,读操作才能查看到最新的数据。 这几个及时可以确保读写操作没有冲突 ,这个就是MVCC的主要特点。

写写操作,和MVCC没关系,那个就是加锁的方式!

Ps:这里的MVCC是基于 读已提交 去聊的,如果是串行化,那就读不到了。

在操作之前,先了解一下PGSQL中,每张表都会自带两个字段

  • xmin:给当前事务分配的数据版本。如果有其他事务做了写操作,并且提交事务了,就给xmin分配新的版本。

  • xmax:当前事务没有存在新版本,xmax就是0。如果有其他事务做了写操作,未提交事务,将写操作的版本放到xmax中。提交事务后,xmax会分配到xmin中,然后xmax归0。

PostgreSQL基础(十):PostgreSQL的并发问题-LMLPHP 

基于上图的操作查看一波效果

事务A

-- 左,事务A
--1、开启事务
begin;
--2、查询某一行数据,  xmin = 630,xmax = 0
select xmin,xmax,* from test where id = 8;
--3、每次开启事务后,会分配一个事务ID 事务id=631
select txid_current();
--7、修改id为8的数据,然后在本事务中查询   xmin = 631, xmax = 0
update test set name = '铃铛' where id = 8;
select xmin,xmax,* from test where id = 8;
--9、提交事务
commit;

 事务B

-- 右,事务B
--4、开启事务
begin;
--5、查询某一行数据,  xmin = 630,xmax = 0
select xmin,xmax,* from test where id = 8;
--6、每次开启事务后,会分配一个事务ID 事务id=632
select txid_current();
--8、事务A修改完,事务B再查询  xmin = 630  xmax = 631
select xmin,xmax,* from test where id = 8;
--10、事务A提交后,事务B再查询  xmin = 631  xmax = 0
select xmin,xmax,* from test where id = 8;

  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

  • 📢本文由 Lansonli 原创,首发于 CSDN博客🙉

  • 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨

06-09 17:15