[db:标题]

摘要:MySQL的InnoDB引擎下更新操作时事务的执行过程?什么是脏读、幻读、不可重复读?MySQL中的事务隔离级别?MySQL的InnoDB引擎是如何解决脏读、幻读、不可重复读?
MySQL的InnoDB引擎下更新操作时事务的执行过程 MySQL数据库在InnoDB中一次update的操作过程基本如下: 首先将数据加载到Buffer Pool里:当InnoDB需要更新一条记录时,首先会在Buffer Pool中查找该记录是否在内存中。若没在内存中,则从磁盘读取该页到Buffer Pool中。 记录UndoLog:在修改操作前,InnoDB会在Undo Log中记录修改前的数据。Undo Log是用来保证事务原子性和一致性的一种机制,用于在发生事务回滚等情况时,将修改操作回滚到修改前的状态,以达到事务的原子性和一致性。Undo Log 首先写入内存中的 Undo 缓冲区,随后由后台线程定期刷盘,无需等待事务提交。。 在Buffer Pool中更新数据:当执行update语句时,InnoDB会先更新已经读取到Buffer Pool中的数据,而不是直接写入磁盘。同时,InnoDB会将修改后的数据页状态设置为"脏页"(DirtyPage)状态,表示该页已经被修改但尚未写入磁盘。 记录RedoLog Buffer:InnoDB在Buffer Pool中记录修改操作的同时,InnoDB会先将修改操作写入到Redo Log Buffer 中。 提交事务:在执行完所有修改操作后,事务被提交。在提交事务时,InnoDB会将Redo Log写入磁盘,以保证事务持久性(commit 时会保证 write+fsync,但 log buffer 中的内容可能在 prepare 阶段就已被后台线程提前刷盘)。 写入磁盘:在提交后,InnoDB会将Buffer Pool中的脏页写入磁盘,以保证数据的持久性。但是这个写入过程并不是立即执行的,是有一个后台线程异步执行的,所以可能会延迟写入,总之MySQL会选择合适的时机把数据写入磁盘做持久化。 记录Binlog:在提交过程中,MySQL Server层将事务提交的信息记录到Binlog中。Binlog是MySQL用来实现主从复制的一种机制,用于将主库上的事务同步到从库上。在Binlog中记录的信息包括:事务开始的时间、数据库名、表名、事务ID、SQL语句等。 什么是脏读、幻读、不可重复读 在整个事务的执行过程中,当出现并发、以及兼顾性能等情况,会出现一系列的问题,但是针对不同的情况,MySQL 也给出了针对性方案。下面就针对脏读、幻读、不可重复读三种异常情况来说明一下。 脏读 脏读是指读到了其他事务还没提交的数据。 脏读产生的过程是当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交(commit)到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。 不可重复读 不可重复读是指在对某数据进行读取过程中,有其他事务对数据进行了修改(UPDATE、DELETE),导致第二次读取的结果不同。 不可重复读的发生过程,在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。 幻读 幻读是指事务在做范围查询过程中,有另外一个事务对范围内新增了记录(INSERT),导致范围查询的结果条数不一致。 幻读也常被看作不可重复读在‘范围查询’场景下的特殊表现 例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中符合条件的的“全部数据行”。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入"一行新数据"。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。 MySQL中的事务隔离级别 脏读、幻读、不可重复读这三种异常情况,产生的主要原因还是由于数据库支持多个事务同时执行时,互相操作相同的数据。那么事务之间能看到哪些数据呢? 这就是由数据库的事务隔离级别来决定的。 事务隔离级别,主要用于定义事务处理过程中,不同事务之间可见性和相互影响程度的一套标准。 业内标准SQL-92(也叫 SQL2)是 ANSI/ISO 在 1992 年发布的第二版 SQL 标准,它对 1986 年的 SQL-86 做了大幅扩充,奠定了今天主流关系数据库(Oracle、DB2、SQL Server、PostgreSQL、MySQL 等)所支持的核心功能。
阅读全文