前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PostgreSQL 为什么也不建议 RR隔离级别,MySQL别笑

PostgreSQL 为什么也不建议 RR隔离级别,MySQL别笑

作者头像
AustinDatabases
发布2024-04-25 16:22:17
1150
发布2024-04-25 16:22:17
举报
文章被收录于专栏:AustinDatabasesAustinDatabases

为了说这件事的公平性,公正,透明的特性,调整isolation 从源头进行改变,所以语句执行的时候,并不会在begin 上标明是什么隔离级别。这点请各位看官注意。

代码语言:javascript
复制
# only default tablespace
#check_function_bodies = on
default_transaction_isolation = 'serializable' #'read committed' 'repeatable read'
#default_transaction_read_only = off
#default_transaction_deferrable = off
#session_replication_role = 'origin'

本篇需要说明几个问题

1 PG 的Repeatable Read 在事务的隔离性方面,的确是非常的严谨,相关的严谨性方面我们可以对比 serializable 。

2 如果我们使用 RC 的情况下,会避免一些使用RR 方面的什么问题

本着这些问题,我们来开始我们的讨论

问题1:RR 和 Serializable 在PG 中,对于一些事务的处理的情况

代码语言:javascript
复制
postgres=# create table test (id int primary key,
                   name varchar(20));
                                   
insert into test (id,name) values (1,'simon');
insert into test (id,name) values (2,'kacy');
insert into test (id,name) values (3,'Tim');
insert into test (id,name) values (4,'Austin');
CREATE TABLE
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
postgres=# 
postgres=# show transaction_isolation;
 transaction_isolation 
-----------------------
 repeatable read
(1 row)

postgres=# select * from test;
 id |  name  
----+--------
  1 | simon
  2 | kacy
  3 | Tim
  4 | Austin
(4 rows)

上图中我们初始化了一个数据库的表,并且插入了4条,数据记录。

然后我们打开4个客户进程,来模拟多客户访问下的一些情况。首先我们要在 serializable 隔离级别下进行,相关的工作。我们以截图和文字的方式来进行解析。

1 serializable

session 1

代码语言:javascript
复制
postgres=# begin;
BEGIN
postgres=*# show transaction_isolation;
 transaction_isolation 
-----------------------
 serializable
(1 row)

postgres=*# update test set name = '4444' where id = 4;
UPDATE 1
postgres=*# update test set name = '333' where id = 3;
ERROR:  could not serialize access due to concurrent update
postgres=!# 

session2

代码语言:javascript
复制
postgres=# show transaction_isolation;
 transaction_isolation 
-----------------------
 serializable
(1 row)

postgres=# insert into test (id,name) values (5,'5555');
INSERT 0 1
postgres=# 

session 3

代码语言:javascript
复制
postgres=# show transaction_isolation;
 transaction_isolation 
-----------------------
 serializable
(1 row)

postgres=#  
postgres=# update test set name = '333' where id = 3;
UPDATE 1

上面是相关PostgreSQL 在SERIALIZABLE 级别上执行事务产生的结果,

ERROR: could not serialize access due to concurrent update

此时我们将,Isolation 调整为 , repeatable read 我们在尝试一次,看结果如何

1 repeatable read

session 1

代码语言:javascript
复制
postgres=# begin;
BEGIN
postgres=*# update test set name = '4444' where id = 4;
UPDATE 1

session 2

代码语言:javascript
复制
postgres=# insert into test (id,name) values (5,'5555');
INSERT 0 1

session 3

代码语言:javascript
复制
postgres=# update test set name = '333' where id = 3;
UPDATE 1

session 1

代码语言:javascript
复制
postgres=*# update test set name = '333' where id = 3;
ERROR:  could not serialize access due to concurrent update
postgres=!# 

从上图的执行过程我们得到了session 1 执行事务错误,并且报告为 could not serialize access due to concurrent update 的错误。

通过上面的实验,我们得到一个答案,在这样的事务处理中,PG 在事务操作中的反馈-- 序列化和RR 反馈是一样的。

可能一个事例不够,那么我们在做一个实例,这个实例比较简单,开四个进程,表中一条记录,分别对这条记录进行修改,最后最先进行修改的进程对这个数据进行commit, 然后观察

CREATE TABLE accounts (

id SERIAL PRIMARY KEY,

name VARCHAR(100),

balance INTEGER

);

INSERT INTO accounts (name, balance) VALUES ('Alice', 1000);

下面四个图,是repeatable read 和 serializable 两个隔离级别,在操作同样的事务操作后的结果,可以看到这两个之间没有区别。

那么我们将隔离级别降级为RC,看看做同样的事情会有什么变化

我们把事例1的操作在重新来一边

在这次操作里面,我们可以发现操作中没有失败和退回了,整体操作都是正常进行的。

那么PG的隔离级别到底有什么问题,PG数据库主要的在隔离级别方面有以下特点

1 PG的隔离级别中是不存在 Read uncommitted 的,这点和某些世界级别数据库一样,某些数据库也不存在read uncommitted.

2 PG 数据库在 RR 隔离级别方面,是非常严格实现相关隔离级别的要求,没有偷工减料,但这样得结果是,在RR 隔离级别中,将会对于高并发和热表的事务操作变得不友好,会产生更多的死锁,BLOCKED 事务失败的概率会提高不少,应用程序必须有重试的机制,或者这将劝退不少的PG初级的使用者(开发人员)

3 PG 的 RC 隔离级别,严格遵守RC的隔离级别的要求,同时在金融类的场景下,RC 完全满足使用的需求,并不需要进行RR的隔离级别强制需求,如果有一些特殊的需求,也可以通过应用程序来自行解决,这点也参见世界级别的数据库产品Oracle,他在金融系统中也是使用RC,也并未使用RR 作为默认的金融方面的隔离级别进行使用

另需要注明,如果必须使用PG 中的RR 隔离级别,则应用系统的开发者,需要注意应用中一些设计的事务的顺序,不要不同的事务操作表的顺序是逆向的(非业务要求,进行逆向设计)。这样也会避免RR 给你带来的一些事务经常失败的问题产生。

最后,MYSQL 在事务隔离级别中,为什么也不建议使用RR,结果与PG 一样都是不建议,但MYSQL 在RR 隔离级别上的问题,主要是性能问题,这里主要指的的是 间隙锁解决幻读的问题导致的在MYSQL范围查询中导致的性能问题。同时下面的图也能说明一些问题,在RR ISOLATION 的层面。

所以如果作为金融类的数据库使用,必须要严谨的情况下,并且必须使用RR 作为默认隔离级别的情况下,建议还是首先考虑POSTGRESQL 而不是......

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-23,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 AustinDatabases 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com