ACID特性
在关系型数据库管理系统中,一个逻辑工作单元要成为事务,必须满足4个特性,即所谓的ACID
原子性 Atomicity
事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行
每一个写事务,都会修改BufferPool,从而产生相应的Redo/Undo日志,在BufferPool中的页被刷到磁盘之前,这些日志信息都会先写入到日志文件中,如果BufferPool中的脏页没有刷成功,此时数据库挂了,那在数据库再次启动之后,可以通过Redo日志将其恢复出来,以保证脏页写的数据不会丢失。如果脏页刷新成功,此时数据库挂了,就需要通过Undo来实现了
一致性 Consistency
指的是事务开始之前和事务结束之后,数据库的完整性限制未被破坏。
一致性包括两方面的内容
约束一致性
创建表结构时所指定的外键、Check、唯一索引等约束,MySQL不支持Check
数据一致性
是一个综合性的规定,因为它是原子性、持久性、隔离性共同保证的结果,而不是单单依赖于某一种技术
一致性可以理解为数据的完整性,它是通过原子性、隔离性、持久性来保证的,而这3个特性又是通过Redo/Undo来保证的
逻辑上的一致性,包括唯一索引、外键约束、Check约束,这属于业务逻辑范畴
隔离性 Isolation
指的是一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对其他的并发事务是隔离的
InnoDB支持的隔离性有4种,隔离性由低至高分别为:读未提交、读提交、可重复读、可串行化
锁和多版本控制(MVCC)技术就是用于保障隔离性的
持久性 Durability
指的是一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,后续的操作或故障不应该对其有任何影响,不会丢失
MySQL一个“提交”动作触发的操作有,它们都是数据库保证其数据完整性、持久性的手段
binlog落地
发送binlog
存储引擎提交
flush_logs
check_point
事务提交标记
MySQL的持久性与WAL技术相关,redo_log在系统Crash重启之类的情况时,可以修复数据,从而保障事务的持久性
通过原子性可以保证逻辑上的持久性,通过存储引擎的数据刷盘可以保证物理上的持久性
ACID中有3个与WAL有关系,都需要通过Redo、Undo日志来保证
WAL:Write-Ahead Logging,先写日志,在写磁盘
事务隔离级别
MySQL数据库系统提供了4种隔离级别
读未提交
Read UnCommitted,所有事务都可以看到其他未提交事务的执行结果
解决了回滚覆盖类型的更新丢失,但可能发生脏读现象,也就是可能读取到其他会话中未提交事务修改的数据
已提交读
Read Committed,一个事务只能看到其他事务已提交的数据
解决了脏读,但可能发生不可重复读,即一个事务中两次查询结果不一致
大多数数据库系统的默认隔离级别(非MySQL默认)
可重复读
Repeatable Read,确保同一事务的多个实例在并发读取数据时,会看到同样的数据行
解决了不可重复读,理论上会出现幻读,InnoDB通过MVCC机制解决了该问题
MySQL默认事务隔离级别
可串行化
Serializable,所有增删改查串行执行。强制事务排序,使之不可能互相冲突
这个级别可能导致大量的超时现象和锁竞争,效率低下
最高的隔离级别
数据库的事务隔离级别越高,并发问题就越小,但并发处理能力越差
RU隔离级别最低,并发问题多,但并发处理能力好
对不可重复读和幻读并不敏感,更多关心并发处理能力,可以使用RC隔离级别
隔离级别和锁
事务隔离级别是SQL92定制的标准,详单与事务并发控制的整体解决方案,本质上是对锁和MVCC使用的封装,隐藏了底层细节
锁是数据库实现并发控制的基础,事务隔离性是采用锁来实现,对相应操作加不同的锁,就可以防止其他事务同时对数据进行读写操作
对用户来说,首先选择使用隔离级别,当选用的隔离级别不能解决并发问题或需求时,才有必要在开发中手动的设置锁
关系
RC级别
读操作需要加S锁,但是查询语句执行完以后立即释放S锁
RR级别
读操作需要加S锁,但是事务提交之前并不释放S锁,必须等事务结束才释放
Serializable
会在RR级别基础上,添加一个范围锁,保证一个事务在两次查询时结果相同
默认
MySQL:RR
Oracle、SQLServer:RC
一般使用时,建议采用默认隔离级别,然后存在的一些并发问题,可以通过悲观锁、乐观锁等实现处理
控制
查看
show variables like ‘%isolation%’;
select @@tx_isolation;