目录
acid
atomicity
consitency
isolation
durability
隔离级别
当数据库中有多个事务同时执行时,就可能出现脏读(dirty read),不可重复读(non-repeatable read),幻读(phanton read)的问题。为了解决这些问题,引入了隔离级别概念。
- 未提交读:一个事务未提交时,他做的变更可以被其他事务看到,会导致脏读(dirty read)(性能不会比其他级别好多少)
- 提交读:一个事务提交之后,做的变更可以被其他事务看到
- 可重复读:一个事务执行过程中看到的数据,总是跟这个事务启动时看到的数据是一致的。(再可重复读的隔离级别下,未提交变更对其他事务也是不可见)
- 串行化:读写都会加锁。当出现读写锁冲突,后访问的事务必须等前一个事务执行完,才能继续执行。
实现:数据库会创建一个视图,访问的时候以视图逻辑结果为准。
可重复读隔离级别下,这个视图时再每个sql语句开始时创建。
读提交隔离级别这个视图时再sql语句开始执行时创建的。
读未提交直接返回记录的最新值,没有视图概念
串行隔离级别直接加锁避免并发访问
事务隔离的实现
实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。
innodb的多版本并发控制
通过在每行记录后面保存两个隐藏的列来实现(一个是创建时间,一个保存行的过期时间或删除时间,系统版本号,非实际时间)
repeatable read隔离级别下,mvcc的具体操作
- select
- innodb只查找版本早于当前事务版本的数据行(行的系统版本号小于或等于事务的系统版本号)保证事务读取的行要么在事务开始前就已经存在的,要么就是事务自身插入或修改过的
- 行的删除版本要么未定义,要么大于当前事务版本号。可以确保事务读取到的行,在事务开始之前未被删除
- insert
- 为新插入的每行保存当前系统版本号作为行版本号
- delete
- 为删除的每行保存当前系统版本号作为删除标识
- update
- innodb为插入一行新纪录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为删除标识