
获得徽章 0
赞了这篇沸点
赞了这篇沸点
innodb存储引擎:
Buffer pool(缓冲池)
以页为存储单位,默认大小16KB,底层通过链表数据结构管理页,innodb访问索引和表记录时会在页中缓存,以达到减少磁盘io操作的目的。
页分为三类
free page:空闲页,未被使用
clean page:干净页,数据未更改
dirty page:脏页,页数据有更改,与磁盘数据不一致
针对三种页提供了三种不同的链表来管理。
free list:管理空闲页
flush list:管理脏页,作用是刷盘。按页修改时间来排序,修改时间越早的越先被刷盘。脏页也存在于lru list,两者互不干扰。
lru list:管理clean page和dirty page。作用是释放页。运用lru算法(近期最少使用算法)。缓冲区以midpoint为基点,每有一个新的页加入时都会从midpoint位置插入。前后链表分别为new列表区和old列表区。new列表区存放热数据,old则存放冷数据。当无空闲页可用时,就会将排在尾端的页释放掉,将内存空间供新的页使用。
Buffer pool(缓冲池)
以页为存储单位,默认大小16KB,底层通过链表数据结构管理页,innodb访问索引和表记录时会在页中缓存,以达到减少磁盘io操作的目的。
页分为三类
free page:空闲页,未被使用
clean page:干净页,数据未更改
dirty page:脏页,页数据有更改,与磁盘数据不一致
针对三种页提供了三种不同的链表来管理。
free list:管理空闲页
flush list:管理脏页,作用是刷盘。按页修改时间来排序,修改时间越早的越先被刷盘。脏页也存在于lru list,两者互不干扰。
lru list:管理clean page和dirty page。作用是释放页。运用lru算法(近期最少使用算法)。缓冲区以midpoint为基点,每有一个新的页加入时都会从midpoint位置插入。前后链表分别为new列表区和old列表区。new列表区存放热数据,old则存放冷数据。当无空闲页可用时,就会将排在尾端的页释放掉,将内存空间供新的页使用。
展开
评论
点赞
for update是当前读,当有其他未提交事务在update、
、delete、select…for update、select…lock in share mode时。就会被堵塞,直到该事务提交后才会结束堵塞。
原因:update、
、delete、select…for update是加了写锁。select…lock in share mode加了读锁。读锁加了后,只能再加读锁,却不能加写锁。写锁加了后,不能加读锁和写锁。所以才会堵塞。
前提:事务已打开
select * from users where 后面条件使用到了索引 就锁行,没有使用到索引就锁表。用到索引列时,如果没有该条记录,那会对该索引前后两条之间加间隙锁(gap),在这两条记录之间无法插入新的记录。但不影响其余地方的插入、更新、删除。
、delete、select…for update、select…lock in share mode时。就会被堵塞,直到该事务提交后才会结束堵塞。
原因:update、
、delete、select…for update是加了写锁。select…lock in share mode加了读锁。读锁加了后,只能再加读锁,却不能加写锁。写锁加了后,不能加读锁和写锁。所以才会堵塞。
前提:事务已打开
select * from users where 后面条件使用到了索引 就锁行,没有使用到索引就锁表。用到索引列时,如果没有该条记录,那会对该索引前后两条之间加间隙锁(gap),在这两条记录之间无法插入新的记录。但不影响其余地方的插入、更新、删除。
展开
1
4
#每天一个知识点#表锁和元数据锁异同
同:都是表级锁
异:
①表锁通过lock tables 表名 read/write 语句添加。 而元数据锁是自动加上。
②如果线程A执行了 lock tables t1 read, t2write;那么其他线程对t1表只能读操作,t2表无法读和写。而线程A也只能对t1表读,t2表读写。
元数据锁的读写规则是,读读共享,读写互斥,写写互斥。
同:都是表级锁
异:
①表锁通过lock tables 表名 read/write 语句添加。 而元数据锁是自动加上。
②如果线程A执行了 lock tables t1 read, t2write;那么其他线程对t1表只能读操作,t2表无法读和写。而线程A也只能对t1表读,t2表读写。
元数据锁的读写规则是,读读共享,读写互斥,写写互斥。
展开
评论
1
页分裂:将当前页一半的数据分到新页,此时新页的值都是比原来的页大的。
更新索引上的值也会造成数据页的空洞:
因为更新一个索引时,会先删除原先索引,在生成一个新的索引,如下图,如果删除id为7的数据,那么对应空间保留,当有符合 6 < id < 19 的数据时就会复用,没有时就会一直空着。这就是所谓的空洞。
更新索引上的值也会造成数据页的空洞:
因为更新一个索引时,会先删除原先索引,在生成一个新的索引,如下图,如果删除id为7的数据,那么对应空间保留,当有符合 6 < id < 19 的数据时就会复用,没有时就会一直空着。这就是所谓的空洞。
展开
评论
点赞
update 和 delete 都是先读到内存再操作。那这两个语句岂不是用不到change buffer?
change buffer对应的是普通索引树,update 、insert、delete对应的数据更新后,对应索引树也是需要更新的,主键索引和唯一的二级索引 这两种索引不会用change buffer,普通索引原本也需要读入内存进行更新,但有了change buffer 后,就不需要立马读入,而是将相应更新信息放到change buffer中,等后续执行其他sql语句将对应索引树读入内存时在合并。
change buffer对应的是普通索引树,update 、insert、delete对应的数据更新后,对应索引树也是需要更新的,主键索引和唯一的二级索引 这两种索引不会用change buffer,普通索引原本也需要读入内存进行更新,但有了change buffer 后,就不需要立马读入,而是将相应更新信息放到change buffer中,等后续执行其他sql语句将对应索引树读入内存时在合并。
展开
评论
点赞
bin log 与 redo log差异点:
①存储内容不同:redo log是物理日志,存储的是数据页上的操作信息,bin log是逻辑日志,存储的是原始的语句逻辑,如给“ ID=2 这一行的 c 字段加 1 ”。
②存储方式不同:redo log是循环写,空间固定会用完,bin log是追加写,写满了会切换到写一个页(需要定期手动清理,避免占用过多磁盘空间)。
③适用范围不同:redo log是innodb引擎特有的,bin log是mysql的server层实现,所有引擎都可用。
2.小知识:最早mysql默认的存储引擎是myisam,只有bin log(用于归档,没有crash_save能力),没有redo log。innodb是另一家公司以插件的形式引入mysql。使用redo log来实现crash_save能力。
3.两阶段提交,事务提交过程:
①.先写redo log,将其状态变为prepare状态,这步已经将唯一标识事务的xid写入。
②.再写bin log。
③.事务提交,将redo log状态变更为commit。
理解:以bin log为基础,如果在步骤二之前崩溃,因为处于prepare阶段,所以redo log的xid会到bin log中匹配,结果没匹配上,就会回滚。如果在步骤三之前崩溃,此时redo log 的xid在bin log中匹配到了,就会执行第三个步骤,将事务提交。
①存储内容不同:redo log是物理日志,存储的是数据页上的操作信息,bin log是逻辑日志,存储的是原始的语句逻辑,如给“ ID=2 这一行的 c 字段加 1 ”。
②存储方式不同:redo log是循环写,空间固定会用完,bin log是追加写,写满了会切换到写一个页(需要定期手动清理,避免占用过多磁盘空间)。
③适用范围不同:redo log是innodb引擎特有的,bin log是mysql的server层实现,所有引擎都可用。
2.小知识:最早mysql默认的存储引擎是myisam,只有bin log(用于归档,没有crash_save能力),没有redo log。innodb是另一家公司以插件的形式引入mysql。使用redo log来实现crash_save能力。
3.两阶段提交,事务提交过程:
①.先写redo log,将其状态变为prepare状态,这步已经将唯一标识事务的xid写入。
②.再写bin log。
③.事务提交,将redo log状态变更为commit。
理解:以bin log为基础,如果在步骤二之前崩溃,因为处于prepare阶段,所以redo log的xid会到bin log中匹配,结果没匹配上,就会回滚。如果在步骤三之前崩溃,此时redo log 的xid在bin log中匹配到了,就会执行第三个步骤,将事务提交。
展开
评论
2
alter table t1 engine = innodb 执行完后表占用空间反而变大了是为啥?
重点:重建表后表空间不是最紧凑的。
因为重建表的时候并不是把一个页全塞满,而是会预留一部分空间(1/16页)留作更新时使用,所以当之前已经执行过一次重建表后,又有新的数据插入,此时已经将该页留给更新的空间用了一部分,这时候再重建就有可能开新页导致表占用空间变大。
重点:重建表后表空间不是最紧凑的。
因为重建表的时候并不是把一个页全塞满,而是会预留一部分空间(1/16页)留作更新时使用,所以当之前已经执行过一次重建表后,又有新的数据插入,此时已经将该页留给更新的空间用了一部分,这时候再重建就有可能开新页导致表占用空间变大。
展开
3
点赞
赞了这篇沸点
#每天一个知识点# 你可能还不知道 JavaScript 的 toLocaleString 还可以这么玩。
123456789..toLocaleString('zh-hans-cn-u-nu-hanidec',{useGrouping: false}); //"一二三四五六七八九"
123456789..toLocaleString('zh-hans-cn-u-nu-hanidec',{useGrouping: false}); //"一二三,四五六,七八九"
new Date().toLocaleString('zh-hans-cn-u-nu-hanidec'); //"二〇一九/五/二九 下午三:一五:四〇"
123456789..toLocaleString('zh-hans-cn-u-nu-hanidec',{useGrouping: false}); //"一二三四五六七八九"
123456789..toLocaleString('zh-hans-cn-u-nu-hanidec',{useGrouping: false}); //"一二三,四五六,七八九"
new Date().toLocaleString('zh-hans-cn-u-nu-hanidec'); //"二〇一九/五/二九 下午三:一五:四〇"
展开
评论
14
每日知识点:
为什么表数据删了一半,表文件大小不变?
delete操作只是把被删除的位置标记为可复用,但磁盘文件大小并不会变,这些被标记但未被使用的就会视为空洞。可以用过alter table 表名 engine = innodb来重建表空间。
为什么表数据删了一半,表文件大小不变?
delete操作只是把被删除的位置标记为可复用,但磁盘文件大小并不会变,这些被标记但未被使用的就会视为空洞。可以用过alter table 表名 engine = innodb来重建表空间。
3
2