Transaction事务

** Transaction & ACID **

在对数据库的常规操作过程中,我们一般希望一组操作要么全部成功,要么全部失败,不希望出现一部分成功,一部分失败的情况(可能导致数据的混乱,较难纠正); 在RDBMS中,这种一组操作叫做Transaction,Transaction拥有ACID的特性,详情如下:

    1、原子性(atomicity): 事务必须以一个整体单元的形式进行,这一组操作(SELECT、UPDATE、DELETE、INSERT等),要么全部进行完毕,要么全部不执行,如果异常中断就需要进行全部的回退操作;

    2、一致性(consistency): 事务在结束时,数据必须全部处于相同版本(保持一致的状态,并非所有数据都相同,而是版本相同,例如2018-04-03 12:00:03完成了一组Transaction,那么所有被操作的数据结束时都应该是操作完毕时的数据,而不是部分数据中间状态或者以前的状态)

    3、隔离性(isolation): 事务查看数据时的状态,数据并不会处于某事务的中间状态,要么为另一个事务修改它之前的状态,要么是另一个事务修改它之后的状态;

    4、持久性(durability): 事务完成之后,应该永久存储数据,不会因为数据库宕机而消失或者改变;

在PostgrelSQL中,通过MVCC来维护数据的一致性的,相比于锁定模型,MVCC的优点是Read Lock和Write Lock之间之前是不会阻塞的,在PG中提供了表级别和行级别锁定语句;

** 事务隔离级别 **

Transaction Isolation有以下4个级别:

    1、READ UNCOMMITTED

    2、READ COMMITTED

    3、REPEATABLE READ

    4、SERIALIZABLE

要了解这4个隔离级别,我们得先了解三种不一致的情况:

    1、脏读: 一个事务读取了另一个未提交事务写入的数据,如果发生脏读,数据一致性控制上会出现很大问题;

    2、不可重复读: 你开始了一次银行卡余额的查询, 此时余额是10,000元,这时候,你的女朋友购置了800元的日常用品以及一支YSL(直男只知道YSL了)的口红,你再查询的时候(本次操作还未结束,只是在这组操作再查询一次而已),余额变成了9,200元, 这就是不可重复读;

    3、幻影读(幻读):一个事务开始后,需要更新一批数据,更新后重新查询数据发现仍然存在一些未被修改的数据(因为是新插入);

    例如: 

--Session 1:
mydb# SELECT id,name,loc FROM t_name
      WHERE name = 'NiuJinlin';
  id  |  name      |  LOC
  ---------------------------
  1   |  NiuJinlin |  BeiJing
  2   |  NiuJinlin |  ShangHai
  3   |  NiuJinlin |  Shenzhen
(3 rows)

--Transaction 1(Session 1):
mydb# UPDATE t_name SET loc = 'UNKNOW'
      WHERE name = 'NiuJinlin';

--Transaction 2(Session 2):
mydb# INSERT INTO t_name VALUES (4,'NiuJinlin','England');
mydb# COMMIT;

--Session 1:
mydb# SELECT ID,NAME,LOC FROM T_NAME
      WHERE NAME = 'NiuJinlin';
  id  |  name      |  LOC
  ---------------------------
  1   |  NiuJinlin |  UNKNOW
  2   |  NiuJinlin |  UNKNOW
  3   |  NiuJinlin |  UNKNOW
  4   |  NiuJinlin |  England
(3 rows)


隔离级别

脏读

不可重复读

幻读

READ UNCOMMITTED

✔️

✔️

✔️

READ COMMITTED


✔️

✔️

REPEATABLE READ



✔️

SERIALIZABLE




在PostgreSQL 9.1之前的版本中,仅仅支持READ COMMITTED和SERIALIZABLE,之后的版本可以支持REPEATABLE READ,但是READ UNCOMMITTED事实上仍然不可以支持脏读;