代码拉取完成,页面将自动刷新
同步操作将从 funnylog/mysql45 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
<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">
42讲grant之后要跟着flushprivileges吗
</h1>
<div data-v-87ffcada="" class="article-content typo common-content pd"><img data-v-87ffcada=""
src="https://static001.geekbang.org/resource/image/da/b2/da36874cb2adba5ac984cebc448aceb2.jpg">
<div>
<audio controls="controls" height="100" width="100">
<source src="42讲grant之后要跟着flushprivileges吗.mp3" type="audio/mp3" />
<embed height="100" width="100" src="42讲grant之后要跟着flushprivileges吗.mp3" />
</audio>
</div>
<div data-v-87ffcada="" id="article-content" class="">
<div class="text">
<p>在MySQL里面,grant语句是用来给用户赋权的。不知道你有没有见过一些操作文档里面提到,grant之后要马上跟着执行一个flush privileges命令,才能使赋权语句生效。我最开始使用MySQL的时候,就是照着一个操作文档的说明按照这个顺序操作的。</p><p>那么,grant之后真的需要执行flush privileges吗?如果没有执行这个flush命令的话,赋权语句真的不能生效吗?</p><p>接下来,我就先和你介绍一下grant语句和flush privileges语句分别做了什么事情,然后再一起来分析这个问题。</p><p>为了便于说明,我先创建一个用户:</p><pre><code>create user 'ua'@'%' identified by 'pa';
</code></pre><p>这条语句的逻辑是创建一个用户’ua’@’%’,密码是pa。注意,在MySQL里面,用户名(user)+地址(host)才表示一个用户,因此 ua@ip1 和 ua@ip2代表的是两个不同的用户。</p><p>这条命令做了两个动作:</p><ol>
<li>
<p>磁盘上,往mysql.user表里插入一行,由于没有指定权限,所以这行数据上所有表示权限的字段的值都是N;</p>
</li>
<li>
<p>内存里,往数组acl_users里插入一个acl_user对象,这个对象的access字段值为0。</p>
</li>
</ol><p>图1就是这个时刻用户ua在user表中的状态。</p><!-- [[[read_end]]] --><p><img src="https://static001.geekbang.org/resource/image/7e/35/7e75bbfbca0cb932e1256941c99d5f35.png" alt=""></p><center><span class="reference">图1 mysql.user 数据行</span></center><p>在MySQL中,用户权限是有不同的范围的。接下来,我就按照用户权限范围从大到小的顺序依次和你说明。</p><h1>全局权限</h1><p>全局权限,作用于整个MySQL实例,这些权限信息保存在mysql库的user表里。如果我要给用户ua赋一个最高权限的话,语句是这么写的:</p><pre><code>grant all privileges on *.* to 'ua'@'%' with grant option;
</code></pre><p>这个grant命令做了两个动作:</p><ol>
<li>
<p>磁盘上,将mysql.user表里,用户’ua’@’%'这一行的所有表示权限的字段的值都修改为‘Y’;</p>
</li>
<li>
<p>内存里,从数组acl_users中找到这个用户对应的对象,将access值(权限位)修改为二进制的“全1”。</p>
</li>
</ol><p>在这个grant命令执行完成后,如果有新的客户端使用用户名ua登录成功,MySQL会为新连接维护一个线程对象,然后从acl_users数组里查到这个用户的权限,并将权限值拷贝到这个线程对象中。之后在这个连接中执行的语句,所有关于全局权限的判断,都直接使用线程对象内部保存的权限位。</p><p>基于上面的分析我们可以知道:</p><ol>
<li>
<p>grant 命令对于全局权限,同时更新了磁盘和内存。命令完成后即时生效,接下来新创建的连接会使用新的权限。</p>
</li>
<li>
<p>对于一个已经存在的连接,它的全局权限不受grant命令的影响。</p>
</li>
</ol><p>需要说明的是,<strong>一般在生产环境上要合理控制用户权限的范围</strong>。我们上面用到的这个grant语句就是一个典型的错误示范。如果一个用户有所有权限,一般就不应该设置为所有IP地址都可以访问。</p><p>如果要回收上面的grant语句赋予的权限,你可以使用下面这条命令:</p><pre><code>revoke all privileges on *.* from 'ua'@'%';
</code></pre><p>这条revoke命令的用法与grant类似,做了如下两个动作:</p><ol>
<li>
<p>磁盘上,将mysql.user表里,用户’ua’@’%'这一行的所有表示权限的字段的值都修改为“N”;</p>
</li>
<li>
<p>内存里,从数组acl_users中找到这个用户对应的对象,将access的值修改为0。</p>
</li>
</ol><h1>db权限</h1><p>除了全局权限,MySQL也支持库级别的权限定义。如果要让用户ua拥有库db1的所有权限,可以执行下面这条命令:</p><pre><code>grant all privileges on db1.* to 'ua'@'%' with grant option;
</code></pre><p>基于库的权限记录保存在mysql.db表中,在内存里则保存在数组acl_dbs中。这条grant命令做了如下两个动作:</p><ol>
<li>
<p>磁盘上,往mysql.db表中插入了一行记录,所有权限位字段设置为“Y”;</p>
</li>
<li>
<p>内存里,增加一个对象到数组acl_dbs中,这个对象的权限位为“全1”。</p>
</li>
</ol><p>图2就是这个时刻用户ua在db表中的状态。</p><p><img src="https://static001.geekbang.org/resource/image/32/2e/32cd61ee14ad2f370e1de0fb4e39bb2e.png" alt=""></p><center><span class="reference">图2 mysql.db 数据行</span></center><p>每次需要判断一个用户对一个数据库读写权限的时候,都需要遍历一次acl_dbs数组,根据user、host和db找到匹配的对象,然后根据对象的权限位来判断。</p><p>也就是说,grant修改db权限的时候,是同时对磁盘和内存生效的。</p><p>grant操作对于已经存在的连接的影响,在全局权限和基于db的权限效果是不同的。接下来,我们做一个对照试验来分别看一下。</p><p><img src="https://static001.geekbang.org/resource/image/ae/c7/aea26807c8895961b666a5d96b081ac7.png" alt=""></p><center><span class="reference">图3 权限操作效果</span></center><p>需要说明的是,图中set global sync_binlog这个操作是需要super权限的。</p><p>可以看到,虽然用户ua的super权限在T3时刻已经通过revoke语句回收了,但是在T4时刻执行set global的时候,权限验证还是通过了。这是因为super是全局权限,这个权限信息在线程对象中,而revoke操作影响不到这个线程对象。</p><p>而在T5时刻去掉ua对db1库的所有权限后,在T6时刻session B再操作db1库的表,就会报错“权限不足”。这是因为acl_dbs是一个全局数组,所有线程判断db权限都用这个数组,这样revoke操作马上就会影响到session B。</p><p>这里在代码实现上有一个特别的逻辑,如果当前会话已经处于某一个db里面,之前use这个库的时候拿到的库权限会保存在会话变量中。</p><p>你可以看到在T6时刻,session C和session B对表t的操作逻辑是一样的。但是session B报错,而session C可以执行成功。这是因为session C在T2 时刻执行的use db1,拿到了这个库的权限,在切换出db1库之前,session C对这个库就一直有权限。</p><h1>表权限和列权限</h1><p>除了db级别的权限外,MySQL支持更细粒度的表权限和列权限。其中,表权限定义存放在表mysql.tables_priv中,列权限定义存放在表mysql.columns_priv中。这两类权限,组合起来存放在内存的hash结构column_priv_hash中。</p><p>这两类权限的赋权命令如下:</p><pre><code>create table db1.t1(id int, a int);
grant all privileges on db1.t1 to 'ua'@'%' with grant option;
GRANT SELECT(id), INSERT (id,a) ON mydb.mytbl TO 'ua'@'%' with grant option;
</code></pre><p>跟db权限类似,这两个权限每次grant的时候都会修改数据表,也会同步修改内存中的hash结构。因此,对这两类权限的操作,也会马上影响到已经存在的连接。</p><p>看到这里,你一定会问,看来grant语句都是即时生效的,那这么看应该就不需要执行flush privileges语句了呀。</p><p>答案也确实是这样的。</p><p>flush privileges命令会清空acl_users数组,然后从mysql.user表中读取数据重新加载,重新构造一个acl_users数组。也就是说,以数据表中的数据为准,会将全局权限内存数组重新加载一遍。</p><p>同样地,对于db权限、表权限和列权限,MySQL也做了这样的处理。</p><p>也就是说,如果内存的权限数据和磁盘数据表相同的话,不需要执行flush privileges。而如果我们都是用grant/revoke语句来执行的话,内存和数据表本来就是保持同步更新的。</p><p><strong>因此,正常情况下,grant命令之后,没有必要跟着执行flush privileges命令。</strong></p><h1>flush privileges使用场景</h1><p>那么,flush privileges是在什么时候使用呢?显然,当数据表中的权限数据跟内存中的权限数据不一致的时候,flush privileges语句可以用来重建内存数据,达到一致状态。</p><p>这种不一致往往是由不规范的操作导致的,比如直接用DML语句操作系统权限表。我们来看一下下面这个场景:</p><p><img src="https://static001.geekbang.org/resource/image/90/ec/9031814361be42b7bc084ad2ab2aa3ec.png" alt=""></p><center><span class="reference">图4 使用flush privileges</span></center><p>可以看到,T3时刻虽然已经用delete语句删除了用户ua,但是在T4时刻,仍然可以用ua连接成功。原因就是,这时候内存中acl_users数组中还有这个用户,因此系统判断时认为用户还正常存在。</p><p>在T5时刻执行过flush命令后,内存更新,T6时刻再要用ua来登录的话,就会报错“无法访问”了。</p><p>直接操作系统表是不规范的操作,这个不一致状态也会导致一些更“诡异”的现象发生。比如,前面这个通过delete语句删除用户的例子,就会出现下面的情况:</p><p><img src="https://static001.geekbang.org/resource/image/dd/f1/dd625b6b4eb2dcbdaac73648a1af50f1.png" alt=""></p><center><span class="reference">图5 不规范权限操作导致的异常</span></center><p>可以看到,由于在T3时刻直接删除了数据表的记录,而内存的数据还存在。这就导致了:</p><ol>
<li>
<p>T4时刻给用户ua赋权限失败,因为mysql.user表中找不到这行记录;</p>
</li>
<li>
<p>而T5时刻要重新创建这个用户也不行,因为在做内存判断的时候,会认为这个用户还存在。</p>
</li>
</ol><h1>小结</h1><p>今天这篇文章,我和你介绍了MySQL用户权限在数据表和内存中的存在形式,以及grant和revoke命令的执行逻辑。</p><p>grant语句会同时修改数据表和内存,判断权限的时候使用的是内存数据。因此,规范地使用grant和revoke语句,是不需要随后加上flush privileges语句的。</p><p>flush privileges语句本身会用数据表的数据重建一份内存权限数据,所以在权限数据可能存在不一致的情况下再使用。而这种不一致往往是由于直接用DML语句操作系统权限表导致的,所以我们尽量不要使用这类语句。</p><p>另外,在使用grant语句赋权时,你可能还会看到这样的写法:</p><pre><code>grant super on *.* to 'ua'@'%' identified by 'pa';
</code></pre><p>这条命令加了identified by ‘密码’, 语句的逻辑里面除了赋权外,还包含了:</p><ol>
<li>
<p>如果用户’ua’@’%'不存在,就创建这个用户,密码是pa;</p>
</li>
<li>
<p>如果用户ua已经存在,就将密码修改成pa。</p>
</li>
</ol><p>这也是一种不建议的写法,因为这种写法很容易就会不慎把密码给改了。</p><p>“grant之后随手加flush privileges”,我自己是这么使用了两三年之后,在看代码的时候才发现其实并不需要这样做,那已经是2011年的事情了。</p><p>去年我看到一位小伙伴这么操作的时候,指出这个问题时,他也觉得很神奇。因为,他和我一样看的第一份文档就是这么写的,自己也一直是这么用的。</p><p>所以,今天的课后问题是,请你也来说一说,在使用数据库或者写代码的过程中,有没有遇到过类似的场景:误用了很长时间以后,由于一个契机发现“啊,原来我错了这么久”?</p><p>你可以把你的经历写在留言区,我会在下一篇文章的末尾选取有趣的评论和你分享。感谢你的收听,也欢迎你把这篇文章分享给更多的朋友一起阅读。</p><h1>上期问题时间</h1><p>上期的问题是,MySQL解析statement格式的binlog的时候,对于load data命令,解析出来为什么用的是load data local。</p><p>这样做的一个原因是,为了确保备库应用binlog正常。因为备库可能配置了secure_file_priv=null,所以如果不用local的话,可能会导入失败,造成主备同步延迟。</p><p>另一种应用场景是使用mysqlbinlog工具解析binlog文件,并应用到目标库的情况。你可以使用下面这条命令 :</p><pre><code>mysqlbinlog $binlog_file | mysql -h$host -P$port -u$user -p$pwd
</code></pre><p>把日志直接解析出来发给目标库执行。增加local,就能让这个方法支持非本地的$host。</p><p>评论区留言点赞板:</p><blockquote>
<p>@poppy 、@库淘淘 两位同学提到了第一个场景;<br>
@王显伟 @lionetes 两位同学帮忙回答了 @undifined 同学的疑问,拷贝出来的文件要确保MySQL进程可以读。</p>
</blockquote><p><img src="https://static001.geekbang.org/resource/image/09/77/09c1073f99cf71d2fb162a716b5fa577.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>http://ww1.sinaimg.cn/large/d1885ed1ly1g0ab2twmjaj21gs0js78u.jpg <br></div>
<span class="time">2019-02-18 09:11</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">👍,优秀</p>
<p class="reply-time">2019-02-18 11:58</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/57/6e/dd0eee5f.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">夜空中最亮的星(华仔)</span>
</div>
<div class="bd">通过老师的讲解 flush privileges 这回彻底懂了,高兴😃 <br></div>
<span class="time">2019-02-18 16:55</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">👍</p>
<p class="reply-time">2019-02-19 09:17</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/e0/b9/bca7ff9a.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">way</span>
</div>
<div class="bd">写个比较小的点:在命令行查询数据需要行转列的时候习惯加个\G ; 比如slave slave stauts \G ; 后来发现 ; 是多余的。列几个常用的<br>\G 行转列并发送给 mysql server<br>\g 等同于 ;<br>\! 执行系统命令<br>\q exit<br>\c 清除当前SQL(不执行)<br>\s mysql status 信息<br>其他参考 \h <br></div>
<span class="time">2019-02-20 11:55</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">👍<br><br>我最开始使用MySQL的时候,就是不自然的在\G后面加分号<br>而且还看到报错,好紧张😆</p>
<p class="reply-time">2019-02-20 13:32</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/77/fd/c6619535.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">XD</span>
</div>
<div class="bd">老师,我刚说的是acl_db,是在db切换的时候,从acl_dbs拷贝到线程内部的?类似acl_user。<br><br>session a<br>drop user 'test'@'%';<br>create user 'test'@'%' identified by '123456';<br>grant SELECT,UPDATE on gt.* to 'test'@'%';<br><br>session b 使用test登录<br>use gt;<br><br>session a<br>revoke SELECT,UPDATE on gt.* from 'test'@'%';<br><br>session b<br>show databases; //只能看到information_schema库<br>use gt; // Access denied for user 'test'@'%' to database 'gt'<br>show tables; //可以看到gt库中所有的表<br>select/update //操作都正常 <br></div>
<span class="time">2019-02-18 23:28</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">你说的对,我刚翻代码确认了下,确实是特别对“当前db”有一个放过的逻辑。<br><br>多谢指正。我勘误下。</p>
<p class="reply-time">2019-02-19 21:14</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/14/57/96/b65bdf43.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">萤火虫</span>
</div>
<div class="bd">坚持到最后 为老师打call <br></div>
<span class="time">2019-02-20 16:52</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">👍<br>是真爱</p>
<p class="reply-time">2019-02-20 18:44</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/ef/af/ba786593.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">wljs</span>
</div>
<div class="bd">老师我想问个问题 我们公司一个订单表有110个字段 想拆分成两个表 第一个表放经常查的字段 第二个表放不常查的 现在程序端不想改sql,数据库端来实现 当查询字段中 第一个表不存在 就去关联第二个表查出数据 db能实现不? <br></div>
<span class="time">2019-02-19 23:51</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/12/a1/a5/2100367c.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">舜</span>
</div>
<div class="bd">老师,介绍完了order by后能不能继续介绍下group by的原理?等了好久了,一直想继续在order by基础上理解下group by,在使用过程中两者在索引利用上很相近,性能考虑也类似 <br></div>
<span class="time">2019-02-19 12:58</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">37篇讲了group by的,你看下<br><br>还有问再提出来😆</p>
<p class="reply-time">2019-02-19 15:39</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/0f/a1/e6/50da1b2d.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">旭东</span>
</div>
<div class="bd">老师请教一个问题:MySQL 表设计时列表顺序对MySQL性能的影响大吗?对表的列顺序有什么建议吗? <br></div>
<span class="time">2019-02-18 23:16</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">没有影响<br><br>建议就是每次如果要加列都加到最后一列😆</p>
<p class="reply-time">2019-02-19 09:22</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/77/fd/c6619535.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">XD</span>
</div>
<div class="bd">老师,实际测试了下。<br>两个会话ab,登陆账号都为user。a中给user授予db1的select、update权限,b切换到db1,可以正常增改。然后a中回收该用户的db权限,b会话中的用户还是可以进行增改操作的。<br>我发现用户的db权限好像是在切换数据库的时候刷新的,只要不切换,grant操作并不会产生作用,所以acl_db是否也是维护在线程内部的呢?<br><br>以及,权限检验应该是在优化器的语义分析里进行的吧? <br></div>
<span class="time">2019-02-18 22:25</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">acl_dbs是全局数组<br><br>把你使用sql语句,和语句序列发一下哦<br><br>类似按照时间顺序<br>session a:<br> xxx<br> xxx<br>session b:<br> xxxx<br>session a:<br> xxxx<br>这样</p>
<p class="reply-time">2019-02-18 22:59</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="http://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJCscgdVibmoPyRLRaicvk6rjTJxePZ6VFHvGjUQvtfhCS6kO4OZ1AVibbhNGKlWZmpEFf2yA6ptsqHw/132" class="avatar">
<div class="info">
<div class="hd"><span class="username">夹心面包</span>
</div>
<div class="bd">我在此分享一个授权库的小技巧, 如果需要授权多个库,库名还有规律,比如 db_201701 db_201702<br>可以采用正则匹配写一条 grant on db______,每一个_代表一个字符.这样避免了多次授权,简化了过程。我们线上已经采用 <br></div>
<span class="time">2019-02-18 17:09</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">是的,MySQL还支持 % 赋权,%表示匹配任意字符串,<br>比如<br>grant all privileges on `db%`.* to ... 表示所有以db为前缀的库。<br><br>不过。。。我比较不建议这么用😅</p>
<p class="reply-time">2019-02-19 10:33</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/1c/5c/f5f24221.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">发芽的紫菜</span>
</div>
<div class="bd">老师,联合索引的数据结构是怎么样的?到底是怎么存的?看了前面索引两章,还是不太懂,留言里老师说会在后面章节会讲到,但我也没看到,所以来此问一下?老师能否画图讲解一下 <br></div>
<span class="time">2019-02-18 15:42</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">联合索引就是两个字段拼起来作索引<br><br>比如一个索引如果定义为(f1,f2),<br>在数据上,就是f1的值之后跟着f2的值。<br>查找的时候,比如执行 where f1=M and f2=N, 也是把M,N拼起来,去索引树查找</p>
<p class="reply-time">2019-02-18 23:03</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/e9/8e/6dc15a91.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">晨思暮语</span>
</div>
<div class="bd">丁老师,您好:<br>关于上一章我留言的疑问,我重新整理了下。就是第十五章中老师留的思考题。<br>我模拟了老师的实验,结果有点出入,请老师帮忙看看,谢谢!<br>基础环境:<br>mysql> select version();<br>+------------+<br>| version() |<br>+------------+<br>| 5.7.22-log |<br>+------------+<br>1 row in set (0.00 sec)<br><br>mysql> show variables like '%tx%';<br>+---------------+-----------------+<br>| Variable_name | Value |<br>+---------------+-----------------+<br>| tx_isolation | REPEATABLE-READ |<br>| tx_read_only | OFF |<br>+---------------+-----------------+<br>2 rows in set (0.00 sec)<br>模拟实验:<br>session A: <br>mysql> begin; <br>mysql> select * from t; <br>+----+------+ <br>| id | a | <br>+----+------+ <br>| 1 | 2 | <br>+----+------+ <br>1 row in set (0.00 sec) <br><br>session B: <br>mysql> update t set a=3 where id=1; <br>Query OK, 1 row affected (0.00 sec) <br>Rows matched: 1 Changed: 1 Warnings: 0 <br><br>SESSION A: <br>mysql> update t set a=3 where id=1; <br>Query OK, 0 rows affected (0.00 sec) <br>Rows matched: 1 Changed: 0 Warnings: 0 <br>/*老师的实验显示为:1 rows affected*/ <br>mysql> select * from t where id=1; <br>+----+------+ <br>| id | a | <br>+----+------+ <br>| 1 | 2 | <br>+----+------+ <br>1 row in set (0.00 sec) <br>/*老师实验的查询结果为:1,3 */ <br></div>
<span class="time">2019-02-18 10:28</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="http://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJAibnPX9jW8kqLcIfibjic8GbkQkEUYyFKJkc39hZhibVlNrqwTjdLozkqibI2IwACd5YzofYickNxFnZg/132" class="avatar">
<div class="info">
<div class="hd"><span class="username">Sinyo</span>
</div>
<div class="bd">查一张大表,order_key字段值对应的最小createtime;<br>以前一直用方法一查数,后来同事说可以优化成方法二,查询效率比方法一高了几倍;<br>mysql特有的group by功能,没有group by的字段默认取查到的第一条记录;<br><br>方法一:<br>select distinct order_key<br> ,createtime<br> from (select order_key<br> ,min(createtime) createtime<br> from aaa<br> group by order_key) a<br> join aaa b<br> on a.order_key = b.order_key<br> and a.createtime = b.createtime<br><br>方法二:<br>select order_key<br> ,createtime<br> from (select order_key<br> ,createtime<br> FROM aaa<br> order by createtime<br> ) a<br> group by order_key <br></div>
<span class="time">2019-02-18 10:07</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">👍<br><br><br>这第二个写法跟:<br>select order_key ,createtime FROM aaa force index(createtime) group by order_key<br> 的逻辑语义相同吗?<br></p>
<p class="reply-time">2019-02-18 11:57</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/12/9b/a8/6a391c66.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">Leon📷</span>
</div>
<div class="bd">老师我使用delte删除用户,再创建用户都是失败,但是使用drop就可以了<br>mysql> create user 'ua'@'%' identified by 'L1234567890c-';<br>ERROR 1396 (HY000): Operation CREATE USER failed for 'ua'@'%'<br>mysql> drop user 'ua'@'%';<br>Query OK, 0 rows affected (0.00 sec)<br><br>mysql> create user 'ua'@'%' identified by 'L1234567890c-';<br>Query OK, 0 rows affected (0.01 sec)<br>是不是drop才会同时从内存和磁盘删除用户信息,但是delete只是从磁盘删除 <br></div>
<span class="time">2019-02-18 09:46</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">对,drop是同时操作磁盘和内存,<br>delete就是我们说的不规范操作</p>
<p class="reply-time">2019-02-18 23:00</p>
</div>
</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">众所周知,sql是不区分大小写的。然而,涉及插件的变量却不是这样;上次在配置一个插件的参数的时候,苦思良久……最后发现了这个问题。难受😭 <br></div>
<span class="time">2019-02-18 08:12</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">😆你说的是参数的名字,还是参数的值?<br></p>
<p class="reply-time">2019-02-18 09:16</p>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。