POSTGRESQL 通过例子来验证POSTGRESQL 的序列化

2021-01-12 00:00:00 数据 数据库 操作 事务 进程



隔离级别是有一套理论的,在每种数据库中,实现的方式不同,实现的结果也不同,近会有几期的文字对不同的数据库的隔离级别探探究竟。


传统数据库中的隔离级别是配合MVCC 多版本控制来完成读取不会阻塞写,在任意时刻,每个事务都能看到读取当时数据的快照,避免数据发生变化后,事务在整个流程中看到的数据是不同的.


实际上每种数据库的在MVCC的中如何完成都有自己的形成的原理, 今天通过POSTGRESQL 来验证POSTGRESQL 中的序列 Serializable 在数据库操作中是什么样子.


我们先调整POSTGRESQL 的数据库到序列化的模式.


1  通过POSTGRESQL 中的参数调整,然后重新RELOAD系统

2  通过SESSION 的方式控制当前的访问的进程为序列化


下面我们采用种方式,把default_transaction_isolation 制为 'serializable'



我们建立一个数据库test

然后建立一个表

CREATE TABLE employee

(id INTEGER

, name VARCHAR(50)

);

INSERT INTO employee (id,name)

VALUES

(1,'anvesh'),(2,'neevan')

,(3,'roy'),(4,'martin');


然后我们打开三个进程,A B C ,分别在每个进程下执行如下命令

SESSIONA

BEGIN TRANSACTION ISOLATION LEVELSERIALIZABLE;

 

UPDATE employee SET Name ='varlin' WHERE id=4;

 

SELECT * FROM employee;

 

 

SESSION B

 

UPDATE employee SET name ='Loother' WHERE id=3;

 

SESSION C

 

INSERT INTO Employee (id,name) VALUES (5,'mahi');

 

SELECT * FROM employee;

 

SESSION A

 

SELECT * FROM employee;


结果和序列化的定义预期是一致的


SESSION A 只能看到自己在事务定义时刻的数据,以及对那一个时刻的数据的改变,SESSION B  SESSION C  也可以到底自己执行命令时刻以及改变数据时刻后的数据的变化.  


SESSION A 

SESSION B


SESSION C 

 

但注意此时的SESSION A  SESSION B  SESSION C  之间并没有冲突,因为互相并未干涉同一行数据.


此时我们将SESSION B 的操作在SESSION A 中操作. 我们得到一个错误



2021-02-09 06:22:25.477 EST [33403] ERROR:  could not serialize access due to concurrent update

2021-02-09 06:22:25.477 EST [33403] STATEMENT:  UPDATE employee SET name ='Loother' WHERE id=3;

ERROR:  could not serialize access due to concurrent update



通过上图我们捋一捋, 实际上如果每个进程炒作的数据之间没有关系,则序列化的隔离级别不会影响每个进程的操作, 而如果进程之间操作的数据是同一行数据,则序列化的问题就出现了.


SESSION A 中的 ID = 3 的一行的数据变化必须按照时间的序列的要求,需要在退出事务后,才能进行,也就是说以事务为单位,每行数据具有时间顺序操作的需要.


我们通过下面的例子,在此验证上面的假设


我们分别在SESSION A  B C ,三个进程, 依次的执行 

update employee set name = 'siome' where id = 1;   A

update employee set name = 'siome' where id = 1;   B

update employee set name = 'siome' where id = 1;   C


SESSION A 我们可以清晰的看到 SESSION B  SESSION C 在执行中报错

SESSION B  SESSION C  即使在SESSION A  COMMIT 后, COMMIT 也只能进行回滚.

SESSION B


通过上的例子可以验证在序列化中,如果一个事务占有了某个一个行,则其他进程的事务是无法对这个行进行任何DML 的操作的.



相关文章