输入的查询SQL语句,是怎么样执行的?
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">摘要:输入一条语句,返回一个结果,却不<span style="color: black;">晓得</span>这条语句在 MySQL 内部的执行过程。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">本文分享自华为云社区《<a style="color: black;">一条<span style="color: black;">查找</span>SQL是<span style="color: black;">怎样</span>执行的-云社区-华为云</a>》,作者: 共饮一杯无 。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">执行如下SQL,<span style="color: black;">咱们</span>看到的只是输入一条语句,返回一个结果,却不<span style="color: black;">晓得</span>这条语句在 MySQL 内部的执行过程。</span></p>
<span style="color: black;">select</span> * <span style="color: black;">from</span> <span style="color: black;">where</span> <span style="color: black;">id</span> =<span style="color: black;">1</span>;<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/fce6a355d7ae43daa3d2383346438cfc~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1723347413&x-signature=FtdoMT0htY4zyH4IALBfHFGlPus%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">上图给出的是 MySQL 的基本架构示意图,从中你<span style="color: black;">能够</span>清楚地看到 SQL 语句在 MySQL 的各个功能模块中的执行过程。大体<span style="color: black;">来讲</span>,MySQL <span style="color: black;">能够</span>分为 Server 层和存储引擎层两部分。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Server 层<span style="color: black;">包含</span>连接器、<span style="color: black;">查找</span>缓存、分析器、优化器、执行器等,涵盖 MySQL 的大<span style="color: black;">都数</span>核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,<span style="color: black;">例如</span>存储过程、触发器、视图等。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。<span style="color: black;">此刻</span>最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本<span style="color: black;">起始</span><span style="color: black;">作为</span>了默认存储引擎。<span style="color: black;">亦</span><span style="color: black;">能够</span><span style="color: black;">经过</span>指定存储引擎的类型来<span style="color: black;">选取</span>别的引擎,<span style="color: black;">例如</span>在 create table 语句中<span style="color: black;">运用</span> engine=memory, 来指定<span style="color: black;">运用</span>内存引擎创建表。</span></p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/0221403d90c84b4f92954605a4ab13eb~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1723347413&x-signature=d7nGEfXNI00VMxMG7kYd61IoV68%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">一条SQL<span style="color: black;">查找</span>的完整执行流程如上图所示。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">Server服务层</h1>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">连接器</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">连接数据库最<span style="color: black;">起始</span>肯定是连接器。连接器负责跟客户端<span style="color: black;">创立</span>连接、获取权限、维持和管理连接。连接命令<span style="color: black;">通常</span>是这么写的:</span></p>
<span style="color: black;">mysql</span> -h<span style="color: black;">$ip</span> -P<span style="color: black;">$port</span> -u<span style="color: black;">$user</span> -p<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">输完命令之后,你就<span style="color: black;">必须</span>在交互对话里面输入<span style="color: black;">秘码</span>。虽然<span style="color: black;">秘码</span><span style="color: black;">亦</span><span style="color: black;">能够</span>直接跟在 -p 后面写在命令行中,但<span style="color: black;">这般</span>可能会<span style="color: black;">引起</span>你的<span style="color: black;">秘码</span><span style="color: black;">泄密</span>。<span style="color: black;">倘若</span>你连的是生产服务器,<span style="color: black;">剧烈</span><span style="color: black;">意见</span>你不要这么做。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">连接命令中的 mysql 是客户端工具,用来跟服务端<span style="color: black;">创立</span>连接。在完成经典的 TCP 握手后,连接器就要<span style="color: black;">起始</span>认证你的身份,这个时候用的<span style="color: black;">便是</span>你输入的用户名和<span style="color: black;">秘码</span>。</span></p><span style="color: black;"><span style="color: black;">倘若</span>用户名或<span style="color: black;">秘码</span>不对,你就会收到一个"</span><strong style="color: blue;"><span style="color: black;">Access denied for user</span></strong><span style="color: black;">"的错误,<span style="color: black;">而后</span>客户端程序结束执行。</span><span style="color: black;"><span style="color: black;">倘若</span>用户名<span style="color: black;">秘码</span>认证<span style="color: black;">经过</span>,连接器会到权限表里面查出你<span style="color: black;">持有</span>的权限。之后,这个连接里面的权限判断<span style="color: black;">规律</span>,都将依赖于此时读到的权限。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这就<span style="color: black;">寓意</span>着,一个用户成功<span style="color: black;">创立</span>连接后,即使你用管理员账号对这个用户的权限做了修改,<span style="color: black;">亦</span>不会影响<span style="color: black;">已然</span>存在连接的权限。修改完成后,<span style="color: black;">仅有</span>再新建的连接才会<span style="color: black;">运用</span>新的权限设置。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">连接完成后,<span style="color: black;">倘若</span>你<span style="color: black;">无</span>后续的动作,这个连接就<span style="color: black;">处在</span>空闲状态,你<span style="color: black;">能够</span>在 show processlist 命令中看到它。文本中这个图是 show processlist 的结果,其中的 Command 列<span style="color: black;">表示</span>为“Sleep”的这一行,就<span style="color: black;">暗示</span><span style="color: black;">此刻</span>系统里面有一个空闲连接。</span></p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/9a722af9446745df846745e9aaea2d11~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1723347413&x-signature=RCNJBRONtxf3hHbGiDTblRYyPog%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">客户端<span style="color: black;">倘若</span>太<span style="color: black;">长期</span>没动静,连接器就会自动将它断开。这个时间<span style="color: black;">是由于</span>参数 wait_timeout <span style="color: black;">掌控</span>的,默认值是 8 小时。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span>在连接被断开之后,客户端再次发送请求的话,就会收到一个错误提醒: Lost connection to MySQL server during query。<span style="color: black;">此时</span>候<span style="color: black;">倘若</span>你要继续,就<span style="color: black;">必须</span>重连,<span style="color: black;">而后</span>再执行请求了。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">数据库里面,长连接<span style="color: black;">指的是</span>连接成功后,<span style="color: black;">倘若</span>客户端<span style="color: black;">连续</span>有请求,则<span style="color: black;">始终</span><span style="color: black;">运用</span>同一个连接。短连接则<span style="color: black;">指的是</span>每次执行完很少的几次<span style="color: black;">查找</span>就断开连接,下次<span style="color: black;">查找</span>再重新<span style="color: black;">创立</span>一个。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">创立</span>连接的过程<span style="color: black;">一般</span>是比较<span style="color: black;">繁杂</span>的,<span style="color: black;">因此</span>我<span style="color: black;">意见</span>你在<span style="color: black;">运用</span>中要<span style="color: black;">尽可能</span>减少<span style="color: black;">创立</span>连接的动作,<span style="color: black;">亦</span><span style="color: black;">便是</span><span style="color: black;">尽可能</span><span style="color: black;">运用</span>长连接。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">然则</span><span style="color: black;">所有</span><span style="color: black;">运用</span>长连接后,你可能会<span style="color: black;">发掘</span>,有些时候 MySQL 占用内存涨得<span style="color: black;">尤其</span>快,这是<span style="color: black;">由于</span> MySQL 在执行过程中临时<span style="color: black;">运用</span>的内存是管理在连接对象里面的。这些资源会在连接断开的时候才释放。<span style="color: black;">因此</span><span style="color: black;">倘若</span>长连接累积下来,可能<span style="color: black;">引起</span>内存占用太大,被系统强行杀掉(OOM),从现象看<span style="color: black;">便是</span> MySQL <span style="color: black;">反常</span>重启了。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">怎么<span style="color: black;">处理</span>这个问题呢?你<span style="color: black;">能够</span><span style="color: black;">思虑</span>以下两种<span style="color: black;">方法</span>。</span></p><span style="color: black;"><span style="color: black;">定时</span>断开长连接。<span style="color: black;">运用</span>一段时间,<span style="color: black;">或</span>程序里面判断执行过一个占用内存的大查询后,断开连接,之后要<span style="color: black;">查找</span>再重连。</span><span style="color: black;"><span style="color: black;">倘若</span>你用的是 MySQL 5.7 或更新版本,<span style="color: black;">能够</span>在每次执行一个比<span style="color: black;">很强</span>的操作后,<span style="color: black;">经过</span>执行 mysql_reset_connection 来重新初始化连接资源。这个过程不<span style="color: black;">必须</span>重连和重新做权限验证,<span style="color: black;">然则</span>会将连接恢复到<span style="color: black;">刚才</span>创建完时的状态。</span>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">查找</span>缓存</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">连接<span style="color: black;">创立</span>完成后,你就<span style="color: black;">能够</span>执行 select 语句了。执行<span style="color: black;">规律</span>就会来到第二步:<span style="color: black;">查找</span>缓存。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">MySQL 拿到一个<span style="color: black;">查找</span>请求后,会先到<span style="color: black;">查找</span>缓存<span style="color: black;">瞧瞧</span>,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是<span style="color: black;">查找</span>的语句,value 是<span style="color: black;">查找</span>的结果。<span style="color: black;">倘若</span>你的<span style="color: black;">查找</span>能够直接在这个缓存中找到 key,<span style="color: black;">那样</span>这个 value 就会被直接返回给客户端。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span>语句不在<span style="color: black;">查找</span>缓存中,就会继续后面的执行<span style="color: black;">周期</span>。执行完成后,执行结果会被存入<span style="color: black;">查找</span>缓存中。你<span style="color: black;">能够</span>看到,<span style="color: black;">倘若</span><span style="color: black;">查找</span>命中缓存,MySQL 不<span style="color: black;">必须</span>执行后面的<span style="color: black;">繁杂</span>操作,就<span style="color: black;">能够</span>直接返回结果,这个效率会很高。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;"><span style="color: black;">然则</span>大<span style="color: black;">都数</span><span style="color: black;">状况</span>下我会<span style="color: black;">意见</span>你不要<span style="color: black;">运用</span><span style="color: black;">查找</span>缓存,为什么呢?<span style="color: black;">由于</span><span style="color: black;">查找</span>缓存<span style="color: black;">常常</span><span style="color: black;">坏处</span>大于利。</span></strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">查找</span>缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的<span style="color: black;">查找</span>缓存都会被清空。<span style="color: black;">因此呢</span>很可能你费劲地把结果存起来,还没<span style="color: black;">运用</span>呢,就被一个更新全清空了。<span style="color: black;">针对</span>更新压力大的数据库<span style="color: black;">来讲</span>,<span style="color: black;">查找</span>缓存的命中率会非常低。除非你的业务<span style="color: black;">便是</span>有一张静态表,很<span style="color: black;">长期</span>才会更新一次。<span style="color: black;">例如</span>,一个系统配置表,那这张表上的<span style="color: black;">查找</span>才适合<span style="color: black;">运用</span><span style="color: black;">查找</span>缓存。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">好在 MySQL <span style="color: black;">亦</span><span style="color: black;">供给</span>了这种“按需<span style="color: black;">运用</span>”的方式。你<span style="color: black;">能够</span>将参数 query_cache_type 设置成 DEMAND,<span style="color: black;">这般</span><span style="color: black;">针对</span>默认的 SQL 语句都不<span style="color: black;">运用</span><span style="color: black;">查找</span>缓存。而<span style="color: black;">针对</span>你确定要<span style="color: black;">运用</span><span style="color: black;">查找</span>缓存的语句,<span style="color: black;">能够</span>用 SQL_CACHE 显式指定,像下面这个语句<span style="color: black;">同样</span>:</span></p>
mysql> <span style="color: black;">select</span> SQL_CACHE * <span style="color: black;">from</span> T <span style="color: black;">where</span> ID=<span style="color: black;">10</span>;<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">必须</span><span style="color: black;">重视</span>的是,</span><strong style="color: blue;"><span style="color: black;">MySQL 8.0 版本直接将<span style="color: black;">查找</span>缓存的整块功能删掉了</span></strong><span style="color: black;">,<span style="color: black;">亦</span><span style="color: black;">便是</span>说 8.0 <span style="color: black;">起始</span>彻底<span style="color: black;">无</span>这个功能了。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">分析器</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span><span style="color: black;">无</span>命中<span style="color: black;">查找</span>缓存,就要<span style="color: black;">起始</span>真正执行语句了。<span style="color: black;">首要</span>,MySQL <span style="color: black;">必须</span><span style="color: black;">晓得</span>你要做什么,<span style="color: black;">因此呢</span><span style="color: black;">必须</span>对 SQL 语句做解析。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">分析器先会做“词法分析”。你输入的<span style="color: black;">是由于</span>多个字符串和空格<span style="color: black;">构成</span>的一条 SQL 语句,MySQL <span style="color: black;">必须</span>识别出里面的字符串分别是什么,<span style="color: black;">表率</span>什么。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">MySQL 从你输入的"select"这个关键字识别出来,这是一个<span style="color: black;">查找</span>语句。它<span style="color: black;">亦</span>要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">做完了这些识别以后,就要做“语法分析”。<span style="color: black;">按照</span>词法分析的结果,语法分析器会<span style="color: black;">按照</span>语法规则,判断你输入的这个 SQL 语句<span style="color: black;">是不是</span>满足 MySQL 语法。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span>你的语句不对,就会收到“</span><strong style="color: blue;"><span style="color: black;">You have an error in your SQL syntax</span></strong><span style="color: black;">”的错误提醒,<span style="color: black;">例如</span>下面这个语句 select 少打了开头的字母“s”。</span></p>
mysql> elect * from t <span style="color: black;">where</span> ID=<span style="color: black;">1</span>;
ERROR <span style="color: black;">1064</span> (<span style="color: black;">42000</span>): You have an error <span style="color: black;">in</span>your SQL syntax; check the manual that corresponds to your MySQL server version<span style="color: black;">for</span> the right syntax to <span style="color: black;">use</span> near <span style="color: black;">elect</span> * from t <span style="color: black;">where</span> ID=<span style="color: black;">1</span> at line <span style="color: black;">1</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">通常</span>语法错误会提示<span style="color: black;">第1</span>个<span style="color: black;">显现</span>错误的位置,<span style="color: black;">因此</span>你要关注的是紧接“use near”的内容。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">优化器</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">经过了分析器,MySQL 就<span style="color: black;">晓得</span>你要做什么了。在<span style="color: black;">起始</span>执行之前,还要先经过优化器的处理。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">优化器是在表里面有多个索引的时候,决定<span style="color: black;">运用</span>哪个索引;<span style="color: black;">或</span>在一个语句有多表<span style="color: black;">相关</span>(join)的时候,决定各个表的连接<span style="color: black;">次序</span>。<span style="color: black;">一般</span>两种执行<span style="color: black;">办法</span>的<span style="color: black;">规律</span>结果是<span style="color: black;">同样</span>的,<span style="color: black;">然则</span>执行的效率会有<span style="color: black;">区别</span>,而优化器的<span style="color: black;">功效</span><span style="color: black;">便是</span>决定<span style="color: black;">选取</span><span style="color: black;">运用</span>哪一个<span style="color: black;">方法</span>。优化器<span style="color: black;">周期</span>完成后,这个语句的执行<span style="color: black;">方法</span>就确定下来了,<span style="color: black;">而后</span>进入执行器<span style="color: black;">周期</span>。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">执行SQL<span style="color: black;">查找</span>的时候优化器<span style="color: black;">重点</span>执行如下任务:</span></p><span style="color: black;"><span style="color: black;">选取</span>最合适的索引;</span><span style="color: black;"><span style="color: black;">选取</span>表扫还是走索引;</span><span style="color: black;"><span style="color: black;">选取</span>表<span style="color: black;">相关</span><span style="color: black;">次序</span>;</span><span style="color: black;">优化 where 子句;</span><span style="color: black;">排除管理中无用表;</span><span style="color: black;">决定 order by 和 group by <span style="color: black;">是不是</span>走索引;</span><span style="color: black;">尝试<span style="color: black;">运用</span> inner join 替换 outer join;</span><span style="color: black;">简化子<span style="color: black;">查找</span>,决定结果缓存;</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">MySQL <span style="color: black;">查找</span>优化器有几个<span style="color: black;">目的</span>,<span style="color: black;">然则</span>其中最<span style="color: black;">重点</span>的<span style="color: black;">目的</span>是尽可能地<span style="color: black;">运用</span>索引,并且<span style="color: black;">运用</span>最严格的索引来消除尽可能多的数据行。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">优化器试图排除数据行的<span style="color: black;">原由</span>在于它排除数据行的速度越快,<span style="color: black;">那样</span>找到与<span style="color: black;">要求</span>匹配的数据行<span style="color: black;">亦</span>就越快。<span style="color: black;">倘若</span>能够<span style="color: black;">首要</span>进行最严格的测试,<span style="color: black;">查找</span>就<span style="color: black;">能够</span>执行地更快。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">执行器</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">MySQL <span style="color: black;">经过</span>分析器<span style="color: black;">晓得</span>了你要做什么,<span style="color: black;">经过</span>优化器<span style="color: black;">晓得</span>了该怎么做,于是就进入了执行器<span style="color: black;">周期</span>,<span style="color: black;">起始</span>执行语句。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">起始</span>执行的时候,要先判断一下你对这个表 T 有<span style="color: black;">无</span>执行<span style="color: black;">查找</span>的权限,<span style="color: black;">倘若</span><span style="color: black;">无</span>,就会返回<span style="color: black;">无</span>权限的错误,如下所示 (在工程实现上,<span style="color: black;">倘若</span>命中<span style="color: black;">查找</span>缓存,会在<span style="color: black;">查找</span>缓存返回结果的时候,做权限验证。<span style="color: black;">查找</span><span style="color: black;">亦</span>会在优化器之前调用 precheck 验证权限)。</span></p>
mysql> <span style="color: black;">select</span> * <span style="color: black;">from</span> T <span style="color: black;">where</span> ID=<span style="color: black;">10</span>;
ERROR <span style="color: black;">1142</span> (<span style="color: black;">42000</span>): SELECT command denied to user <span style="color: black;">b</span>@<span style="color: black;">localhost</span> <span style="color: black;">for</span> table <span style="color: black;">T</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span>有权限,就打开表继续执行。打开表的时候,执行器就会<span style="color: black;">按照</span>表的引擎定义,去<span style="color: black;">运用</span>这个引擎<span style="color: black;">供给</span>的接口。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">例如</span><span style="color: black;">咱们</span>这个例子中的表 T 中,ID 字段<span style="color: black;">无</span>索引,<span style="color: black;">那样</span>执行器的执行流程是<span style="color: black;">这般</span>的:</span></p><span style="color: black;">调用 InnoDB 引擎接口取这个表的<span style="color: black;">第1</span>行,判断 ID 值是不是 10,<span style="color: black;">倘若</span>不是则跳过,<span style="color: black;">倘若</span>是则将这行存在结果集中;</span><span style="color: black;">调用引擎接口取“下一行”,重复相同的判断<span style="color: black;">规律</span>,直到取到这个表的最后一行。</span><span style="color: black;">执行器将<span style="color: black;">以上</span>遍历过程中所有满足<span style="color: black;">要求</span>的行<span style="color: black;">构成</span>的记录集<span style="color: black;">做为</span>结果集返回给客户端。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">至此,这个语句就执行完<span style="color: black;">成为了</span>。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">针对</span>有索引的表,执行的<span style="color: black;">规律</span><span style="color: black;">亦</span>差不多。<span style="color: black;">第1</span>次调用的是“取满足<span style="color: black;">要求</span>的<span style="color: black;">第1</span>行”这个接口,之后循环取“满足<span style="color: black;">要求</span>的下一行”这个接口,这些接口都是引擎中<span style="color: black;">已然</span>定义好的。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">你会在数据库的慢<span style="color: black;">查找</span>日志中看到一个 rows_examined 的字段,<span style="color: black;">暗示</span>这个语句执行过程中扫描了多少行。这个值<span style="color: black;">便是</span>在执行器每次调用引擎获取数据行的时候累加的。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">在有些场景下,执行器调用一次,在引擎内部则扫描了多行,<span style="color: black;">因此呢</span></span><strong style="color: blue;"><span style="color: black;">引擎扫描行数跟 rows_examined 并不是完全相同的。</span></strong></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">存储引擎</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">经过</span> show engines;查看引擎类型,<span style="color: black;">能够</span>看出来要用到事务只能用InnoDB引擎类型</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">InnoDB存储引擎</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">InnoDB是MySQL的默认事务型引擎,<span style="color: black;">亦</span>是最重要、<span style="color: black;">运用</span>最广泛的存储引擎,并且有行级锁定和外键约束。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">它被设计用来处理<span style="color: black;">海量</span>的短期(short-lived)事务,短期事务大部分<span style="color: black;">状况</span>是正常提交,很少会被回滚。InnoDB的性能和自动崩溃恢复特性,使得它在非事务型存储的需求中<span style="color: black;">亦</span>很流行。除非有非常<span style="color: black;">尤其</span>的<span style="color: black;">原由</span><span style="color: black;">必须</span><span style="color: black;">运用</span>其他的存储引擎,否则应该优先<span style="color: black;">思虑</span>InnoDB引擎。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">InnoDB的适用场景/特性,有以下几种:</span></p><span style="color: black;">经常更新的表,适合处理多重并发的更新请求。</span><span style="color: black;">支持事务。</span><span style="color: black;"><span style="color: black;">能够</span>从<span style="color: black;">劫难</span>中恢复(<span style="color: black;">经过</span>bin-log日志等)。</span><span style="color: black;">外键约束。<span style="color: black;">仅有</span>他支持外键。</span><span style="color: black;">支持自动<span style="color: black;">增多</span>列属性auto_increment。</span>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">MyISAM存储引擎</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">MyISAM<span style="color: black;">供给</span>了<span style="color: black;">海量</span>的特性,<span style="color: black;">包含</span>全文检索、压缩等,但不支持事务和行级锁,支持表级锁。 <span style="color: black;">针对</span>只读的数据,<span style="color: black;">或</span>表较小、<span style="color: black;">能够</span>忍受修复操作的场景,依然<span style="color: black;">能够</span><span style="color: black;">运用</span>MyISAM。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">MyISAM的适用场景/特性,有以下几种:</span></p><span style="color: black;">不支持事务的设计,<span style="color: black;">然则</span>并不<span style="color: black;">表率</span>着有事务操作的项目<span style="color: black;">不可</span>用MyISAM存储引擎,完全<span style="color: black;">能够</span>在程序层进行<span style="color: black;">按照</span>自己的业务需求进行相应的<span style="color: black;">掌控</span>。</span><span style="color: black;">不支持外键的表设计。</span><span style="color: black;"><span style="color: black;">查找</span>速度<span style="color: black;">火速</span>,<span style="color: black;">倘若</span>数据库insert和update的操作比较多的话比较适用。</span><span style="color: black;">整天 对表进行加锁的场景。</span><span style="color: black;">MyISAM极度强调快速读取操作。</span><span style="color: black;">MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只<span style="color: black;">必须</span>直接读取<span style="color: black;">已然</span><span style="color: black;">保留</span>好的值而不<span style="color: black;">必须</span>进行全表扫描。<span style="color: black;">倘若</span>表的读操作远远多于写操作且不<span style="color: black;">必须</span>数据库事务的支持,<span style="color: black;">那样</span>MyIASM<span style="color: black;">亦</span>是很好的<span style="color: black;">选取</span>。</span>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">MySQL内建的其他存储引擎</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">MySQL还有<span style="color: black;">有些</span>特殊用途的存储引擎,在<span style="color: black;">有些</span>特殊场景下用起来会很爽的。在MySQL新版本中,有些可能<span style="color: black;">由于</span><span style="color: black;">有些</span><span style="color: black;">原由</span><span style="color: black;">已然</span><span style="color: black;">再也不</span>支持了,还有<span style="color: black;">有些</span>会继续支持,<span style="color: black;">然则</span><span style="color: black;">必须</span><span style="color: black;">知道</span>地启用后<span style="color: black;">才可</span><span style="color: black;">运用</span>。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">Archive存储引擎</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Archive引擎只支持insert和select操作,并且在MySQL 5.1之前连索引都不支持。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Archive引擎会缓存所有的写并利用zlib对<span style="color: black;">插进</span>的行进行压缩,<span style="color: black;">因此</span>比MyISAM引擎的磁盘I/O更少。<span style="color: black;">然则</span>每次select<span style="color: black;">查找</span>都<span style="color: black;">必须</span>进行全表扫描,<span style="color: black;">因此</span>Archive更适合日志和数据采集类应用,况且这类应用在做数据分析时<span style="color: black;">常常</span><span style="color: black;">必须</span>全表扫描。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Archive引擎支持行级锁和专用的缓冲区,<span style="color: black;">因此</span><span style="color: black;">能够</span>实现高并发的<span style="color: black;">插进</span>。在一个<span style="color: black;">查找</span><span style="color: black;">起始</span>直到返回表中存在的所有行之前,Archive引擎会阻止其他的select执行,以实现一致性读。<span style="color: black;">另一</span>,这<span style="color: black;">亦</span>实现了批量<span style="color: black;">插进</span>在完成之前对读操作是不看见的。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">Blackhole存储引擎</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Blackhole引擎<span style="color: black;">无</span>实现任何的存储机制,它会丢失所有<span style="color: black;">插进</span>的数据,不做任何<span style="color: black;">保留</span>。怪哉,岂不是一无用处?</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">然则</span>服务器会记录Blackhole的日志,<span style="color: black;">因此</span><span style="color: black;">能够</span>用于复制数据到备库,<span style="color: black;">或</span>只是简单地记录到日志。这种特殊的存储引擎<span style="color: black;">能够</span>在一些特殊的复制架构和日志审核时发挥<span style="color: black;">功效</span>。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">但这种存储引擎的存在,<span style="color: black;">迄今</span>还是有些难以理解。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">CSV存储引擎</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">CSV引擎<span style="color: black;">能够</span>将普通的CSV文件<span style="color: black;">做为</span>MySQL的表来处理,但这种表不支持索引。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">CSV引擎<span style="color: black;">能够</span>在数据库运行时拷入<span style="color: black;">或</span>拷出文件,<span style="color: black;">能够</span>将Excel等电子表格软件中的数据存储为CSV文件,<span style="color: black;">而后</span>复制到MySQL数据目录下,就能在MySQL中打开<span style="color: black;">运用</span>。<span style="color: black;">一样</span>,<span style="color: black;">倘若</span>将数据写入到一个CSV引擎表中,其他的<span style="color: black;">外边</span>程序<span style="color: black;">亦</span>能立即从表的数据文件中读取CSV格式的数据。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">因此呢</span>,CSV引擎<span style="color: black;">能够</span><span style="color: black;">做为</span>一种数据交换的机制,是非常有用的。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">Memory存储引擎</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span><span style="color: black;">必须</span>快速地<span style="color: black;">拜访</span>数据,并且这些数据不会被修改,重启以后丢失<span style="color: black;">亦</span><span style="color: black;">无</span>关系,<span style="color: black;">那样</span><span style="color: black;">运用</span>Memory引擎是非常有用的。Memory引擎<span style="color: black;">最少</span>比MyISAM引擎要快一个数量级,<span style="color: black;">由于</span>所有的数据都<span style="color: black;">保留</span>在内存中,不<span style="color: black;">必须</span>进行磁盘I/O。Memory引擎的表结构在重启以后还会<span style="color: black;">保存</span>,但数据会丢失。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Memory引擎在<span style="color: black;">非常多</span>场景下<span style="color: black;">能够</span>发挥很好的<span style="color: black;">功效</span>:</span></p><span style="color: black;">用于<span style="color: black;">查询</span><span style="color: black;">或</span>映射表,例如将邮箱和州名映射的表。</span><span style="color: black;">用于缓存周期性聚合数据的结果。</span><span style="color: black;">用于<span style="color: black;">保留</span>数据分析中产生的中间数据。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Memory引擎支持Hash索引,<span style="color: black;">因此呢</span><span style="color: black;">查询</span>非常快。虽然Memory的速度非常快,但还是<span style="color: black;">没法</span>取代传统的基于磁盘的表。Memory引擎是表级锁,<span style="color: black;">因此呢</span>并发吸入的性能较低。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span>MySQL在执行<span style="color: black;">查找</span>的过程中,<span style="color: black;">必须</span><span style="color: black;">运用</span>临时表来<span style="color: black;">保留</span>中间结果,内部<span style="color: black;">运用</span>的临时表<span style="color: black;">便是</span>Memory引擎。<span style="color: black;">倘若</span>中间结果太大超出了Memory的限制,<span style="color: black;">或</span>含有BLOB或TEXT字段,则临时表会转换成MyISAM的引擎。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">看了上面的说明,<span style="color: black;">大众</span>就会经常混淆Memory和临时表了。临时表<span style="color: black;">指的是</span><span style="color: black;">运用</span>CREATE TEMPORARY TABLE语句创建的表,它<span style="color: black;">能够</span><span style="color: black;">运用</span>任何存储引擎,<span style="color: black;">因此呢</span>和Memory不是一回事。临时表<span style="color: black;">仅在</span>单个连接中可见,当连接断开时,临时表<span style="color: black;">亦</span>将不复存在。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">关于临时表和Memory引擎的<span style="color: black;">哪些</span>事,可参考MySQL · 引擎特性 · 临时表<span style="color: black;">哪些</span>事儿。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">MySQL的存储引擎及第三方存储引擎,还有<span style="color: black;">非常多</span>,<span style="color: black;">这里</span>就不一一介绍了,后续如有<span style="color: black;">必须</span>,再进一步来谈谈。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">怎样</span><span style="color: black;">选取</span>合适的存储引擎呢</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这么多存储引擎,真是眼花缭乱,<span style="color: black;">咱们</span>该<span style="color: black;">怎样</span><span style="color: black;">选取</span>呢?</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">大部分<span style="color: black;">状况</span>下,都会<span style="color: black;">选取</span>默认的存储引擎——InnoDB,并且这<span style="color: black;">亦</span>是最正确的<span style="color: black;">选取</span>,<span style="color: black;">因此</span>Oracle在MySQL 5.5版本时<span style="color: black;">最终</span>将InnoDB<span style="color: black;">做为</span>默认的存储引擎了。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">针对</span><span style="color: black;">怎样</span><span style="color: black;">选取</span>合适的存储引擎,<span style="color: black;">能够</span>简单地归纳为一句话:”除非<span style="color: black;">必须</span>用到某些InnoDB不具备的特性,并且<span style="color: black;">无</span>其他<span style="color: black;">能够</span>替代,否则都应该优先<span style="color: black;">选取</span>InnoDB引擎”。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">例如,<span style="color: black;">倘若</span>要用到全文检索,<span style="color: black;">意见</span>优先<span style="color: black;">思虑</span>InnoDB加上Sphinx的组合,而不是<span style="color: black;">运用</span>支持全文检索的MyISAM。当然,<span style="color: black;">倘若</span>不<span style="color: black;">必须</span>用到InnoDB的特性,<span style="color: black;">同期</span>其他引擎的特性能够更好地满足需求,就<span style="color: black;">能够</span><span style="color: black;">思虑</span>一下其他存储引擎。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">除非万不得已,<span style="color: black;">意见</span>不要混合<span style="color: black;">运用</span>多种存储引擎,否则可能带来一系列<span style="color: black;">繁杂</span>的问题,以及<span style="color: black;">有些</span>潜在的bug和边界问题。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span><span style="color: black;">必须</span><span style="color: black;">运用</span><span style="color: black;">区别</span>的存储引擎,<span style="color: black;">意见</span><span style="color: black;">思虑</span>从以下几个<span style="color: black;">原因</span>进行衡量<span style="color: black;">思虑</span>。</span></p><span style="color: black;">事务</span><span style="color: black;">备份</span><span style="color: black;">恢复</span><span style="color: black;">特有的特性</span>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">其他<span style="color: black;">查询</span>引擎SQL</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">经过</span>下面的命令查看默认的存储引擎。</span></p>
mysql> show variables like <span style="color: black;">%storage_engine%</span>;
<span style="color: black;">--查看表的存储引擎</span>
show <span style="color: black;">table</span> <span style="color: black;">status</span> like <span style="color: black;">"table_name"</span> ;<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">若有收获,就点赞关注一下吧</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">点击下方,<span style="color: black;">第1</span>时间<span style="color: black;">认识</span>华为云<span style="color: black;">鲜嫩</span>技术~</span></strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">华为云博客_大数据博客_AI博客_云计算博客_<span style="color: black;">研发</span>者中心-华为云</a></p>
外贸B2B平台有哪些? 感谢你的精彩评论,为我的思绪打开了新的窗口。
页:
[1]