浅谈数据库事务

一、事务的定义

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。

二、事务的特征

原子性:保证事务中的所有操作全部执行或全部不执行。例如执行转账事务,要么转账成功,要么失败。成功,则金额从转出帐户转入到目的帐户,并且两个帐户金额将发生相应的变化;失败,则两个账户的金额都不变。不会出现转出帐户扣了钱,而目的帐户没有收到钱的情况。


一致性:保证数据库始终保持数据的一致性——事务操作之前是一致的,事务操作之后也是一致的,不管事务成功与否。如上面的例子,转账之前和之后数据库都保持数据上的一致性。


隔离性:多个事务并发执行的话,结果应该与多个事务串行执行效果是一样的。显然最简单的隔离就是将所有事务都串行执行:先来先执行,一个事务执行完了才允许执行下一个。但这样数据库的效率低下,如:两个不同的事务只是读取同一批数据,这样完全可以并发进行。为了控制并发执行的效果就有了不同的隔离级别。下面将详细介绍。


持久性:持久性表示事物操作完成之后,对数据库的影响是持久的,即使数据库因故障而受到破坏,数据库也应该能够恢复。通常的实现方式是采用日志。

扫描二维码关注公众号,回复: 1289423 查看本文章

三、为何引入事务

1、数据完整性   

2、数据安全性   

3、充分利用系统资源,提高系统并发处理的能力

四、为什么需要对事务并发控制

更新丢失Lost update:两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。


脏读Dirty Reads:一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能所有的操作都被回滚。


不可重复读Non-repeatable Reads:一个事务对同一行数据重复读取两次,但是却得到了不同的结果。
二次更新问题Second lost updates problem:无法重复读取的特例。有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。


不可重复读Phantom Reads:事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另外一个事务插入数据造成的。

五、数据库的隔离级别

为了兼顾并发效率和异常控制,在标准SQL规范中,定义了4个事务隔离级别,事务准备接受不一致数据的级别称为隔离级别。隔离级别是一个事务必须与其它事务进行隔离的程度。较低的隔离级别可以增加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。应用程序要求的隔离级别确定了所使用的锁定行为:


Read Uncommitted:直译就是"读未提交",意思就是即使一个更新语句没有提交,但是别的事务可以读到这个改变.这是很不安全的.


Read Committed:直译就是"读提交",意思就是语句提交以后即执行了COMMIT以后别的事务就能读到这个改变.


Repeatable Read:直译就是"可以重复读",这是说在同一个事务里面先后执行同一个查询语句的时候,得到的结果是一样的.


Serializable:直译就是"序列化",意思是说这个事务执行的时候不允许别的事务并发执行.

六,隔离级别与锁

隔离级别越高越能保证数据完整性和一致性,但是对并发性能影响也越大。
对于多数应用程序,可以优先考虑把数据库系统隔离级别设为Read Committed ,它能够避免脏读取而且具有较好并发性能。
尽管它会导致不可重复读、虚读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制 。
锁(Lock) 是在多用户环境下对资源访问的一种限制。机制当对一个数据源加锁后,
此数据源就有了一定的访问限制。我们就称对此数据源进行了“锁定”。
为了处理这些问题,SQL标准定义了以下几种事务隔离级别
READ UNCOMMITTED 幻想读、不可重复读和脏读都允许。
READ COMMITTED 允许幻想读、不可重复读,不允许脏读
REPEATABLE READ 允许幻想读,不允许不可重复读和脏读
SERIALIZABLE 幻想读、不可重复读和脏读都不允许


Oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。所以Oracle不支持脏读
SQL标准所定义的默认事务隔离级别是SERIALIZABLE,但是Oracle 默认使用的是READ COMMITTED
设置隔离级别使用 SET TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]

猜你喜欢

转载自fred-han.iteye.com/blog/1893981