ACID
- Atomicity 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- Consistency 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- Isolation 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- Durability 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
隔离级别
- 未提交读 Read Commited:可能发生脏读(一个事务读取到了另一个事务未提交的数据修改)
- 提交读 Read Commited:可能发生不可重复读(一个事务内因为另一个事务的修改两次读取的数据不同)
- 可重复读 Repeated Read:可能发生幻读(一个事务发现了另一个事务的插入数据)
- 串行化 Serializable
| 隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
|---|---|---|---|
| 未提交读(Read uncommitted) | 可能 | 可能 | 可能 |
| 已提交读(Read committed) | 不可能 | 可能 | 可能 |
| 可重复读(Repeatable read) | 不可能 | 不可能 | 可能 |
| 可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
- 不可重复读:update&delete
- 幻读:insert
锁
数据库遵循的是两段锁协议,将事务分成两个阶段,加锁阶段和解锁阶段
- 加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁(共享锁,其它事务可以继续加共享锁,但不能加排它锁),在进行写操作之前要申请并获得X锁(排它锁,其它事务不能再获得任何锁)。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
- 解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。
- 提交读:数据读取不加锁,数据的写入、修改和删除是需要加锁。事务对操作的数据(写入、修改和删除)加行锁,另一个事务无法拿到行锁直至超时
- 可重复读:事务第一次读取到数据后,就将这些数据加锁,其它事务无法修改这些数据。但无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会发现之前没有的数据,这就是幻读。
- 乐观锁:基于数据版本记录机制实现。在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
- 悲观锁:为了保证事务的隔离性,就需要一致性锁定读。读取数据时给加锁,其它事务无法修改这些数据。修改删除数据时也要加锁,其它事务无法读取这些数据。
- MVCC:数据添加事务的版本号,操作时检查版本号
引擎
- MyISAM
- 不支持事务
- 只支持表锁
- 保存表的总行数
- 大量SELECT性能更佳
- InnoDB
- 支持事务、外键
- 支持表锁、行锁(Where主键有效)
- 不保存表的总行数
- 大量INSERT或者UPDATE性能更佳
索引
索引增加了数据库存储空间,插入修改时花费更多时间修改索引
- 聚集索引:索引的逻辑顺序与数据库物理顺序相同,聚集索引查找到需要的数据
- 非聚集索引:索引的逻辑顺序与数据库物理顺序不相同,非聚集索引查找到记录对应的主键
- B树或者B+树实现
- 查找次数少
- 利用磁盘读取特性