原地更新:假如列是 char(10),将值从2个字节更新到10个字节后,还是一样的长度。
非原地更新:如果列是 varchar(10),一开存的时候是5个节字,现在要更新到10个字节,如果这条记录后面已经有了其它记录,原来的记录是原地更新不了的,只能把这条记录删掉,在后面空闲的空间中插入数据。
原地更新不会占用新的存储空间,不会触发页的分裂
非原地更新需要删除原来的空间的数据,然后将更新后的数据插入到页的后面,删除的数据的空间,会插入到 Free_List 链表的头部。
这儿的 Free_List 在每个页中都有,Free_List 是将页中被删除的空间串联在一起(组成一个链表),当有数据被插到页内时,先看一下Free_list 中第一个空间的大小,如果空间合适,就将该记录插入到 第一个空间中去,如果不合适,直接插入到页的尾部的剩余空间(不会去看Free_list的第二个空间)。当该页的数据被插满了,不会马上进行分裂,而是进行 reorganize 操作,即将页内的数据在内存中 中进行整理(将数据从头到尾重新插入一遍,这样,空闲空间就到了页的尾部),然后覆盖原来的页(不影响性能),所以 InnoDB 不需要碎片整理,每次页满了,都会尝试做 reorganize,相对于分裂来说,reorganize 的成本小得多(optimize就是手动重建)。