1,原子性(Atomicity)
1,实现原理(Undo Log)
- Undo Log 又叫回滚日志,记录的是数据的历史状态
- Undo Log 是追加的,也就是一直会往后面叠加日志的
- 在 InnoDB 存储引擎中,用 Undo Log实现多版本的并发控制(MVCC)
- 在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方被称为 Undo Log),然后进行数据的修改,如果出现了错误或者用户执行了 RollBack 语句,系统可以利用 Undo Log 中的备份将数据恢复到事务开始之前的状态
Undo Log 是逻辑日志,记录了数据行的操作,如下:
Redo Log 又叫前滚日志,记录的是数据的最新状态
- 当数据发生修改时, InnoDB 引擎先将记录写到 RedoLog 中,再更新内存,此时更新完成,之后再去将数据同步到磁盘
- Redo Log 是固定大小和循环写的,当日志满的时候,会将之前记录的日志处理掉(同步到磁盘中)后清理日志腾出空间继续写日志
- 有了 RedoLog,InnoDB 就可以保证即使数据库异常重启,数据也不会丢失,这就是 Crash-Safe
- RedoLog是物理日志,记录了磁盘页的物理更改
参数(innodb_flush_log_at_trx_commit)的值是 0,1,2,决定如何将 Redo Log 的数据同步到磁盘,可修改
以上三种方式中:
- 0 性能最好,但是容易丢数据,不安全
- 1 最安全不易丢数据,但是性能最低
- 2 是折中做法
WAL(Write Ahead Log):提前写日志(在写内存之前先写日志)
3,隔离性(Isolation)
事务具有隔离性,事务之间的执行不应该互相影响,各个事务的执行应该是串行的
但是完全的串行隔离会导致系统并发性能很低,降低对资源的利用率,所以实际上会对隔离性进行一定的放宽,这也会导致数据库的一致性降低
1,隔离性产生的问题
1,脏读
2,不可重复读
在同一个事务中多次获取的数据不一致,第一次获取时别的事务还没提交,第二次获取时别的事务已经提交,导致**两次数据不一致**
3,幻读
和不可重复读类似,不可重复读强调相同的记录值不同,幻读强调多出新的记录
在别的事务还没提交插入数据时本事务读取数据,等别的事务提交之后本事务插入一条主键相同的数据,会报插入失败,明明查询出来的数据没有该主键对应的数据但是插入报错,因为事实上其他事务已经插入了该主键的数据
4,不可重复读和幻读的区别
不可重复读:强调的是同样的记录数据是一致的,而不关心是否有新的记录
幻读:就是读到了新的数据(如果少了数据,就归为不可重复读)
案例:
- 事务1 读取了 A,B 两条记录,事务2 将 A 和 B 的相关字段改掉且提交,事务1再读取 A 和 B 发现有字段值不同,这就是不可重复读
- 事务1 读取出 A,B 两条记录,事务2新插入 C,D 两条记录且提交,事务1再读取发现 A 和 B 的字段值不变,但是多出 C 和 D 两条记录,这就是幻读
事务1 读取出 A,B 两条记录,事务2删除 A 且提交,事务1再读取发现只有 B 了,这是不可重复读,因为 A 的两次查询不一致了(第一次有,第二次没了)
2,事务的隔离级别(通过锁实现)
1,读未提交(READ UNCOMMITED)
2,读已提交(READ COMMITED)
3,可重复读(REPEATABLE READ)(默认)
4,串行化(SERIALIZABLE)
4,一致性(Consistency)
在事务的四个特点中,一致性是事务的根本追求,以下情况会破坏事务的一致性
事务的并发执行
- 事务故障或系统故障
数据库系统通过并发控制技术和日志恢复技术来避免这种情况的发生
- 并发控制技术保证了事务的隔离性,使数据库的一致性不会因为并发执行的操作被破坏
- 日志恢复技术保证了事务的原子性,使一致性不会因为事务或者系统故障而被破坏,同时已提交的对数据库的修改不会因为系统崩溃而丢失,保证了事务的持久性
事务的执行结果必须使数据库从一个一致性状态到另一个一致性状态。一致性状态是指
- 系统的状态满足数据的完整性约束
- 系统的状态反应数据库本应该描述的现实世界的真实状态(比如转账前后两个账户的总额应该不变)