数据库事务
事务是指满足AICD特性的一组操作,通过commit来提交事务,也可以通过RollBack来进行事务回滚。
AICD
- 原子性(Atomicity)
事务被视为不可分割的最小单位,要么成功,要么失败。 - 一致性(Consistency)
数据库在执行事务前后保持一致性,所有事务对一个数据读取结果都是相同的。 - 隔离性(Isolation)
一个事务所做修改,在提交之前是对其他事务不可见的。 - 持久性(Durability)
一旦事务提交,则永久存在数据库中。
- 满足一致性,执行结果才是一样的。
- 满足隔离型和原子性,就一定满足一致性。
- 持久性是将数据持久化,放置数据库崩溃导致数据丢失。
AutoCommit
在MySQL中,默认采用自动提交模式。只要不显式使用START TRANSACTION
语句开始一个事务,每个查询都会当做一个事务自动提交。
数据库并发一致性
在并发环境下,事务隔离性很难保证,因此会出现并发一致性的问题。
丢失修改
两个事务对同一个数据进行修改,后修改的事务会覆盖先修改的事务。
读脏数据
同一个数据,一个事务修改后,另一个事务读取,第一个事务在撤销修改,则第二个事务读取的就是脏数据。
不可重复度
第一个事务读取了数据后,第二个失误对该数据进行修改,此时第一个数据再去读取数据,两次读取结果就不一致。
幻影读
第一个事务读取了一个范围的数据,第二个事务在这个范围内插入数据,此时第一个事务在读取,两次读取结果不一致。
原因与解决
- 并发情况下破坏了事务的隔离性
- 可以通过并发控制来保证事务隔离性
- 可以通过封锁方式保证事务隔离性
- 可以通过事务隔离级别来进行事务隔离性
封锁
用户可以通过封锁来控制并发控制,但是封锁操作需要用户控制,比较复杂。
封锁粒度
- 行级锁
- 表级锁
封锁类型
读写锁
- 互斥锁 - X 锁 - 写锁
- 共享锁 - S 锁 - 读锁
- 一个事务对数据加了X锁,就可对数据进行读取和更新,其他事务不能对A加任何所。
- 一个事务对数据加了S锁,就可对数据进行读取,但不能进行更新。加锁期间,其他事务可以对数据加S锁,但不能加X锁。
意向锁
在存在行级锁和表级所时,事务想对表加锁,则要判断表中所有行是否加锁。十分耗时。因此引入意向锁:IS/IX,意向锁是表级锁。他用来表示该表中,有事务对行数据加了锁。
- 一个事务要获取数据的S锁,则要获取表的IS锁或更强的锁。
- 一个事务要获取数据的X锁,则要获取表的IX锁。
封锁协议
三级封锁协议
一级封锁协议
事务修改数据时必须加X锁,事务结束释放。
解决丢失修改问题,两个事务不能同时修改一个数据。
二级封锁协议
在一级基础上,要求事务读数据时加S锁,读完释放。
解决读脏数据的问题,当有事务对数据修改时加X锁,此时数据无法加S锁读取。
三级封锁协议
在二级基础上,要求读取数据时必须加S锁,事务结束后释放。
可以解决不可重复读的问题,事务读取数据时,其他事务不能对数据加X锁修改。
两段封锁协议
加锁和解锁在两个阶段执行
MySQL隐式与显示锁定
隐式锁定
Mysql 的 InnoDB存储引擎采用两段锁协议,会根据隔离级别在需要的时候自动加锁,并且所有的锁在同一时刻(执行commit和rollback时)被释放。
显式锁定
InnoDb会根据事务的隔离级别在需要的时候自动加锁,InnoDb也可以通过特定的语句进行显式锁定(不属于SQL规范)
SELECT ... LOCK In SHARE MODE;
SELECT ... FOR UPDATE;
事务隔离级别
未提交读
事务中的修改,即使没有提交,对其他事务也是可见的。
提交读
与未提交读相反,事务的修改,没有提交,对其他事务是不可见的。
可重复读
保证在同一个事务中的多次读取同一数据结果是一样的。
可串行化
强制事务串行执行,多个事务互不干扰。需要通过加锁实现,锁机制保证同一时间只有一个事务执行,也就保证了事务串行。
多版本并发控制 - MVCC
多版本并发控制是MySQL的InnoDb存储引擎实现隔离级别的具体方式。
实现:
- 提交读
- 可重复读。
- 未提交读总是读取最新的数据行,无需使用MVCC
- 可串行化需要对读取的行加锁,单使用MVCC无法实现。
存储引擎
数据库存储是数据库底层软件组织,用于为数据库提供增、删、查、改等操作。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能。Mysql的核心就是存储引擎
可以通过SHOW ENGINES
来查询数据库的存储引擎,Mysql默认的存储引擎是InnoDB
。
InnoDB
InnoDB是事务型数据库的首选引擎,支持行锁定和外键。
- 支持事务、行锁、表锁、外键。
- 5.6.4之前不支持全文索引,5.6.4开始支持全文索引。
- 主键索引是聚集索引。
- 默认使用B+Tree,叶子节点存放了主键和行记录。也有Hash索引和全文索引。
名词解释:
- 全文索引:先创建索引,再对索引进行搜索。
- 聚集索引:数据行的物理顺序与列值的逻辑顺序相同,即一块地址内存中,物理地址在前面的那行数据,在表中也在前面。
Next-Key Locks
Next-Key Locks是MySQL中InnoDB存储引擎的一种锁实现。
Next-Key Locks是Record Locks和Gap Locks的结合,不仅锁定索引,也锁定索引之间的间隙。
- Record Lock : 锁定记录索引,而不是记录本身。如果表没有索引,则会在主键上自动创建隐藏索引
- Gap Lock : 锁定索引之间的间隙,而不是索引本身
MyISAM
- 不支持事务,外键。在Web、数据仓储环境下常用。
- 插入、查询速度较高。
- 支持所表,支持全文索引
- 并发性能差,崩溃后无法恢复
- 主键是非聚集索引,叶子节点值存储主键和对应数据地址
Memory
- 内存存储,使用Hash索引,数据不经过磁盘IO,速度最快。
- 一般用于存储保存中间结果数据
总结
- 数据库事务是满足AICD特性的一组数据库操作。
- 并发情况由于不能满足AICD会出现的问题(4种):
- 丢失修改
- 读脏数据
- 不能重复读
- 幻影读
- 如何在并发情况下满足AICD(两种):
- 封锁(开销大):
- 封锁类型(2种):
- 读写锁 S/X锁
- 意向锁 IS/IX锁
- 封锁协议(2类)
- 三级封锁协议
- 两段封锁协议
- 封锁类型(2种):
- 事务隔离(常用,4种)
- 未提交读
- 提交读
- 可重复读
- 可串行化
- 封锁(开销大):
- 数据库引擎 -> 常用的数据库引擎(3种):
- InnoDB -> MySQL默认引擎,支持外键、事务、锁、索引
- MyISAM -> 不支持外键、事务,只有表锁,支持全文索引
- Memory -> 内存存储,Hash索引,速度快