MySQL中的一个表,表的创建语句如下,使用的是InnoDB引擎。
create table T(ID int primary key, c int);
对于下列这样一条更新语句,MySQL进行了哪些操作?
update T set c = c+1 where ID = 2;
- 使和这个表有关的查询缓存失效。
- 开启事务,根据索引选择,选择使用ID索引,经过B+树的查找算法,找到ID=2的这一行,判断该行是否在内存中。如果在内存中,直接到下一步;如果不在,那么尝试将该行数据所在的数据页读入到内存中。
- 若此时内存空间不足,根据LRU(最近最少使用)算法对选择一张数据页换出,根据数据页的LSN值,与redo log中checkpoint的LSN进行比较(比之大,则为脏页,否则为干净页),判断是否为脏页。若该内存页为脏页,则先将该内存页直接(此时无需操作redo log,当redo log写这个数据页所在的位置时,会判断这个位置可以使用)写回到磁盘中,该页变成了干净页,再将其换出。
- 判断该行是否有写锁。若有写锁,则需要等待锁的释放,轮到自己读,这时候可能会出现死锁,当然概率很小;否则,使用当前读,读取该行最新版本的数据。
- 拿到数据之后,将数据进行更新,并将新的数据在内存中更新。
- 将该更新语句对数据页上做的修改操作,先写入到redo log buffer,置状态为prepare。
- 若此时redo log已满,触发刷脏页机制,此时会停止库的所有更新操作,将redo log的checkpoint向前推进,以留出一定空间。根据所设置的脏页比例上限,确定要刷脏页的数量,全力刷脏页。
- 将该更新语句的更新逻辑,追加写入到binlog中,并将binlog写入到磁盘中。
- 提交事务,将redo log buffer中的redo log状态置为commit,循环写入到redo log所在的磁盘空间中,释放行锁。