事务的特性(ACID):
代码语言:java复制1、原子性(Atomicity):事务不可分割(一个事务中的所有操作要么全部执行,要么干脆不执行,不会结束在中间某个环节)
2、一致性(Consistency):事务执行的前后,数据完整性保持一致(在事物开始之前和事物结束以后,数据库的完整性没有被破坏)
3、隔离性(Isolation):并发事物,相互之间不能影响(防止多个事物并发执行时由于交叉执行而导致的数据不一致问题)
4、持久性(Durability):是指事物提交后,数据就永久的保存到数据库(不会因为系统故障而丢失数据)
1、原子性:通过 undo log(回滚日志)来保证的
2、一致性:原子性、隔离性、持久性这三种特性就是为了保证数据库的有一致性
3、隔离性:通过 MVCC(多版本并发控制) 或锁机制来保证的
4、持久性:通过 redo log (重做日志)来保证的
1、原子性:主要依靠undo.log日志实现,即在事务失败时执行回滚。
undo.log日志会记录事务执行的sql,当事务需要回滚时,通过反向补偿回滚数据库状态
2、一致性:就是事务再执行的前和后数据库的状态都是正常的,表现为没有违反数据完整性,参照完整性和用户自定义完整性等等。
原子性、隔离性、持久性这三种特性就是为了保证数据库的有一致性
3、隔离性:我的理解就是多线程时多事务之间互相产生了影响,要避免这个影响,那就加锁。
mysql的锁有表锁,行锁,间隙锁,好像还有一个锁数据库的,叫全局锁还是什么来着。
写写操作通过加锁实现隔离性,写读操作通过MVCC实现
4、持久性:主要依靠redo.log日志实现。
首先,mysql持久化通过缓存来提高效率,即在select时先查缓存,再查磁盘;
在update时先更新缓冲,再更新磁盘。以减少磁盘io次数,提高效率。
但由于缓存断电就没了,所以需要redo.log日志。
在执行修改操作时,sql会先写入到redo.log日志,再写入缓存中。这样即使断电,也能保证数据不丢失,达到持久性
代码语言:java复制1、binlog(归档日志):将执行完的增删改SQL语句的具体操作记录到binlog中,MySQL 自带的日志模块
2、undo_log(回滚日志):支持事务原子性,数据更改前的快照,可以用来回滚数据(记录旧数据)
3、redo_log(重做日志):支持事务持久性,记录修改操作的日志,用来崩溃后的数据恢复(记录新数据),InnoDB 引擎自带了日志模块。
redo_log 采用两阶段提交的方式:
redo_log(prepare):记录新数据,更新redo_log状态为预提交状态。
redo_log(commit):更新redo_log状态为提交状态。
1、原子性:InnoDB依赖undo log 实现原子性(回滚日志,记录旧数据)。
当事务对数据库进行修改时,InnoDB会生成对应的undo log日志。
如果事务执行失败或者调用rollback,导致事务回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子;
undo log 是逻辑日志,记录的是sql执行相关的信息,当发生回滚时,InnoDB会根据undo log的内容做与之前相反的工作:
对于insert,回滚时会执行delete;
对于delete,回滚时会执行insert;
对于update,回滚时会执行一个相反的update;
2、隔离性:依赖的是MVCC或者锁来实现的
MVCC本质依旧是依赖undo log生成版本快照。
3、持久性:InnoDB依赖redo log 来保证(重做日志,记录新数据)。
这里简述下:为了减少与磁盘的交互次数,mysql的更新操作只会更新Buffer Pool(内存)级别。
Buffer Pool中的数据会定时的写入到磁盘中,但是引入了一个新问题?当mysql宕机时,如何保证数据不丢失?
依赖的就是redo log来实现,具体是通过WAL(Write-ahead Logging 预写式日志)来实现,
即先写入日志,在更新到Buffer Pool,以保证系统宕机后可以安全恢复。
mysql的一个update需要经历什么最终持久化到磁盘? ---> 请看 SQL语句的执行流程
2.4 一致性
一致性是事务追求的最终目标,上面说到的原子性、隔离性、持久性都是为了保证数据库状态的一致性。
当然除了数据库层面的保障,一致性的实现也需要应用层面的保障。