事务的基本定义
事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。
事务的属性
谈到事务一般都是以下四点属性:
- 原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 一致性(Consistency)
事务前后数据的完整性必须保持一致。
- 隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
- 持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
事务的隔离级别
事务的隔离是为了解决多事务执行过程中产生的脏读、不可重复读、幻读等问题。
事务从低到高的四种隔离级别(其中隔离级别越严格,安全性越高,但数据库的并发性能也就越低):
- Read Uncommitted(读未提交)
一个事务可以读取另一个未提交事务(有修改操作)的数据。会出现脏读。
- Read committed(读已提交)[比较常见]
一个事务要等另一个事务(有修改操作)提交后才能读取数据。若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。
但是会出现不可重复读问题:一个事务范围内两个相同的查询(查询间隔中另一个事务对查询的内容进行了修改)却返回了不同数据,这就是不可重复读。
- Repeatable read(可重复读)
在开始读取数据(事务开启)时,不再允许修改操作。可避免脏读、不可重复读情况发生。
不可重复读问题对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。
- Serializable(串行化)[比较少见]
Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
隔离的实现
隔离的实现主要有读写锁和MVCC(Multi-Version Concurrency Control)多版本并发处理方式。
-
读写锁
最简单直接的的事务隔离实现方式,每次读操作需要获取一个共享锁,每次写操作需要获取一个写锁。共享锁之间不会产生互斥,共享锁和写锁之间、以及写锁与写锁之间会产生互斥。当产生锁竞争时,需要等待其中一个操作释放锁后,另一个操作才能获取到锁。
-
MVCC
在读写锁中,读和写的排斥作用大大降低了事务的并发效率,于是人们又提出了能不能让读写之间也不冲突的方法,就是读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了。不同的事务session会看到自己特定版本的数据,即使其他的事务更新了数据,但是对本事务仍然不可见,本事务看到的数据始终是第一次查询到的数据。在数据库中,这个快照的处理方式叫多版本并发控制(Multi-Version Concurrency Control)。这种方式真正实现了非阻塞读,只有在写操作时才需要加行级锁,因此并发效率更高。
操作事务
-
手工开启
begin 或者 start transaction
-
事务的提交和回滚
commit # 提交 rollback # 回滚
-
设定事务是否自动开启
set session autocommit = on/off