diff --git "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\345\272\223/mysql/\344\270\200\346\235\241sql\350\257\255\345\217\245\345\234\250mysql\344\270\255\345\246\202\344\275\225\346\211\247\350\241\214\347\232\204.md" "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\345\272\223/mysql/\344\270\200\346\235\241sql\350\257\255\345\217\245\345\234\250mysql\344\270\255\345\246\202\344\275\225\346\211\247\350\241\214\347\232\204.md" index 79ba726..59a94df 100644 --- "a/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\345\272\223/mysql/\344\270\200\346\235\241sql\350\257\255\345\217\245\345\234\250mysql\344\270\255\345\246\202\344\275\225\346\211\247\350\241\214\347\232\204.md" +++ "b/\350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\346\225\260\346\215\256\345\272\223/mysql/\344\270\200\346\235\241sql\350\257\255\345\217\245\345\234\250mysql\344\270\255\345\246\202\344\275\225\346\211\247\350\241\214\347\232\204.md" @@ -1,112 +1,112 @@ ![](https://user-gold-cdn.xitu.io/2019/3/21/1699dea772f58967?w=800&h=531&f=jpeg&s=58821) -## 概览 +## 姒傝 -最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的更新是怎么完成的。 +鏈杩戝紑濮嬪湪瀛︿範mysql鐩稿叧鐭ヨ瘑锛岃嚜宸辨牴鎹鍒扮殑鐭ヨ瘑鐐癸紝鏍规嵁鑷繁鐨勭悊瑙f暣鐞嗗垎浜嚭鏉ワ紝鏈瘒鏂囩珷浼氬垎鏋愪笅涓涓猻ql璇彞鍦╩ysql涓殑鎵ц娴佺▼锛屽寘鎷瑂ql鐨勬煡璇㈠湪mysql鍐呴儴浼氭庝箞娴佽浆锛宻ql璇彞鐨勬洿鏂版槸鎬庝箞瀹屾垚鐨勩 -## 一、mysql架构分析 +## 涓銆乵ysql鏋舵瀯鍒嗘瀽 -下面是mysql的一个简要架构图: +涓嬮潰鏄痬ysql鐨勪竴涓畝瑕佹灦鏋勫浘锛 ![](https://user-gold-cdn.xitu.io/2019/3/23/169a8bc60a083849?w=950&h=1062&f=jpeg&s=38189) -mysql主要分为Server层和存储引擎层 +mysql涓昏鍒嗕负Server灞傚拰瀛樺偍寮曟搸灞 -**Server层**:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog日志模块。 +**Server灞**锛氫富瑕佸寘鎷繛鎺ュ櫒銆佹煡璇㈢紦瀛樸佸垎鏋愬櫒銆佷紭鍖栧櫒銆佹墽琛屽櫒绛夛紝鎵鏈夎法瀛樺偍寮曟搸鐨勫姛鑳介兘鍦ㄨ繖涓灞傚疄鐜帮紝姣斿瀛樺偍杩囩▼銆佽Е鍙戝櫒銆佽鍥撅紝鍑芥暟绛夛紝杩樻湁涓涓氱敤鐨勬棩蹇楁ā鍧 binglog鏃ュ織妯″潡銆 -**存储引擎**: 主要负责数据的存储和读取,采用可以替换的插件式架构,支持InnoDB、MyISAM、Memory等多个存储引擎,其中InnoDB引擎有自有的日志模块redolog 模块。 +**瀛樺偍寮曟搸**锛 涓昏璐熻矗鏁版嵁鐨勫瓨鍌ㄥ拰璇诲彇锛岄噰鐢ㄥ彲浠ユ浛鎹㈢殑鎻掍欢寮忔灦鏋勶紝鏀寔InnoDB銆丮yISAM銆丮emory绛夊涓瓨鍌ㄥ紩鎿庯紝鍏朵腑InnoDB寮曟搸鏈夎嚜鏈夌殑鏃ュ織妯″潡redolog 妯″潡銆 -InnoDB 5.5.5版本作为默认引擎。 +InnoDB 5.5.5鐗堟湰浣滀负榛樿寮曟搸銆 -**连接器** +**杩炴帴鍣** -主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。 +涓昏璐熻矗鐢ㄦ埛鐧诲綍鏁版嵁搴擄紝杩涜鐢ㄦ埛鐨勮韩浠借璇侊紝鍖呮嫭鏍¢獙璐︽埛瀵嗙爜锛屾潈闄愮瓑鎿嶄綔锛屽鏋滅敤鎴疯处鎴峰瘑鐮佸凡閫氳繃锛岃繛鎺ュ櫒浼氬埌鏉冮檺琛ㄤ腑鏌ヨ璇ョ敤鎴风殑鎵鏈夋潈闄愶紝涔嬪悗鍦ㄨ繖涓繛鎺ラ噷鐨勬潈闄愰昏緫鍒ゆ柇閮芥槸浼氫緷璧栨鏃惰鍙栧埌鐨勬潈闄愭暟鎹紝涔熷氨鏄锛屽悗缁彧瑕佽繖涓繛鎺ヤ笉鏂紑锛屽嵆鏃剁鐞嗗憳淇敼浜嗚鐢ㄦ埛鐨勬潈闄愶紝璇ョ敤鎴蜂篃鏄笉鍙楀奖鍝嶇殑銆 -**查询缓存** +**鏌ヨ缂撳瓨** -连接建立后,执行查询语句的时候,会先查询缓存,Mysql会先校验这个sql是否执行过,以Key-Value的形式缓存在内存中,Key是查询预计,Value是结果集。如果缓存key被命中,就会直接返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。 +杩炴帴寤虹珛鍚庯紝鎵ц鏌ヨ璇彞鐨勬椂鍊欙紝浼氬厛鏌ヨ缂撳瓨锛孧ysql浼氬厛鏍¢獙杩欎釜sql鏄惁鎵ц杩囷紝浠ey-Value鐨勫舰寮忕紦瀛樺湪鍐呭瓨涓紝Key鏄煡璇㈤璁★紝Value鏄粨鏋滈泦銆傚鏋滅紦瀛榢ey琚懡涓紝灏变細鐩存帴杩斿洖缁欏鎴风锛屽鏋滄病鏈夊懡涓紝灏变細鎵ц鍚庣画鐨勬搷浣滐紝瀹屾垚鍚庝篃浼氭妸缁撴灉缂撳瓨璧锋潵锛屾柟渚夸笅涓娆¤皟鐢ㄣ傚綋鐒跺湪鐪熸鎵ц缂撳瓨鏌ヨ鐨勬椂鍊欒繕鏄細鏍¢獙鐢ㄦ埛鐨勬潈闄愶紝鏄惁鏈夎琛ㄧ殑鏌ヨ鏉′欢銆 -Mysql 查询不建议使用缓存,因为对于经常更新的数据来说,缓存的有效时间太短了,往往带来的效果并不好,对于不经常更新的数据来说,使用缓存还是可以的,Mysql 8.0 版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。 +Mysql 鏌ヨ涓嶅缓璁娇鐢ㄧ紦瀛橈紝鍥犱负瀵逛簬缁忓父鏇存柊鐨勬暟鎹潵璇达紝缂撳瓨鐨勬湁鏁堟椂闂村お鐭簡锛屽線寰甯︽潵鐨勬晥鏋滃苟涓嶅ソ锛屽浜庝笉缁忓父鏇存柊鐨勬暟鎹潵璇达紝浣跨敤缂撳瓨杩樻槸鍙互鐨勶紝Mysql 8.0 鐗堟湰鍚庡垹闄や簡缂撳瓨鐨勫姛鑳斤紝瀹樻柟涔熸槸璁や负璇ュ姛鑳藉湪瀹為檯鐨勫簲鐢ㄥ満鏅瘮杈冨皯锛屾墍浠ュ共鑴嗙洿鎺ュ垹鎺変簡銆 -**分析器** +**鍒嗘瀽鍣** -mysql 没有命中缓存,那么就会进入分析器,分析器主要是用来分析SQL语句是来干嘛的,分析器也会分为几步: +mysql 娌℃湁鍛戒腑缂撳瓨锛岄偅涔堝氨浼氳繘鍏ュ垎鏋愬櫒锛屽垎鏋愬櫒涓昏鏄敤鏉ュ垎鏋怱QL璇彞鏄潵骞插槢鐨勶紝鍒嗘瀽鍣ㄤ篃浼氬垎涓哄嚑姝ワ細 -**第一步,词法分析**,一条SQL语句有多个字符串组成,首先要提取关键字,比如select,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。 +**绗竴姝ワ紝璇嶆硶鍒嗘瀽**锛屼竴鏉QL璇彞鏈夊涓瓧绗︿覆缁勬垚锛岄鍏堣鎻愬彇鍏抽敭瀛楋紝姣斿select锛屾彁鍑烘煡璇㈢殑琛紝鎻愬嚭瀛楁鍚嶏紝鎻愬嚭鏌ヨ鏉′欢绛夌瓑銆傚仛瀹岃繖浜涙搷浣滃悗锛屽氨浼氳繘鍏ョ浜屾銆 -**第二步,语法分析**,主要就是判断你输入的sql是否正确,是否符合mysql的语法。 +**绗簩姝ワ紝璇硶鍒嗘瀽**锛屼富瑕佸氨鏄垽鏂綘杈撳叆鐨剆ql鏄惁姝g‘锛屾槸鍚︾鍚坢ysql鐨勮娉曘 -完成这2步之后,mysql就准备开始执行了,但是如何执行,怎么执行是最好的结果呢?这个时候就需要优化器上场了。 +瀹屾垚杩2姝ヤ箣鍚庯紝mysql灏卞噯澶囧紑濮嬫墽琛屼簡锛屼絾鏄浣曟墽琛岋紝鎬庝箞鎵ц鏄渶濂界殑缁撴灉鍛紵杩欎釜鏃跺欏氨闇瑕佷紭鍖栧櫒涓婂満浜嗐 -**优化器** +**浼樺寲鍣** -优化器的作用就是它认为的最优的执行方案去执行(虽然有时候也不是最优),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。 +浼樺寲鍣ㄧ殑浣滅敤灏辨槸瀹冭涓虹殑鏈浼樼殑鎵ц鏂规鍘绘墽琛岋紙铏界劧鏈夋椂鍊欎篃涓嶆槸鏈浼橈級锛屾瘮濡傚涓储寮曠殑鏃跺欒濡備綍閫夋嫨绱㈠紩锛屽琛ㄦ煡璇㈢殑鏃跺欏浣曢夋嫨鍏宠仈椤哄簭绛夈 -**执行器** +**鎵ц鍣** -当选择了执行方案后,mysql就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。 +褰撻夋嫨浜嗘墽琛屾柟妗堝悗锛宮ysql灏卞噯澶囧紑濮嬫墽琛屼簡锛岄鍏堟墽琛屽墠浼氭牎楠岃鐢ㄦ埛鏈夋病鏈夋潈闄愶紝濡傛灉娌℃湁鏉冮檺锛屽氨浼氳繑鍥為敊璇俊鎭紝濡傛灉鏈夋潈闄愶紝灏变細鍘昏皟鐢ㄥ紩鎿庣殑鎺ュ彛锛岃繑鍥炴帴鍙f墽琛岀殑缁撴灉銆 -## 二、语句分析 +## 浜屻佽鍙ュ垎鏋 -### 2.1 查询语句 +### 2.1 鏌ヨ璇彞 -说了以上这么多,那么究竟一条sql语句是如何执行的呢?其实我们的sql可以分为2中,一种是查询,一种是更新(增加,更新,删除)。我们先分析下查询语句,语句如下: +璇翠簡浠ヤ笂杩欎箞澶氾紝閭d箞绌剁珶涓鏉ql璇彞鏄浣曟墽琛岀殑鍛紵鍏跺疄鎴戜滑鐨剆ql鍙互鍒嗕负2涓紝涓绉嶆槸鏌ヨ锛屼竴绉嶆槸鏇存柊锛堝鍔狅紝鏇存柊锛屽垹闄わ級銆傛垜浠厛鍒嗘瀽涓嬫煡璇㈣鍙ワ紝璇彞濡備笅锛 ``` -select * from tb_student A where A.age='18' and A.name='张三'; +select * from tb_student A where A.age='18' and A.name='寮犱笁'; ``` -结合上面的说明,我们分析下这个语句的执行流程: +缁撳悎涓婇潰鐨勮鏄庯紝鎴戜滑鍒嗘瀽涓嬭繖涓鍙ョ殑鎵ц娴佺▼锛 -* 先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在mysql8.0版本以前,会先查询缓存,以这条sql语句为key在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。 -* 通过分析器进行词法分析,提取sql语句的关键元素,比如提取上面这个语句是查询select,提取需要查询的表名为tb_student,需要查询所有的列,查询条件是这个表的id='1'。然后判断这个sql语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。 -* 接下来就是优化器进行确定执行方案,上面的sql语句,可以有两种执行方案: +* 鍏堟鏌ヨ璇彞鏄惁鏈夋潈闄愶紝濡傛灉娌℃湁鏉冮檺锛岀洿鎺ヨ繑鍥為敊璇俊鎭紝濡傛灉鏈夋潈闄愶紝鍦╩ysql8.0鐗堟湰浠ュ墠锛屼細鍏堟煡璇㈢紦瀛橈紝浠ヨ繖鏉ql璇彞涓簁ey鍦ㄥ唴瀛樹腑鏌ヨ鏄惁鏈夌粨鏋滐紝濡傛灉鏈夌洿鎺ョ紦瀛橈紝濡傛灉娌℃湁锛屾墽琛屼笅涓姝ャ +* 閫氳繃鍒嗘瀽鍣ㄨ繘琛岃瘝娉曞垎鏋愶紝鎻愬彇sql璇彞鐨勫叧閿厓绱狅紝姣斿鎻愬彇涓婇潰杩欎釜璇彞鏄煡璇elect锛屾彁鍙栭渶瑕佹煡璇㈢殑琛ㄥ悕涓簍b_student,闇瑕佹煡璇㈡墍鏈夌殑鍒楋紝鏌ヨ鏉′欢鏄繖涓〃鐨刬d='1'銆傜劧鍚庡垽鏂繖涓猻ql璇彞鏄惁鏈夎娉曢敊璇紝姣斿鍏抽敭璇嶆槸鍚︽纭瓑绛夛紝濡傛灉妫鏌ユ病闂灏辨墽琛屼笅涓姝ャ +* 鎺ヤ笅鏉ュ氨鏄紭鍖栧櫒杩涜纭畾鎵ц鏂规锛屼笂闈㈢殑sql璇彞锛屽彲浠ユ湁涓ょ鎵ц鏂规锛 - a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是18。 - b.先找出学生中年龄18岁的学生,然后再查询姓名为“张三”的学生。 - 那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。 + a.鍏堟煡璇㈠鐢熻〃涓鍚嶄负鈥滃紶涓夆濈殑瀛︾敓锛岀劧鍚庡垽鏂槸鍚﹀勾榫勬槸18銆 + b.鍏堟壘鍑哄鐢熶腑骞撮緞18宀佺殑瀛︾敓锛岀劧鍚庡啀鏌ヨ濮撳悕涓衡滃紶涓夆濈殑瀛︾敓銆 + 閭d箞浼樺寲鍣ㄦ牴鎹嚜宸辩殑浼樺寲绠楁硶杩涜閫夋嫨鎵ц鏁堢巼鏈濂界殑涓涓柟妗堬紙浼樺寲鍣ㄨ涓猴紝鏈夋椂鍊欎笉涓瀹氭渶濂斤級銆傞偅涔堢‘璁や簡鎵ц璁″垝鍚庡氨鍑嗗寮濮嬫墽琛屼簡銆 -* 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。 +* 杩涜鏉冮檺鏍¢獙锛屽鏋滄病鏈夋潈闄愬氨浼氳繑鍥為敊璇俊鎭紝濡傛灉鏈夋潈闄愬氨浼氳皟鐢ㄦ暟鎹簱寮曟搸鎺ュ彛锛岃繑鍥炲紩鎿庣殑鎵ц缁撴灉銆 -### 2.2 更新语句 +### 2.2 鏇存柊璇彞 -以上就是一条查询sql的执行流程,那么接下来我们看看一条更新语句如何执行的呢?sql语句如下: +浠ヤ笂灏辨槸涓鏉℃煡璇ql鐨勬墽琛屾祦绋嬶紝閭d箞鎺ヤ笅鏉ユ垜浠湅鐪嬩竴鏉℃洿鏂拌鍙ュ浣曟墽琛岀殑鍛紵sql璇彞濡備笅锛 ``` -update tb_student A set A.age='19' where A.name='张三'; +update tb_student A set A.age='19' where A.name='寮犱笁'; ``` -我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。其实条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,mysql 自带的日志模块式binlog(归档日志),所有的存储引擎都可以使用,我们常用的InnoDB引擎还自带了一个日志模块redo log,我们就以InnoDB模式下来探讨这个语句的执行流程。流程如下: +鎴戜滑鏉ョ粰寮犱笁淇敼涓嬪勾榫勶紝鍦ㄥ疄闄呮暟鎹簱鑲畾涓嶄細璁剧疆骞撮緞杩欎釜瀛楁鐨勶紝涓嶇劧瑕佽鎶鏈礋璐d汉鎵撶殑銆傚叾瀹炴潯璇彞涔熷熀鏈笂浼氭部鐫涓婁竴涓煡璇㈢殑娴佺▼璧帮紝鍙笉杩囨墽琛屾洿鏂扮殑鏃跺欒偗瀹氳璁板綍鏃ュ織鍟︼紝杩欏氨浼氬紩鍏ユ棩蹇楁ā鍧椾簡锛宮ysql 鑷甫鐨勬棩蹇楁ā鍧楀紡binlog锛堝綊妗f棩蹇楋級锛屾墍鏈夌殑瀛樺偍寮曟搸閮藉彲浠ヤ娇鐢紝鎴戜滑甯哥敤鐨処nnoDB寮曟搸杩樿嚜甯︿簡涓涓棩蹇楁ā鍧梤edo log锛屾垜浠氨浠nnoDB妯″紡涓嬫潵鎺㈣杩欎釜璇彞鐨勬墽琛屾祦绋嬨傛祦绋嬪涓嬶細 -* 先查询到张三这一条数据,如果有缓存,也是会用到缓存。 -* 然后拿到查询的语句,把 age 改为19,然后调用引擎API接口,写入这一行数据,InnoDB引擎把数据保存在内存中,同时记录redo log,此时redo log进入prepare状态,然后告诉执行器,执行完成了,随时可以提交。 -* 执行器收到通知后记录binlog,然后调用引擎接口,提交redo log 为提交状态。 -* 更新完成。 +* 鍏堟煡璇㈠埌寮犱笁杩欎竴鏉℃暟鎹紝濡傛灉鏈夌紦瀛橈紝涔熸槸浼氱敤鍒扮紦瀛樸 +* 鐒跺悗鎷垮埌鏌ヨ鐨勮鍙ワ紝鎶 age 鏀逛负19锛岀劧鍚庤皟鐢ㄥ紩鎿嶢PI鎺ュ彛锛屽啓鍏ヨ繖涓琛屾暟鎹紝InnoDB寮曟搸鎶婃暟鎹繚瀛樺湪鍐呭瓨涓紝鍚屾椂璁板綍redo log锛屾鏃秗edo log杩涘叆prepare鐘舵侊紝鐒跺悗鍛婅瘔鎵ц鍣紝鎵ц瀹屾垚浜嗭紝闅忔椂鍙互鎻愪氦銆 +* 鎵ц鍣ㄦ敹鍒伴氱煡鍚庤褰昩inlog锛岀劧鍚庤皟鐢ㄥ紩鎿庢帴鍙o紝鎻愪氦redo log 涓烘彁浜ょ姸鎬併 +* 鏇存柊瀹屾垚銆 -这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?这就是之前mysql的模式了,MyISAM引擎是没有redo log的,那么我们知道它是不支持事务的,所以并不是说只用一个日志模块不可以,只是InnoDB引擎就是通过redo log来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么redo log 要引入prepare预提交状态?这里我们用反证法来说明下为什么要这么做? +杩欓噷鑲畾鏈夊悓瀛︿細闂紝涓轰粈涔堣鐢ㄤ袱涓棩蹇楁ā鍧楋紝鐢ㄤ竴涓棩蹇楁ā鍧椾笉琛屽悧锛熻繖灏辨槸涔嬪墠mysql鐨勬ā寮忎簡锛孧yISAM寮曟搸鏄病鏈塺edo log鐨勶紝閭d箞鎴戜滑鐭ラ亾瀹冩槸涓嶆敮鎸佷簨鍔$殑锛屾墍浠ュ苟涓嶆槸璇村彧鐢ㄤ竴涓棩蹇楁ā鍧椾笉鍙互锛屽彧鏄疘nnoDB寮曟搸灏辨槸閫氳繃redo log鏉ユ敮鎸佷簨鍔$殑銆傞偅涔堬紝鍙堜細鏈夊悓瀛﹂棶锛屾垜鐢ㄤ袱涓棩蹇楁ā鍧楋紝浣嗘槸涓嶈杩欎箞澶嶆潅琛屼笉琛岋紝涓轰粈涔坮edo log 瑕佸紩鍏repare棰勬彁浜ょ姸鎬侊紵杩欓噷鎴戜滑鐢ㄥ弽璇佹硶鏉ヨ鏄庝笅涓轰粈涔堣杩欎箞鍋氾紵 -* **先写redo log 直接提交,然后写 binlog**,假设写完redo log 后,机器挂了,binlog日志没有被写入,那么机器重启后,这台机器会通过redo log恢复数据,但是这个时候bingog并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。 -* **先写binlog,然后写redo log**,假设写完了binlog,机器异常重启了,由于没有redo log,本机是无法恢复这一条记录的,但是binlog又有记录,那么和上面同样的道理,就会产生数据不一致的情况。 +* **鍏堝啓redo log 鐩存帴鎻愪氦锛岀劧鍚庡啓 binlog**锛屽亣璁惧啓瀹宺edo log 鍚庯紝鏈哄櫒鎸備簡锛宐inlog鏃ュ織娌℃湁琚啓鍏ワ紝閭d箞鏈哄櫒閲嶅惎鍚庯紝杩欏彴鏈哄櫒浼氶氳繃redo log鎭㈠鏁版嵁锛屼絾鏄繖涓椂鍊檅ingog骞舵病鏈夎褰曡鏁版嵁锛屽悗缁繘琛屾満鍣ㄥ浠界殑鏃跺欙紝灏变細涓㈠け杩欎竴鏉℃暟鎹紝鍚屾椂涓讳粠鍚屾涔熶細涓㈠け杩欎竴鏉℃暟鎹 +* **鍏堝啓binlog锛岀劧鍚庡啓redo log**锛屽亣璁惧啓瀹屼簡binlog锛屾満鍣ㄥ紓甯搁噸鍚簡锛岀敱浜庢病鏈塺edo log锛屾湰鏈烘槸鏃犳硶鎭㈠杩欎竴鏉¤褰曠殑锛屼絾鏄痓inlog鍙堟湁璁板綍锛岄偅涔堝拰涓婇潰鍚屾牱鐨勯亾鐞嗭紝灏变細浜х敓鏁版嵁涓嶄竴鑷寸殑鎯呭喌銆 -如果采用redo log 两阶段提交的方式就不一样了,写完binglog后,然后再提交redo log就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?假设redo log 处于预提交状态,binglog也已经写完了,这个时候发生了异常重启会怎么样呢? -这个就要依赖于mysql的处理机制了,mysql的处理过程如下: +濡傛灉閲囩敤redo log 涓ら樁娈垫彁浜ょ殑鏂瑰紡灏变笉涓鏍蜂簡锛屽啓瀹宐inglog鍚庯紝鐒跺悗鍐嶆彁浜edo log灏变細闃叉鍑虹幇涓婅堪鐨勯棶棰橈紝浠庤屼繚璇佷簡鏁版嵁鐨勪竴鑷存с傞偅涔堥棶棰樻潵浜嗭紝鏈夋病鏈変竴涓瀬绔殑鎯呭喌鍛紵鍋囪redo log 澶勪簬棰勬彁浜ょ姸鎬侊紝binglog涔熷凡缁忓啓瀹屼簡锛岃繖涓椂鍊欏彂鐢熶簡寮傚父閲嶅惎浼氭庝箞鏍峰憿锛 +杩欎釜灏辫渚濊禆浜巑ysql鐨勫鐞嗘満鍒朵簡锛宮ysql鐨勫鐞嗚繃绋嬪涓嬶細 -* 判断redo log 是否完整,如果判断是完整的,就立即提交。 -* 如果redo log 只是预提交但不是commit状态,这个时候就会去判断binlog是否完整,如果完整就提交 redo log, 不完整就回滚事务。 +* 鍒ゆ柇redo log 鏄惁瀹屾暣锛屽鏋滃垽鏂槸瀹屾暣鐨勶紝灏辩珛鍗虫彁浜ゃ +* 濡傛灉redo log 鍙槸棰勬彁浜や絾涓嶆槸commit鐘舵侊紝杩欎釜鏃跺欏氨浼氬幓鍒ゆ柇binlog鏄惁瀹屾暣锛屽鏋滃畬鏁村氨鎻愪氦 redo log, 涓嶅畬鏁村氨鍥炴粴浜嬪姟銆 -这样就解决了数据一致性的问题。 +杩欐牱灏辫В鍐充簡鏁版嵁涓鑷存х殑闂銆 -## 三、总结 +## 涓夈佹荤粨 -* Mysql 主要分为Server曾和引擎层,Server层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用。 -* 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory等。 -* sql等执行过程分为两类,一类对于查询等过程如下:权限校验---》查询缓存---》分析器---》优化器---》权限校验---》执行器---》引擎 -* 对于更新等语句执行流程如下:分析器----》权限校验----》执行器---》引擎---redo log prepare---》binlog---》redo log commit +* Mysql 涓昏鍒嗕负Server灞傚拰寮曟搸灞傦紝Server灞備富瑕佸寘鎷繛鎺ュ櫒銆佹煡璇㈢紦瀛樸佸垎鏋愬櫒銆佷紭鍖栧櫒銆佹墽琛屽櫒锛屽悓鏃惰繕鏈変竴涓棩蹇楁ā鍧楋紙binlog锛夛紝杩欎釜鏃ュ織妯″潡鎵鏈夋墽琛屽紩鎿庨兘鍙互鍏辩敤銆 +* 寮曟搸灞傛槸鎻掍欢寮忕殑锛岀洰鍓嶄富瑕佸寘鎷紝MyISAM,InnoDB,Memory绛夈 +* sql绛夋墽琛岃繃绋嬪垎涓轰袱绫伙紝涓绫诲浜庢煡璇㈢瓑杩囩▼濡備笅锛氭潈闄愭牎楠---銆嬫煡璇㈢紦瀛---銆嬪垎鏋愬櫒---銆嬩紭鍖栧櫒---銆嬫潈闄愭牎楠---銆嬫墽琛屽櫒---銆嬪紩鎿 +* 瀵逛簬鏇存柊绛夎鍙ユ墽琛屾祦绋嬪涓嬶細鍒嗘瀽鍣----銆嬫潈闄愭牎楠----銆嬫墽琛屽櫒---銆嬪紩鎿---redo log prepare---銆媌inlog---銆媟edo log commit -## 四、参考 +## 鍥涖佸弬鑰 -* 《一起构建Mysql知识网络》 \ No newline at end of file +* 銆婁竴璧锋瀯寤篗ysql鐭ヨ瘑缃戠粶銆