上一篇,已经写了查询语句的执行过程,那么更新语句难道还不一样?
答案是肯定的。
一、更新准备
update语句其实都会有一个隐藏的查询更能,将需要修改的数据找到,然后才能更新。
其实这一阶段跟查询是一样的。
二、更新
既然获取到了数据,那么要更新,这接下来的事都是与查询sql多操作的了。
先知识扩展一下:
1.mysql中的日志
这里只介绍三种日志:
1)binlog日志
二进制日志,也叫归档日志。它是mysql中server层的日志。
2)redo log
重做日志,是innodb层面的日志。它保证了事物的持久性。这里涉及到了WAL技术,先写日志,在写磁盘。
3)undo log
回滚日志,用于事物回滚的。它保证了事物的原子性。
注:
一、undo log不是redo log的逆向日志。
1)redo log是物理日志,记录的是一个页的修改,它与更新数据无关。即redo log没有能力去更新数据库的一条数据。它的作用是如果意外重启,将数据库与其不一样的数据页加载到内存,根据redo log更新页,这时候的页与数据库中的页不一致,称为脏页。最终数据落盘,称刷脏页。这个刷脏页的过程与redo log一点关系也没有。
2)undo log 是记录的某个版本,是逻辑日志,根据某行进行恢复。
二、redo log的写入
redo log日志是先写入一个redo log buffer缓存中,然后间隔1s或者达到其内存一半时,write到怕page cache中,然后持久化到磁盘。这个过程中,也会存在未提交的事物被持久化到磁盘的情况。
2.mysql中的锁
事物的四个特性:
原子性、一致性、隔离性、持久性。
上面我们已经知道了原理性、持久性是由日志来实现的。那么一致性和隔离性呢?
为了保证原子性,引入了隔离性,那么隔离性又怎么处理呢?
答案是使用锁。
mysql的默认隔离级别是可重复读,那我们更新一条数据,如何使用锁来实现隔离性呢?
讨论是在有更新where条件有索引的基础上进行:
1)更新条件是非唯一索引
这里涉及到了回表,假如如下sql:
update user set age='30' where name='b'
其中name是非唯一索引。
2)当name是唯一索引
3)主键索引
知识点储备到这里,那么update更新怎么操作的,
1)获取锁,获取不到就没有修改的权限,就直接等待就行了。
2)写日志,将undo log、redo log、binlog写入。
3)刷脏页到磁盘,这个时间不定。