1 Star 0 Fork 59

王祥Moon/mysql45

forked from funnylog/mysql45 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
13讲为什么表数据删掉一半,表文件大小不变.html 60.50 KB
一键复制 编辑 原始数据 按行查看 历史
funnylog 提交于 2020-09-18 15:06 . first commit
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover">
<meta name="format-detection" content="telephone=no">
<style type="text/css">
#watermark {
position: relative;
overflow: hidden;
}
#watermark .x {
position: absolute;
top: 800;
left: 400;
color: #3300ff;
font-size: 50px;
pointer-events: none;
opacity:0.3;
filter:Alpha(opacity=50);
}
</style>
<style type="text/css">
html{color:#333;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-rendering:optimizelegibility;font-family:Helvetica Neue,PingFang SC,Verdana,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,sans-serif}html.borderbox *,html.borderbox :after,html.borderbox :before{box-sizing:border-box}article,aside,blockquote,body,button,code,dd,details,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hr,input,legend,li,menu,nav,ol,p,pre,section,td,textarea,th,ul{margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,menu,nav,section{display:block}audio,canvas,video{display:inline-block}body,button,input,select,textarea{font:300 1em/1.8 PingFang SC,Lantinghei SC,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,Helvetica,sans-serif}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}blockquote{position:relative;color:#999;font-weight:400;border-left:1px solid #1abc9c;padding-left:1em;margin:1em 3em 1em 2em}@media only screen and (max-width:640px){blockquote{margin:1em 0}}abbr,acronym{border-bottom:1px dotted;font-variant:normal}abbr{cursor:help}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:400}ol,ul{list-style:none}caption,th{text-align:left}q:after,q:before{content:""}sub,sup{font-size:75%;line-height:0;position:relative}:root sub,:root sup{vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a{color:#1abc9c}a:hover{text-decoration:underline}.typo a{border-bottom:1px solid #1abc9c}.typo a:hover{border-bottom-color:#555;color:#555}.typo a:hover,a,ins{text-decoration:none}.typo-u,u{text-decoration:underline}mark{background:#fffdd1;border-bottom:1px solid #ffedce;padding:2px;margin:0 5px}code,pre,pre tt{font-family:Courier,Courier New,monospace}pre{background:hsla(0,0%,97%,.7);border:1px solid #ddd;padding:1em 1.5em;display:block;-webkit-overflow-scrolling:touch}hr{border:none;border-bottom:1px solid #cfcfcf;margin-bottom:.8em;height:10px}.typo-small,figcaption,small{font-size:.9em;color:#888}b,strong{font-weight:700;color:#000}[draggable]{cursor:move}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}.clearfix{zoom:1}.textwrap,.textwrap td,.textwrap th{word-wrap:break-word;word-break:break-all}.textwrap-table{table-layout:fixed}.serif{font-family:Palatino,Optima,Georgia,serif}.typo-dl,.typo-form,.typo-hr,.typo-ol,.typo-p,.typo-pre,.typo-table,.typo-ul,.typo dl,.typo form,.typo hr,.typo ol,.typo p,.typo pre,.typo table,.typo ul,blockquote{margin-bottom:1rem}h1,h2,h3,h4,h5,h6{font-family:PingFang SC,Helvetica Neue,Verdana,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,sans-serif;color:#000;line-height:1.35}.typo-h1,.typo-h2,.typo-h3,.typo-h4,.typo-h5,.typo-h6,.typo h1,.typo h2,.typo h3,.typo h4,.typo h5,.typo h6{margin-top:1.2em;margin-bottom:.6em;line-height:1.35}.typo-h1,.typo h1{font-size:2em}.typo-h2,.typo h2{font-size:1.8em}.typo-h3,.typo h3{font-size:1.6em}.typo-h4,.typo h4{font-size:1.4em}.typo-h5,.typo-h6,.typo h5,.typo h6{font-size:1.2em}.typo-ul,.typo ul{margin-left:1.3em;list-style:disc}.typo-ol,.typo ol{list-style:decimal;margin-left:1.9em}.typo-ol ol,.typo-ol ul,.typo-ul ol,.typo-ul ul,.typo li ol,.typo li ul{margin-bottom:.8em;margin-left:2em}.typo-ol ul,.typo-ul ul,.typo li ul{list-style:circle}.typo-table td,.typo-table th,.typo table caption,.typo table td,.typo table th{border:1px solid #ddd;padding:.5em 1em;color:#666}.typo-table th,.typo table th{background:#fbfbfb}.typo-table thead th,.typo table thead th{background:hsla(0,0%,95%,.7)}.typo table caption{border-bottom:none}.typo-input,.typo-textarea{-webkit-appearance:none;border-radius:0}.typo-em,.typo em,caption,legend{color:#000;font-weight:inherit}.typo-em{position:relative}.typo-em:after{position:absolute;top:.65em;left:0;width:100%;overflow:hidden;white-space:nowrap;content:"\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB"}.typo img{max-width:100%}.common-content{font-weight:400;color:#353535;line-height:1.75rem;white-space:normal;word-break:normal;font-size:1rem}.common-content img{display:block;max-width:100%;background-color:#eee}.common-content audio,.common-content video{width:100%;background-color:#eee}.common-content center,.common-content font{margin-top:1rem;display:inline-block}.common-content center{width:100%}.common-content pre{margin-top:1rem;padding-left:0;padding-right:0;position:relative;overflow:hidden}.common-content pre code{font-size:.8rem;font-family:Consolas,Liberation Mono,Menlo,monospace,Courier;display:block;width:100%;box-sizing:border-box;padding-left:1rem;padding-right:1rem;overflow-x:auto}.common-content hr{border:none;margin-top:1.5rem;margin-bottom:1.5rem;border-top:1px solid #f5f5f5;height:1px;background:none}.common-content b,.common-content h1,.common-content h2,.common-content h3,.common-content h4,.common-content h5,.common-content strong{font-weight:700}.common-content h1,.common-content h2{font-size:1.125rem;margin-bottom:.45rem}.common-content h3,.common-content h4,.common-content h5{font-size:1rem;margin-bottom:.45rem}.common-content p{font-weight:400;color:#353535;margin-top:.15rem}.common-content .orange{color:#ff5a05}.common-content .reference{font-size:1rem;color:#888}.custom-rich-content h1{margin-top:0;font-weight:400;font-size:15.25px;border-bottom:1px solid #eee;line-height:2.8}.custom-rich-content li,.custom-rich-content p{font-size:14px;color:#888;line-height:1.6}table.hljs-ln{margin-bottom:0;border-spacing:0;border-collapse:collapse}table.hljs-ln,table.hljs-ln tbody,table.hljs-ln td,table.hljs-ln tr{box-sizing:border-box}table.hljs-ln td{padding:0;border:0}table.hljs-ln td.hljs-ln-numbers{min-width:15px;color:rgba(27,31,35,.3);text-align:right;white-space:nowrap;cursor:pointer;user-select:none}table.hljs-ln td.hljs-ln-code,table.hljs-ln td.hljs-ln-numbers{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px;line-height:20px;vertical-align:top}table.hljs-ln td.hljs-ln-code{position:relative;padding-right:10px;padding-left:10px;overflow:visible;color:#24292e;word-wrap:normal;white-space:pre}video::-webkit-media-controls{overflow:hidden!important}video::-webkit-media-controls-enclosure{width:calc(100% + 32px);margin-left:auto}.button-cancel{color:#888;border:1px solid #888;border-radius:3px;margin-right:12px}.button-cancel,.button-primary{-ms-flex-positive:1;flex-grow:1;height:35px;display:inline-block;font-size:15px;text-align:center;line-height:36px}.button-primary{color:#fff;background-color:#ff5a05;border-radius:3px}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.eot);src:url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.eot#iefix) format("embedded-opentype"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.woff) format("woff"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.ttf) format("truetype"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.svg#iconfont) format("svg")}@font-face{font-family:player-font;src:url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.eot);src:url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.eot#iefix) format("embedded-opentype"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.woff) format("woff"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.ttf) format("truetype"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.svg#player-font) format("svg")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-webkit-text-stroke-width:.2px;-moz-osx-font-smoothing:grayscale}html{background:#fff;min-height:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{width:100%}body.fixed{overflow:hidden;position:fixed;width:100vw;height:100vh}i{font-style:normal}a{word-wrap:break-word;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:hover{text-decoration:none}.fade-enter-active,.fade-leave-active{transition:opacity .3s}.fade-enter,.fade-leave-to{opacity:0}.MathJax,.MathJax_CHTML,.MathJax_MathContainer,.MathJax_MathML,.MathJax_PHTML,.MathJax_PlainSource,.MathJax_SVG{outline:0}.ios-app-switch .js-audit{display:none}._loading_wrap_{position:fixed;width:100vw;height:100vh;top:50%;left:50%;transform:translate(-50%,-50%);z-index:999}._loading_div_class_,._loading_wrap_{display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}._loading_div_class_{word-wrap:break-word;padding:.5rem .75rem;text-align:center;z-index:9999;font-size:.6rem;max-width:60%;color:#fff;border-radius:.25rem;-ms-flex-direction:column;flex-direction:column}._loading_div_class_ .message{color:#353535;font-size:16px;line-height:3}.spinner{animation:circle-rotator 1.4s linear infinite}.spinner *{line-height:0;box-sizing:border-box}@keyframes circle-rotator{0%{transform:rotate(0deg)}to{transform:rotate(270deg)}}.path{stroke-dasharray:187;stroke-dashoffset:0;transform-origin:center;animation:circle-dash 1.4s ease-in-out infinite,circle-colors 5.6s ease-in-out infinite}@keyframes circle-colors{0%{stroke:#ff5a05}to{stroke:#ff5a05}}@keyframes circle-dash{0%{stroke-dashoffset:187}50%{stroke-dashoffset:46.75;transform:rotate(135deg)}to{stroke-dashoffset:187;transform:rotate(450deg)}}.confirm-box-wrapper,.confirm-box-wrapper .mask{position:absolute;top:0;left:0;right:0;bottom:0}.confirm-box-wrapper .mask{background:rgba(0,0,0,.6)}.confirm-box-wrapper .confirm-box{position:fixed;top:50%;left:50%;width:267px;background:#fff;transform:translate(-50%,-50%);border-radius:7px}.confirm-box-wrapper .confirm-box .head{margin:0 18px;font-size:18px;text-align:center;line-height:65px;border-bottom:1px solid #d9d9d9}.confirm-box-wrapper .confirm-box .body{padding:18px;padding-bottom:0;color:#353535;font-size:12.5px;max-height:150px;overflow:auto}.confirm-box-wrapper .confirm-box .foot{display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;padding:18px}.confirm-box-wrapper .confirm-box .foot .button-cancel{border:1px solid #d9d9d9}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
</style>
<style type="text/css">
.button-cancel[data-v-87ffcada]{color:#888;border:1px solid #888;border-radius:3px;margin-right:12px}.button-cancel[data-v-87ffcada],.button-primary[data-v-87ffcada]{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;height:35px;display:inline-block;font-size:15px;text-align:center;line-height:36px}.button-primary[data-v-87ffcada]{color:#fff;background-color:#ff5a05;border-radius:3px}.pd[data-v-87ffcada]{padding-left:1.375rem;padding-right:1.375rem}.article[data-v-87ffcada]{max-width:70rem;margin:0 auto}.article .article-unavailable[data-v-87ffcada]{color:#fa8919;font-size:15px;font-weight:600;line-height:24px;border-radius:5px;padding:12px;background-color:#f6f7fb;margin-top:20px}.article .article-unavailable .iconfont[data-v-87ffcada]{font-size:12px}.article .main[data-v-87ffcada]{padding:1.25rem 0;margin-bottom:52px}.article-title[data-v-87ffcada]{color:#353535;font-weight:400;line-height:1.65rem;font-size:1.34375rem}.article-info[data-v-87ffcada]{color:#888;font-size:.9375rem;margin-top:1.0625rem}.article-content[data-v-87ffcada]{margin-top:1.0625rem}.article-content.android video[data-v-87ffcada]::-webkit-media-controls-fullscreen-button{display:none}.copyright[data-v-87ffcada]{color:#b2b2b2;padding-bottom:20px;margin-top:20px;font-size:13px}.audio-player[data-v-87ffcada]{width:100%;margin:20px 0}.to-comment[data-v-87ffcada]{overflow:hidden;padding-top:10px;margin-bottom:-30px}.to-comment a.button-primary[data-v-87ffcada]{float:right;height:20px;font-size:12px;line-height:20px;padding:4px 8px;cursor:pointer}.article-comments[data-v-87ffcada]{margin-top:2rem}.article-comments h2[data-v-87ffcada]{text-align:center;color:#888;position:relative;z-index:1;margin-bottom:1rem}.article-comments h2[data-v-87ffcada]:before{border-top:1px dotted #888;content:"";position:absolute;top:56%;left:0;width:100%;z-index:-1}.article-comments h2 span[data-v-87ffcada]{font-size:15.25px;font-weight:400;padding:0 1rem;background:#fff;display:inline-block}.article-sub-bottom[data-v-87ffcada]{z-index:10;cursor:pointer}.switch-btns[data-v-87ffcada]{height:76px;cursor:pointer;padding-top:24px;padding-bottom:24px;border-bottom:10px solid #f6f7fb;position:relative}.switch-btns[data-v-87ffcada]:before{content:" ";height:1px;background:#e8e8e8;position:absolute;top:0;left:0;-webkit-box-sizing:border-box;box-sizing:border-box;left:1.375rem;right:1.375rem}.switch-btns .btn[data-v-87ffcada]{height:38px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.switch-btns .btn .tag[data-v-87ffcada]{-webkit-box-flex:0;-ms-flex:0 0 62px;flex:0 0 62px;text-align:center;color:#888;font-size:14px;border-radius:10px;height:22px;line-height:22px;background:#f6f7fb;font-weight:400}.switch-btns .btn .txt[data-v-87ffcada]{margin-left:10px;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;color:#888;font-size:15px;height:22px;line-height:22px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400}@media (max-width:769px){.article .breadcrumb[data-v-87ffcada]{padding-top:10px;padding-bottom:10px}}
</style>
<style type="text/css">
.comment-item{list-style-position:inside;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;margin-bottom:1rem}.comment-item a{border-bottom:none}.comment-item .avatar{width:2.625rem;height:2.625rem;-ms-flex-negative:0;flex-shrink:0;border-radius:50%}.comment-item .info{margin-left:.5rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.comment-item .info .hd{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.comment-item .info .hd .username{color:#888;font-size:15.25px;font-weight:400;line-height:1.2}.comment-item .info .hd .control{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.comment-item .info .hd .control .btn-share{color:#888;font-size:.75rem;margin-right:1rem}.comment-item .info .hd .control .btn-praise{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:15.25px;text-decoration:none}.comment-item .info .hd .control .btn-praise i{color:#888;display:inline-block;font-size:.75rem;margin-right:.3rem;margin-top:-.01rem}.comment-item .info .hd .control .btn-praise i.on,.comment-item .info .hd .control .btn-praise span{color:#ff5a05}.comment-item .info .bd{color:#353535;font-size:15.25px;font-weight:400;white-space:normal;word-break:break-all;line-height:1.6}.comment-item .info .time{color:#888;font-size:9px;line-height:1}.comment-item .info .reply .reply-hd{font-size:15.25px}.comment-item .info .reply .reply-hd span{margin-left:-12px;color:#888;font-weight:400}.comment-item .info .reply .reply-hd i{color:#ff5a05;font-size:15.25px}.comment-item .info .reply .reply-content{color:#353535;font-size:15.25px;font-weight:400;white-space:normal;word-break:break-all}.comment-item .info .reply .reply-time{color:#888;font-size:9px}
</style>
</head>
<body>
<div id="app">
<div data-v-87ffcada="" class="article" id="watermark">
<div data-v-87ffcada="" class="main main-app">
<h1 data-v-87ffcada="" class="article-title pd">
13讲为什么表数据删掉一半,表文件大小不变
</h1>
<div data-v-87ffcada="" class="article-content typo common-content pd"><img data-v-87ffcada=""
src="https://static001.geekbang.org/resource/image/7e/11/7e411ea05dde5a1bf3a4106fb8e5ae11.jpg">
<div>
<audio controls="controls" height="100" width="100">
<source src="13讲为什么表数据删掉一半,表文件大小不变.mp3" type="audio/mp3" />
<embed height="100" width="100" src="13讲为什么表数据删掉一半,表文件大小不变.mp3" />
</audio>
</div>
<div data-v-87ffcada="" id="article-content" class="">
<div class="text">
<p>经常会有同学来问我,我的数据库占用空间太大,我把一个最大的表删掉了一半的数据,怎么表文件的大小还是没变?</p><p>那么今天,我就和你聊聊数据库表的空间回收,看看如何解决这个问题。</p><p>这里,我们还是针对MySQL中应用最广泛的InnoDB引擎展开讨论。一个InnoDB表包含两部分,即:表结构定义和数据。在MySQL 8.0版本以前,表结构是存在以.frm为后缀的文件里。而MySQL 8.0版本,则已经允许把表结构定义放在系统数据表中了。因为表结构定义占用的空间很小,所以我们今天主要讨论的是表数据。</p><p>接下来,我会先和你说明为什么简单地删除表数据达不到表空间回收的效果,然后再和你介绍正确回收空间的方法。</p><h1>参数innodb_file_per_table</h1><p>表数据既可以存在共享表空间里,也可以是单独的文件。这个行为是由参数innodb_file_per_table控制的:</p><ol>
<li>
<p>这个参数设置为OFF表示的是,表的数据放在系统共享表空间,也就是跟数据字典放在一起;</p>
</li>
<li>
<p>这个参数设置为ON表示的是,每个InnoDB表数据存储在一个以 .ibd为后缀的文件中。</p>
</li>
</ol><p>从MySQL 5.6.6版本开始,它的默认值就是ON了。</p><p>我建议你不论使用MySQL的哪个版本,都将这个值设置为ON。因为,一个表单独存储为一个文件更容易管理,而且在你不需要这个表的时候,通过drop table命令,系统就会直接删除这个文件。而如果是放在共享表空间中,即使表删掉了,空间也是不会回收的。</p><!-- [[[read_end]]] --><p>所以,<strong>将innodb_file_per_table设置为ON,是推荐做法,我们接下来的讨论都是基于这个设置展开的。</strong></p><p>我们在删除整个表的时候,可以使用drop table命令回收表空间。但是,我们遇到的更多的删除数据的场景是删除某些行,这时就遇到了我们文章开头的问题:表中的数据被删除了,但是表空间却没有被回收。</p><p>我们要彻底搞明白这个问题的话,就要从数据删除流程说起了。</p><h1>数据删除流程</h1><p>我们先再来看一下InnoDB中一个索引的示意图。在前面<a href="https://time.geekbang.org/column/article/69236">第4</a><a href="https://time.geekbang.org/column/article/69636">第5</a>篇文章中,我和你介绍索引时曾经提到过,InnoDB里的数据都是用B+树的结构组织的。</p><p><img src="https://static001.geekbang.org/resource/image/f0/c8/f0b1e4ac610bcb5c5922d0b18563f3c8.png" alt=""></p><center><span class="reference">图1 B+树索引示意图</span></center><p>假设,我们要删掉R4这个记录,InnoDB引擎只会把R4这个记录标记为删除。如果之后要再插入一个ID在300和600之间的记录时,可能会复用这个位置。但是,磁盘文件的大小并不会缩小。</p><p>现在,你已经知道了InnoDB的数据是按页存储的,那么如果我们删掉了一个数据页上的所有记录,会怎么样?</p><p>答案是,整个数据页就可以被复用了。</p><p>但是,<strong>数据页的复用跟记录的复用是不同的。</strong></p><p>记录的复用,只限于符合范围条件的数据。比如上面的这个例子,R4这条记录被删除后,如果插入一个ID是400的行,可以直接复用这个空间。但如果插入的是一个ID是800的行,就不能复用这个位置了。</p><p>而当整个页从B+树里面摘掉以后,可以复用到任何位置。以图1为例,如果将数据页page A上的所有记录删除以后,page A会被标记为可复用。这时候如果要插入一条ID=50的记录需要使用新页的时候,page A是可以被复用的。</p><p>如果相邻的两个数据页利用率都很小,系统就会把这两个页上的数据合到其中一个页上,另外一个数据页就被标记为可复用。</p><p>进一步地,如果我们用delete命令把整个表的数据删除呢?结果就是,所有的数据页都会被标记为可复用。但是磁盘上,文件不会变小。</p><p>你现在知道了,delete命令其实只是把记录的位置,或者数据页标记为了“可复用”,但磁盘文件的大小是不会变的。也就是说,通过delete命令是不能回收表空间的。这些可以复用,而没有被使用的空间,看起来就像是“空洞”。</p><p>实际上,<strong>不止是删除数据会造成空洞,插入数据也会。</strong></p><p>如果数据是按照索引递增顺序插入的,那么索引是紧凑的。但如果数据是随机插入的,就可能造成索引的数据页分裂。</p><p>假设图1中page A已经满了,这时我要再插入一行数据,会怎样呢?</p><p><img src="https://static001.geekbang.org/resource/image/80/ea/8083f05a4a4c0372833a6e01d5a8e6ea.png" alt=""></p><center><span class="reference">图2 插入数据导致页分裂</span></center><p>可以看到,由于page A满了,再插入一个ID是550的数据时,就不得不再申请一个新的页面page B来保存数据了。页分裂完成后,page A的末尾就留下了空洞(注意:实际上,可能不止1个记录的位置是空洞)。</p><p>另外,更新索引上的值,可以理解为删除一个旧的值,再插入一个新值。不难理解,这也是会造成空洞的。</p><p>也就是说,经过大量增删改的表,都是可能是存在空洞的。所以,如果能够把这些空洞去掉,就能达到收缩表空间的目的。</p><p>而重建表,就可以达到这样的目的。</p><h1>重建表</h1><p>试想一下,如果你现在有一个表A,需要做空间收缩,为了把表中存在的空洞去掉,你可以怎么做呢?</p><p>你可以新建一个与表A结构相同的表B,然后按照主键ID递增的顺序,把数据一行一行地从表A里读出来再插入到表B中。</p><p>由于表B是新建的表,所以表A主键索引上的空洞,在表B中就都不存在了。显然地,表B的主键索引更紧凑,数据页的利用率也更高。如果我们把表B作为临时表,数据从表A导入表B的操作完成后,用表B替换A,从效果上看,就起到了收缩表A空间的作用。</p><p>这里,你可以使用alter table A engine=InnoDB命令来重建表。在MySQL 5.5版本之前,这个命令的执行流程跟我们前面描述的差不多,区别只是这个临时表B不需要你自己创建,MySQL会自动完成转存数据、交换表名、删除旧表的操作。</p><p><img src="https://static001.geekbang.org/resource/image/02/cd/02e083adaec6e1191f54992f7bc13dcd.png" alt=""></p><center><span class="reference">图3 改锁表DDL</span></center><p>显然,花时间最多的步骤是往临时表插入数据的过程,如果在这个过程中,有新的数据要写入到表A的话,就会造成数据丢失。因此,在整个DDL过程中,表A中不能有更新。也就是说,这个DDL不是Online的。</p><p>而在<strong>MySQL 5.6版本开始引入的Online DDL,对这个操作流程做了优化。</strong></p><p>我给你简单描述一下引入了Online DDL之后,重建表的流程:</p><ol>
<li>
<p>建立一个临时文件,扫描表A主键的所有数据页;</p>
</li>
<li>
<p>用数据页中表A的记录生成B+树,存储到临时文件中;</p>
</li>
<li>
<p>生成临时文件的过程中,将所有对A的操作记录在一个日志文件(row log)中,对应的是图中state2的状态;</p>
</li>
<li>
<p>临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表A相同的数据文件,对应的就是图中state3的状态;</p>
</li>
<li>
<p>用临时文件替换表A的数据文件。</p>
</li>
</ol><p><img src="https://static001.geekbang.org/resource/image/2d/f0/2d1cfbbeb013b851a56390d38b5321f0.png" alt=""></p><center><span class="reference">图4 Online DDL</span></center><p>可以看到,与图3过程的不同之处在于,由于日志文件记录和重放操作这个功能的存在,这个方案在重建表的过程中,允许对表A做增删改操作。这也就是Online DDL名字的来源。</p><p>我记得有同学在第6篇讲表锁的文章<a href="https://time.geekbang.org/column/article/69862">《全局锁和表锁 :给表加个字段怎么索这么多阻碍?》</a>的评论区留言说,DDL之前是要拿MDL写锁的,这样还能叫Online DDL吗?</p><p>确实,图4的流程中,alter语句在启动的时候需要获取MDL写锁,但是这个写锁在真正拷贝数据之前就退化成读锁了。</p><p>为什么要退化呢?为了实现Online,MDL读锁不会阻塞增删改操作。</p><p>那为什么不干脆直接解锁呢?为了保护自己,禁止其他线程对这个表同时做DDL。</p><p>而对于一个大表来说,Online DDL最耗时的过程就是拷贝数据到临时表的过程,这个步骤的执行期间可以接受增删改操作。所以,相对于整个DDL过程来说,锁的时间非常短。对业务来说,就可以认为是Online的。</p><p>需要补充说明的是,上述的这些重建方法都会扫描原表数据和构建临时文件。对于很大的表来说,这个操作是很消耗IO和CPU资源的。因此,如果是线上服务,你要很小心地控制操作时间。如果想要比较安全的操作的话,我推荐你使用GitHub开源的gh-ost来做。</p><h1>Online 和 inplace</h1><p>说到Online,我还要再和你澄清一下它和另一个跟DDL有关的、容易混淆的概念inplace的区别。</p><p>你可能注意到了,在图3中,我们把表A中的数据导出来的存放位置叫作tmp_table。这是一个临时表,是在server层创建的。</p><p>在图4中,根据表A重建出来的数据是放在“tmp_file”里的,这个临时文件是InnoDB在内部创建出来的。整个DDL过程都在InnoDB内部完成。对于server层来说,没有把数据挪动到临时表,是一个“原地”操作,这就是“inplace”名称的来源。</p><p>所以,我现在问你,如果你有一个1TB的表,现在磁盘间是1.2TB,能不能做一个inplace的DDL呢?</p><p>答案是不能。因为,tmp_file也是要占用临时空间的。</p><p>我们重建表的这个语句alter table t engine=InnoDB,其实隐含的意思是:</p><pre><code>alter table t engine=innodb,ALGORITHM=inplace;
</code></pre><p>跟inplace对应的就是拷贝表的方式了,用法是:</p><pre><code>alter table t engine=innodb,ALGORITHM=copy;
</code></pre><p>当你使用ALGORITHM=copy的时候,表示的是强制拷贝表,对应的流程就是图3的操作过程。</p><p>但我这样说你可能会觉得,inplace跟Online是不是就是一个意思?</p><p>其实不是的,只是在重建表这个逻辑中刚好是这样而已。</p><p>比如,如果我要给InnoDB表的一个字段加全文索引,写法是:</p><pre><code>alter table t add FULLTEXT(field_name);
</code></pre><p>这个过程是inplace的,但会阻塞增删改操作,是非Online的。</p><p>如果说这两个逻辑之间的关系是什么的话,可以概括为:</p><ol>
<li>
<p>DDL过程如果是Online的,就一定是inplace的;</p>
</li>
<li>
<p>反过来未必,也就是说inplace的DDL,有可能不是Online的。截止到MySQL 8.0,添加全文索引(FULLTEXT index)和空间索引(SPATIAL index)就属于这种情况。</p>
</li>
</ol><p>最后,我们再延伸一下。</p><p>在第10篇文章<a href="https://time.geekbang.org/column/article/71173">《MySQL为什么有时候会选错索引》</a>的评论区中,有同学问到使用optimize table、analyze table和alter table这三种方式重建表的区别。这里,我顺便再简单和你解释一下。</p><ul>
<li>从MySQL 5.6版本开始,alter table t engine = InnoDB(也就是recreate)默认的就是上面图4的流程了;</li>
<li>analyze table t 其实不是重建表,只是对表的索引信息做重新统计,没有修改数据,这个过程中加了MDL读锁;</li>
<li>optimize table t 等于recreate+analyze。</li>
</ul><h1>小结</h1><p>今天这篇文章,我和你讨论了数据库中收缩表空间的方法。</p><p>现在你已经知道了,如果要收缩一个表,只是delete掉表里面不用的数据的话,表文件的大小是不会变的,你还要通过alter table命令重建表,才能达到表文件变小的目的。我跟你介绍了重建表的两种实现方式,Online DDL的方式是可以考虑在业务低峰期使用的,而MySQL 5.5及之前的版本,这个命令是会阻塞DML的,这个你需要特别小心。</p><p>最后,又到了我们的课后问题时间。</p><p>假设现在有人碰到了一个“想要收缩表空间,结果适得其反”的情况,看上去是这样的:</p><ol>
<li>
<p>一个表t文件大小为1TB;</p>
</li>
<li>
<p>对这个表执行 alter table t engine=InnoDB;</p>
</li>
<li>
<p>发现执行完成后,空间不仅没变小,还稍微大了一点儿,比如变成了1.01TB。</p>
</li>
</ol><p>你觉得可能是什么原因呢 ?</p><p>你可以把你觉得可能的原因写在留言区里,我会在下一篇文章的末尾把大家描述的合理的原因都列出来,以后其他同学就不用掉到这样的坑里了。感谢你的收听,也欢迎你把这篇文章分享给更多的朋友一起阅读。</p><h1>上期问题时间</h1><p>在上期文章最后,我留给你的问题是,如果一个高配的机器,redo log设置太小,会发生什么情况。</p><p>每次事务提交都要写redo log,如果设置太小,很快就会被写满,也就是下面这个图的状态,这个“环”将很快被写满,write pos一直追着CP。</p><p><img src="https://static001.geekbang.org/resource/image/a2/e5/a25bdbbfc2cfc5d5e20690547fe7f2e5.jpg" alt=""></p><p>这时候系统不得不停止所有更新,去推进checkpoint。</p><p>这时,你看到的现象就是<strong>磁盘压力很小,但是数据库出现间歇性的性能下跌。</strong></p><p>评论区留言点赞板:</p><blockquote>
<p>@某、人 给了一个形象的描述,而且提到了,在这种情况下,连change buffer的优化也失效了。因为checkpoint一直要往前推,这个操作就会触发merge操作,然后又进一步地触发刷脏页操作;<br>
有几个同学提到了内存淘汰脏页,对应的redo log的操作,这个我们会在后面的文章中展开,大家可以先看一下 @melon 同学的描述了解一下;<br>
@算不出流源 提到了“动态平衡”,其实只要出现了这种“平衡”,意味着本应该后台的操作,就已经影响了业务应用,属于有损失的平衡。</p>
</blockquote><p><img src="https://static001.geekbang.org/resource/image/ce/d9/ce7f4e35916ed1aa49206a53a0547bd9.jpg" alt=""></p>
</div>
</div>
</div>
<div data-v-87ffcada="" class="article-comments pd"><h2 data-v-87ffcada=""><span
data-v-87ffcada="">精选留言</span></h2>
<ul data-v-87ffcada="">
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/4f/78/c3d8ecb0.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">undifined</span>
</div>
<div class="bd">老师,有几个问题:<br>1.Truncate 会释放表空间吗<br>2.重建表的时候如果没有数据更新,有没有可能产生页分裂和空洞<br>3.页分裂是发生在索引还是数据上<br>4.应用 row log 的过程会不会再次产生页分裂和空洞<br>5.不影响增删改,就是 Online;相对 Server层没有新建临时表,就是 inplace,这里怎么判断是不是相对 Server 层没有新建临时表<br>辛苦老师解答一下,谢谢老师 <br></div>
<span class="time">2018-12-12 10:41</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">1. Truncate 可以理解为drop+create<br>2. Online 可以认为没有<br>3. 数据也是索引哦<br>4. 可能会<br>5. 好问题,我放到明天答疑部分</p>
<p class="reply-time">2018-12-12 11:16</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/63/70/0b7b5cda.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username"></span>
</div>
<div class="bd">麻烦咨询个问题,“在图 3 中,我们把表 A 中的数据导出来的存放位置叫作 tmp_table。这是一个临时表,是在 server 层创建的。”<br>在server层创建的表也是将A表数据copy到了临时表,为什么在空间不够用时就没有问题,而inplace在InnoDB执行则会再占用一份存储?<br> <br></div>
<span class="time">2018-12-13 11:07</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">额,<br><br>Copy的时候肯定更要的…<br><br>这里特别指出来,是因为大多数人很容易理解copy需要临时空间,但是误以为inplace不需要<br><br><br>Anyway,好问题 😄</p>
<p class="reply-time">2018-12-13 18:13</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/9b/a4/a52a637d.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">陈飞</span>
</div>
<div class="bd">老师,请问下分布式ID(雪花算法生成的ID)生成的索引会比自增长的ID性能低吗?<br><br>雪花算法生成的ID是越来越大的,但不是逐渐递增,长度用的的bitint,麻烦解答下,非常感谢。 <br></div>
<span class="time">2018-12-13 13:57</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">好问题。<br><br><br>性能一样的,没有一定要“连续”,只要是递增</p>
<p class="reply-time">2018-12-13 18:11</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/36/d2/c7357723.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">发条橙子 。</span>
</div>
<div class="bd">老师 , 我的确实是 5.7 版本。我今天看了些关于 online ddl的文章 ,再结合表锁那章评论的内容,有几个点还想确认一下 ,希望老师能解答一下 。<br><br>1. 是不是 5.6 之后 所有的 alter 操作(增删字段、增删索引等)都是支持 online ddl <br><br>2. 如果 alter 都是 online ddl 那么是不是如果 alter操作 获取到mdl写锁 时, 后面的 查询需要mdl读锁会暂时阻塞, 但是mdl会马上降为读锁 ,后面的操作会继续进行不会堵塞 。等再升到写锁 ,后面操作又会暂时阻塞。 <br><br>3. 当 alter 降到mdl 读锁时 , 这时候可以新增数据么 , mdl表级读锁 不会影响到 insert 或者 update的行锁么 <br><br>4. 如果将 alter 操作显式的放到事务里 ,事务不提交 , 另一个事务查询的时候会查询到alter 操作后的表结构 , 比如新增了一个字段。这个是什么原因 ,是否打破了 mvcc 的定义呢 <br></div>
<span class="time">2018-12-13 23:49</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">1. 不是哦,我文章里说的加全文索引就不online<br><br>2. 对,这两个暂时,都是时间很短的<br><br>3. 是,DML语句加的是MDL读锁,读读不冲突<br><br>4. 好问题 , 不过alter table 语句会默认提交前面的事务,然后自己独立执行😄</p>
<p class="reply-time">2018-12-14 00:36</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="http://thirdwx.qlogo.cn/mmopen/vi_32/mcibngvIYnyDbzWPrWu0hD6WvZzjuiawXTSeLQibMJxa7gMtL7RrmT5Qia0esMJSlSLAKC5TC5JpHquKgBNgE8Uhrg/132" class="avatar">
<div class="info">
<div class="hd"><span class="username">飞翔</span>
</div>
<div class="bd">我想到的其中一种可能:<br>本来就很紧凑,没能整出多少剩余空间。<br>重新收缩的过程中,页会按90%满的比例来重新整理页数据(10%留给UPDATE使用),<br>未整理之前页已经占用90%以上,收缩之后,文件就反而变大了。 <br></div>
<span class="time">2018-12-12 11:16</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">一个漂亮的答案</p>
<p class="reply-time">2018-12-12 11:43</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/e8/45/c58cb283.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">帆帆帆帆帆帆帆帆</span>
</div>
<div class="bd">@undifined怎么判断是不是相对 Server 层没有新建临时表。一个最直观的判断方法是看命令执行后影响的行数,没有新建临时表的话新建的行数是0。 <br></div>
<span class="time">2018-12-12 14:41</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">👍🏿,下一篇答疑直接贴你答案😄</p>
<p class="reply-time">2018-12-12 17:56</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/f8/70/f3a33a14.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">某、人</span>
</div>
<div class="bd">通过第10期的课后思考题学习到如果delete的数据还会被用于MVCC,那么该数据页(二级索引和聚簇索引)上的记录不会被物理删除,是被标记删除。只有当该事务不会用于mvcc了,才可以被purge线程把之前标记删除的数据真正删除掉.但是即便数据物理删除了,磁盘空间也不会返回给操作系统.可以通过show table status like &#39;t&#39;;观察data_free来预估该表的碎片。如果过大,可以用alter table t engine=innodb来清除<br>我有几个问题请教下老师:<br>1.inplace相对于其他在线改表软件,多了MDL X锁.既然都是通过临时表&#47;文件来做,为什么一开始要上MDL X锁?<br>2.gh-ost使用binlog来做同步,假设从position 1开始,先lock S前面1000条数据做cp,这时有事务对后面1000条数据做了修改或者插入。等cp后面这个1000条时,会把修改好的数据cp到临时表.最后又应用binlog,那么这相当于做了两次操作,请问这部分数据是怎么处理的?<br>3.online会把过程中对表的操作记录在一个(row log)中,那么中途这些DML事务,是怎么判定的commit?我做测试,中途这些事务都是成功的。但是有在做online DDL快完了,commit那个阶段,DDL报唯一键冲突,这又是什么原因造成的啊?我没有模拟出来这个例子 <br></div>
<span class="time">2018-12-13 20:26</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">1. 确保没有启发请求在用这个表<br><br>2. Binlog设置为row格式,幂等的<br><br>3. 这个我觉得其实是bug,就没提。你在DDL期间,往原表插入一个已经存在相同主键的一行试试</p>
<p class="reply-time">2018-12-13 21:51</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/07/1e/bdbe93f4.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">尘封</span>
</div>
<div class="bd">老师,请教一个问题,和本文无关,既然mysql支持了打包数据排序模式,能够更紧凑的分配内存进行排序,那定义表结构的时候,varchar(10)存储hello和varchar(100)存储hello的优势在哪里呢?谢谢 <br></div>
<span class="time">2018-12-12 07:32</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">你这个问题放在第16篇问就刚刚好了。<br><br>以前不支持紧凑排序的时候有,现在没啥了差别了,小于256都差不多</p>
<p class="reply-time">2018-12-12 10:47</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/11/a2/97c0de02.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">V。</span>
</div>
<div class="bd">可能性有两个。<br>1. 生成临时表过程中,row log中新增的数据较多,导致表的行数变多。<br>2. 生成临时表过程中,row log中有部分插入和删除操作会产生“空洞”。<br>个人感觉,第一种情况,突然多了高于1%的数据,比较少见;但第二种情况,在某些业务中,经常出现。 <br></div>
<span class="time">2018-12-12 09:46</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="" class="avatar">
<div class="info">
<div class="hd"><span class="username">库淘淘</span>
</div>
<div class="bd">alter table A engine=InnoDB 中由写锁降为读锁。有个疑问 为何不直接就加个MDL读锁 ,这样DDL 也执行不了,应用redo 替换文件后释放读锁即可 <br></div>
<span class="time">2018-12-13 16:04</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">如果有别的线程正在读这个表的数据,得等下</p>
<p class="reply-time">2018-12-13 18:07</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/df/e7/e3c450c2.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">lionetes</span>
</div>
<div class="bd">在alter table engine =innodb 未完成前,做了DML 操作, 并且是在已经重构完的数据引起的DML操作,产生了空洞. 导致变大 重构未处理的数据 即使产生了 空洞,到100% 后也能清理碎片空间.<br><br>truncate table 里面的 数据 不产生 binlog,无法恢复, 如果速度上面来讲 还是drop table 更快. 但对于 超大的table 做drop, truncate 时候也是很危险了,容易整个数据库 hang 住,因为要对 buffer pool 中对应的页面清除, 可以对ibd 文件做 ln 操作生成 ibd.hdlk 然后 rm -f ibd 最后 drop table 会很快<br><br>对经常delete 数据的表 用以前讲的 循环删除 方法,来删除 也是 不错的. 当然要根据情况做 碎片整理 <br></div>
<span class="time">2018-12-12 22:34</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/e8/45/c58cb283.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">帆帆帆帆帆帆帆帆</span>
</div>
<div class="bd">执行完成后,空间不仅没变小,还稍微大了一点儿。比较常见的情况是表上只有insert,没有update的情况,如一些存放历史操作记录的表。 <br></div>
<span class="time">2018-12-12 14:42</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/41/f7/277f14bb.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">wang chen wen</span>
</div>
<div class="bd">optimize table t 等于 recreate+analyze<br>老师请教个问题recreate出来应该是几乎全新的,analyze的必要性? <br></div>
<span class="time">2018-12-12 09:45</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">好问题,这个得是比较极端的情况下才有必要,所以我比较喜欢直接用alter </p>
<p class="reply-time">2018-12-12 10:30</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/12/e9/29/629d9bb0.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">天王</span>
</div>
<div class="bd"> delete删除表数据,只是打上一个可复用标记,如果是数据页上一部分数据打上标记,如果按照自增主键insert数据,那表空间的数据不会复用,如果是整个数据页的所有数据打上标记,那么可以复用。2个3相临的数据页,如果空洞太多,合并成一个页,另外一个可以标记复用。重建表可以减少空洞,文件大小可以减小,本质上是通过,创建临时文件,将数据在临时文件上,重建一份,重建过程,按照顺序插入,极大减少了黑洞,数据都拷贝到临时文件以后,会有删除原来文件,切换到新文件。文件会减小了。<br><br><br> <br></div>
<span class="time">2018-12-12 09:14</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">👍🏿<br></p>
<p class="reply-time">2018-12-12 10:32</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/cb/50/66d0bd7f.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">杰之7</span>
</div>
<div class="bd">通过这一节的阅读学习,了解了删除表中的数据以后,表的大小并没有减少,这种现象我们叫做空洞,对于增删改都会产生这种现象。为什么会是这样,我想是计算机系统或许内存方面的内容。<br><br>对于这种现象,老师给予的解决方法是重建表,就是将原表数据重新建立在一张表。同时在高版本Mysql的Innodb支持online操作,同时,老师解释了onplace和inplace的区别。<br><br>中途有两个礼拜没有跟上进度学习,很惭愧,接下来一月会尽快跟上老师的步伐。 <br></div>
<span class="time">2019-01-10 13:21</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/12/be/d4/ff1c1319.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">金龟</span>
</div>
<div class="bd">老师,请教个问题,在innodb中是不是b+树的每个节点都是一页,比如最上层的根节点就是一页。下层有5个节点就是5页。 <br></div>
<span class="time">2018-12-30 11:45</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">是的</p>
<p class="reply-time">2018-12-30 19:31</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/e3/4b/5046906a.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">海曙云崖</span>
</div>
<div class="bd">怎么判断online DDL 的阶段是在MDL还是读锁阶段呢 <br></div>
<span class="time">2018-12-26 15:10</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">Show processlist可以看到<br><br>不过MDL锁阶段很短</p>
<p class="reply-time">2018-12-26 17:06</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/ed/d2/e3ae7ddd.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">三木禾</span>
</div>
<div class="bd">数据页A满了,随机插入一条数据,不得不申请一个新的数据页,这时候数据页A会留下空洞,我的问题是,既然满了,为什么还有空洞呢? <br></div>
<span class="time">2018-12-24 15:18</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">申请新页B,把一部分数据从A挪到B,A就空出一些</p>
<p class="reply-time">2018-12-24 16:20</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/e0/25/d87b1c9b.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">zzkkll99</span>
</div>
<div class="bd">老师我想问一下,为什么对表结构进行修改要读原数据。不可以直接修改吗 <br></div>
<span class="time">2018-12-20 17:28</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">你说的原数据是说表里的数据吗?<br><br>MySQL 官方版本还不支持只改表结构😓</p>
<p class="reply-time">2018-12-20 18:07</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKVIjh4T1akib7wAQXiaMmTRVe89bT3tBAeSdFflCQSWjDZQOs5jeBEWLC1GyFshHjvhsIZKArO6ichw/132" class="avatar">
<div class="info">
<div class="hd"><span class="username">壹口尘埃</span>
</div>
<div class="bd">网上找到一个Inplace和Online的区别,写的挺好的,贴出来方便大家理解:<br>MySQL各版本,对于add Index的处理方式是不同的,主要有三种:<br><br>(1)Copy Table方式<br>这是InnoDB最早支持的创建索引的方式。顾名思义,创建索引是通过临时表拷贝的方式实现的。<br><br>新建一个带有新索引的临时表,将原表数据全部拷贝到临时表,然后Rename,完成创建索引的操作。<br><br>这个方式创建索引,创建过程中,原表是可读的。但是会消耗一倍的存储空间。<br><br>(2)Inplace方式<br>这是原生MySQL 5.5,以及innodb_plugin中提供的创建索引的方式。所谓Inplace,也就是索引创建在原表上直接进行,不会拷贝临时表。相对于Copy Table方式,这是一个进步。<br><br>Inplace方式创建索引,创建过程中,原表同样可读的,但是不可写。<br><br>(3)Online方式<br>这是MySQL 5.6.7中提供的创建索引的方式。无论是Copy Table方式,还是Inplace方式,创建索引的过程中,原表只能允许读取,不可写。对应用有较大的限制,因此MySQL最新版本中,InnoDB支持了所谓的Online方式创建索引。<br><br>InnoDB的Online Add Index,首先是Inplace方式创建索引,无需使用临时表。在遍历聚簇索引,收集记录并插入到新索引的过程中,原表记录可修改。而修改的记录保存在Row Log中。当聚簇索引遍历完毕,并全部插入到新索引之后,重放Row Log中的记录修改,使得新索引与聚簇索引记录达到一致状态。<br><br>与Copy Table方式相比,Online Add Index采用的是Inplace方式,无需Copy Table,减少了空间开销;与此同时,Online Add Index只有在重放Row Log最后一个Block时锁表,减少了锁表的时间。<br><br>与Inplace方式相比,Online Add Index吸收了Inplace方式的优势,却减少了锁表的时间。 <br></div>
<span class="time">2018-12-19 14:40</span>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/gingermoon/mysql45.git
git@gitee.com:gingermoon/mysql45.git
gingermoon
mysql45
mysql45
master

搜索帮助