恩墨学院 PostgreSQl 的PGCE+PGCA 认证考试 课程

Postgres的数据安全

4.6.1.1ACID

指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。

1、原子性(Atomicity

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

链接: https://pan.baidu.com/s/10hEalY5Aarpdnrv8mNBpSQ 

提取码: zukg 

2、一致性(Consistency

事务必须使数据库从一个一致性状态变换到另外一个一致性状态。

3、隔离性(Isolation

事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

4、持久性(Durability

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

4.6.1.2 事务系统

为了保证数据操作的ACID特性在数据库中引入事务,在PostgreSQL系统中,通过事务快俩实现数据库内部底层事务和终端命令的交互,一个事务块包含多个事务(PostgreSQL中的事务表示与命令相对应的事务)。

1、  事务块的操作

在PostgreSQL中,任何语句的执行都是通过事务块的入口函数进入并执行的,执行完毕后,通过事务块的出口函数退出,当系统执行中遇到错误时,会通过事务块出错处理函数完成相关的出错处理。用户也可以通过BEGIN/END/ROLLBACK等命令来改变事务块的状态,PostgreSQL针对每一个能改变事务块状态的命令提供了单独的函数。

StartTransactionCommand在每条语句执行前调用,它的作用是通过判断当前事务块的状态进入不同的底层事务执行函数中,它是进入事务处理模块的入口函数。在每条语句执行后调用CommitTransactionCommand,同StartTransactionCommand一样根据当前事务块的状态决定下一步的事务操作。AbortCurrentTransaction则在系统遇到错误时调用,也是根据当前事务块的状态决定下一步的事务操作,调用时可能进行事务退出或者事务清理操作。

事务块状态改变函数主要包括BeginTransactionBlock、EndTransactionBlock和UserAbortTransactionBlock,他们的功能主要是根据用户输入的改变事务状态的命令以及系统本省的状态来改变事务块的状态。执行BEGIN命令,调用函数BeginTransactionBlock完状态改变,系统会进入一个事务块。执行END命令,会调用EndTransactionBlock函数,该函数指示一个事务块的结束。函数UserAbortTransactionBlock用于执行用户提交的一个ROLLBACK命令。这三个函数都只是改变事务块状态,并没有做实际的事务操作。


1、 两阶段提交

PostgreSQL使用两阶段提交来支持分布式数据库的事务处理,PostgreSQL只是支持分布式数据库中的两阶段提交协议,即给其提供了相关的操作接口,但没有实现整个协议,两阶段的整个流程是由编程者在应用程序中保证的。

1)、预提交阶段

  a、对于分布式事务,某一个事务所在的数据库管理系统会选择成为“协调者”。协调者在本地开始一个分布式事务,并且向其他数据库管理系统发送“Prepare”消息。发送消息时,会使用专门的事务ID(GID)来标识此分布式事务。这样数据库管理系统之间可以确定需要同步执行的事务。

  b、其他数据库管理系统收到“Prepare”消息后,会试图开始一个本地事务以完成分布式事务的功能。它自行巨鼎这个事务是提交还是终止,然后把它的决定发送该协调者。

  c、如果数据库决定提交上述的一个本地事务,它就进入“预提交”阶段。在此阶段,如果协调者没有发送终止的消息,它不能终止这个本地事务。

  d、如果数据库决定终止这个事务,他会向协调者发送取消的信息。然后由协调者进行全局性的取消动作。

         在预提交阶段,各个分布式数据库系统将检查当前各自事务的情况,试图保证这个本地事务如果执行,就不会被终止。即使因系统出错而需要进行系统恢复,与这个事务相关的恢复操作也是应该Redo而不是Undo。

2)全局提交阶段

       a、如果协调者没有收到消息,就默认收到了“取消”消息。如果其他数据库返回给协调者的消息都是“Ready”,协调者将提交这个分布式事务,然后把“Commit”消息发送给其他数据库。如果协调者收到一条“取消”消息,则取消这个分布式事务,然后发送消息进行全局性的取消动作。

  b、本地数据库根据协调者的消息,对本地事务进行COMMIT或者ABORT操作,在这个阶段,各个分布式数据库系统将进行事务的实质提交或者退出操作。

3PostgreSQL的并发控制

         PostgreSQl利用多版本并发控制(MVCC)来维护数据的一致性,每个事务看到的都只是一段时间之前的数据快照。这样,如果对每个数据库会话进行事务隔离,就可以避免一个事务看到其他并发事务的更新而导致不一致的数据。因为MVCC并不能解决所有的并发控制情况,所以还需要使用传统数据库中的锁机制来保证事务的并发。另外,PostgreSQL还提供了会话锁机制,利用它可以扩大锁的使用范围,即一次对某个对象加锁可以保证对于多个事务都有效。

SQL标准考虑了三个必须在并行事务之间避免的现象:

  1)、脏读: 指一个事务读取了另外一个事务未提交的数据。

    这是非常危险的,假设A向B转帐100元,对应sql语句如下所示:

    1.updateaccount set money=money+100 while name=‘b’;   

    2.updateaccount set money=money-100 while name=‘a’;

    当第1条sql执行完,第2条还没执行(A未提交时),如果此时B查询自己的帐户,就会发现自己多了100元钱。如果A等B走后再回滚,B就会损失100元。

  2)、不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同。

    例如银行想查询A帐户余额,第一次查询A帐户为200元,此时A向帐户存了100元并提交了,银行接着又进行了一次查询,此时A帐户为300元了。银行两次查询不一致,可能就会很困惑,不知道哪次查询是准的。

     和脏读的区别是,脏读是读取前一事务未提交的脏数据,不可重复读是重新读取了前一事务已提交的数据。

  3)、幻读:是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

     如丙存款100元未提交,这时银行做报表统计account表中所有用户的总额为500元,然后丙提交了,这时银行再统计发现帐户为600元了,造成虚读同样会使银行不知所措,到底以哪个为准。

为了避免出现这三种现象,SQL标准定义了4个事务隔离级别:

  1)、读未提交(Read Uncommitted):SELECT语句以非锁定方式被执行,所以有可能读到脏数据,隔离级别最低。

  2)、读已提交(Read Committed):postgresql里的缺省隔离级别。只能读取到已经提交的数据。即解决了脏读,但未解决不可重复读。

3)、可重复读(Repeated Read):在同一个事务内的查询都是事务开始时刻一致的,InnoDB的默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻读。

4)、可串行化(Serializable):它提供最严格的事务隔离。完全的串行化读,所有SELECT语句都被隐式的转换成SELECT ... LOCK IN SHARE MODE,即读取使用表级共享锁,读写相互都会阻塞。隔离级别最高。

隔离级别脏读不可重复读幻读

读未提交可能可能可能

读已提交不可能可能可能

可重复读不可能不可能可能

可串行读不可能不可能不可能

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容