一、数据库事务的意义
数据库事务是为了保证了一系列操作的原子性,并提供从失败中恢复的方法。另外数据库事务保证应用程序之间的隔离,避免事务之间的相互影响。
二、数据库事务的4大特性
- 原子性(Atomicity):事务作为一个整体,要么都执行,要么都不执行。
- 一致性(Consistency):是指事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
- 隔离性(Isolation):多个事务之间不会互相影响。
- 持久性(Durability):一旦事务成功提交,结果永久保存。
三、数据库误读现象
- 脏读:读到了未提交的事务操作的数据,数据有可能是无效的。
- 不可重复读:一个事务两次读之间,被另一事务修改了数据,导致两次读的结果不一致。
- 幻读:由于其他事务的新增、删除等,导致本事务操作不全,比如另一事务插入了一行。
四、事务隔离级别
针对上述误读现象,数据库可以设定事务的隔离级别,隔离级别越高,可出现误读的场景越少,相应地并发能力就越低。
隔离级别从低到高依次为:未提交读(Read uncommitted)、提交读(Read committed)、可重复读(Repeatable reads)、可序列化(Serializable)。
- 未提交读:事务在读数据的时候并未对数据加锁。
- 提交读:事务对当前被读取的数据加 行级共享锁(当读到时才加锁),一旦读完该行,立即释放该行级共享锁;
- 可重复读:事务在读取某数据的瞬间,必须先对其加行级共享锁,直到事务结束才释放;事务在更新某数据的瞬间,必须先对其加行级排他锁,直到事务结束才释放。
- 可序列化:事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放;事务在更新数据时,必须先对其加表级排他锁 ,直到事务结束才释放。
共享锁:用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。
如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。
排他锁:用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。
如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。
五、事务提交过程
1、bin log 、undo log 和redo log
1、undo log
数据库事务失败了怎么回滚?Mysql使用undo log来存储事务提交前的数据,这样在执行回滚时就可以从undo log中取数据。用undo log的事务执行过程简述如下:
1)事务开始;
2)将 a = 1 记录到undo log;
3)修改 a = 2;
4)将undo log 写到磁盘;(如果5失败了,可以依赖4进行回滚)
5)将数据写到磁盘;(5在6前是为了避免写磁盘失败,保证持久化成功)
6)提交事务。
undo log 的缺陷是,每次执行事务要写undo log到磁盘,导致大量磁盘IO,性能很低。
2、redo log
和undo log不一样,redo log存的是新数据的备份,目的是将上述第5步数据持久化的过程替换为redo log的持久化,并且通过优化redo log持久化降低数据IO成本。undo和redo配合使用的过程如下:
1)事务开始;
2)将 a = 1 记录到undo log;
3)修改 a = 2;
4)将 a = 2 记录到redo log;
5)将redo log 写到磁盘;
6)提交事务。
7)数据写入磁盘。
参考资料: