PostgreSQL: Transaction Isolation

数据库的隔离级别有四种,分别是 Read uncommitted ,Read committed Repeatable read,Serializable , PostgreSQL 数据库的默认事务隔离级别是 Read committed , 有系统参数可以更改数据库隔离级别。事务隔离级别的特点需要根据以下三种现象来判定:

事务隔离级别

脏读 ( dirty read )

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读 到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的,简单的说,脏读即读到未提交的数据。

不可重复读 ( nonrepeatable read )

不可重复读是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。简单地说,不可重复读即指在一个事务中读到数据不一样,原因是其它会话已经更改了并提交了这些数据。

三幻影读 (phantom read )

幻觉读是指当事务不是独立执行时发生的一种现象,例如 第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

事务隔离级别如下:

PostgreSQL: Transaction Isolation

图一: SQL Transaction Isolation Levels

事务隔离级别参数

default_transaction_isolation (enum)
Each SQL transaction has an isolation level, which can be either “read uncommitted”, “read committed”, “repeatable read”, or “serializable”. This parameter controls the default isolation level of each new transaction. The default is “read committed”.

查看当前事务隔离级别

1
2
3
4
5
skytf=> show default_transaction_isolation;  
default_transaction_isolation
-------------------------------
read committed
(1 row)

Read Committed 事务隔离级别举例

“Read committed”是 PostgreSQL 的默认事务隔离级别,根据图一,”Read committed”可能发生不可重复读 (Nonrepeatable Read), 下面验证一下。

一张测试表,如下:

1
2
3
4
5
6
7
skytf=> select * from test_41;  
id | name
----+------
2 | b
3 | c
1 | a
(3 rows)

事务一

1
2
3
4
5
6
skytf=> begin  
skytf=> select * from test_41 where id=1;
id | name
----+------
1 | a
(1 row)

事务二:修改这行数据

1
2
skytf=> update test_41 set name='aaa' where id=1;  
UPDATE 1

再回到事务一

1
2
3
4
5
skytf=> select * from test_41 where id=1;  
id | name
----+------
1 | aaa
(1 row)

备注:发现在事务一中,两次读到的数据不一样了(红色部分),这就是不可重复读。

REPEATABLE READ 事务隔离级别举例

根据图一,”REPEATABLE READ “ 将不会出现“不可重复读”,下面通过实验验证一下;

表数据

1
2
3
4
5
6
7
skytf=> select * From test_41;  
id | name
----+------
2 | b
3 | c
1 | aaa
(3 rows)

事务一

1
2
3
4
5
6
7
8
9
skytf=> begin;  
BEGIN
skytf=> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
SET
skytf=> select * from test_41 where id=2;
id | name
----+------
2 | b
(1 row)

事务二:修改这行数据

1
2
skytf=> update test_41 set name='bbb' where id=2;  
UPDATE 1

再回到事务一

1
2
3
4
5
skytf=> select * from test_41 where id=2;  
id | name
----+------
2 | b
(1 row)

备注: 将 PostgreSQL 事务隔离级别设置成 “ REPEATABLE READ” 后, “不可重复读”将不再出现。另外,这里是在会话中更改事务的隔离级别,只对当前会话有效,如果修改配置文件是的 default_transaction_isolation 参数,则会影响全局。

附:事务隔离级别设置语法

Name
SET TRANSACTION ― set the characteristics of the current transaction

Synopsis
SET TRANSACTION transaction_mode [, …]
SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, …]
where transaction_mode is one of:
ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
READ WRITE | READ ONLY

总结

今天主要测试了下 “Read committed “ ,”Repeatable read “ 事务隔离级别下的”Nonrepeatable Read “ 特性,有兴趣的朋友可以去测试图二中的其它属性。

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/236410.html

(0)
上一篇 2022年1月24日
下一篇 2022年1月24日

相关推荐

发表回复

登录后才能评论