作者:微信小助手
<section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="ignored" data-mpa-powered-by="yiban.io"> <section> <section> <section> <section> <section class="96wx-bdbc"> <span style="letter-spacing: 0px;font-size: 14px;color: rgb(86, 86, 86);">sequence作为Oracle一个非常普通的对象,在实际设计和开发的过程中,还是有些知识,以及细节,值得总结和注意,下面我会从四个方面,展开介绍,</span> </section> </section> </section> </section> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">1. sequence基本介绍</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">2. sequence性能问题<br></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">3. 18c的sequence新特性</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">4. 一些开发中sequence的使用经验</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>1. sequence基本介绍</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">下图是11g的《Reference》,对于create sequence语法的介绍,</span></p> <section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="body"> <section style="white-space: normal;text-align: center;"> <img src="/upload/dff7b11440097ec30f2dc34c12802b8.png" style="border-radius: 24px;height: auto;visibility: visible !important;width: 677px;" data-type="png" class="" data-ratio="0.5507399577167019" data-w="946"> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">可以知道,sequence有一系列参数,可以辅助序列的创建,实现各种需求,</span></p> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <span style="font-size: 14px;color: rgb(86, 86, 86);">INCREMENT BY:步长,不能为0,正值最大28位,表示升序,负值最大27位,表示降序。该参数的绝对值,必须小于MAXVALUE和MINVALUE之差。默认值为1。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">START WITH:起始值,对于降序序列,默认值为序列的最大值,对于升序序列,默认值为序列的最小值。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">MAXVALUE:最大值,正值最大28位,负值最大27位,MAXVALUE >= START WITH,MINVALUE > MAXVALUE。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">NOMAXVALUE:对于升序序列,最⼤值为1028-1,对于降序序列,最⼤值为-1,该参数为默认值。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">MINVALUE:最小值,正值最大28位,负值最大27位,MINVALUE <= START WITH,MINVALUE < MAXVALUE。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">NOMINVALUE:对于升序序列,最小值为1,对于降序序列,最小值为-(1027 -1),该参数为默认值。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">CYCLE:表示序列值到达最⼤或最⼩值后继续循环生成新值。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">NOCYCLE:表示序列值到达最大或最小值后不会生成新值,该参数为默认值。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">CACHE:表示在内存中缓存多少个序列值,最大28位,最小值为2,对于CYCLE=Y的序列,CACHE的值必须小于循环的序列值,CACHE允许的最大值必须小于如下公式:CEIL (MAXVALUE - MINVALUE)) / ABS (INCREMENT)如果数据库崩溃,还未提交的缓存序列,就会丢失。RAC下建议使用cache选项。<br>NOCACHE:不缓存序列值,如果不指定CACHE和NOCACHE,默认缓存20个的序列值。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">ORDER:表示序列会按照请求的顺序,生成序列值,如果使用序列,作为时间戳,则此参数有用,但若作为主键,未必需要保证序列的顺序。如果用的RAC,ORDER是唯一可以保证按序创建序列值的方法,除此之外,序列都是按序产生的。</span> </blockquote> <blockquote style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="quote"> <br> <span style="font-size: 14px;color: rgb(86, 86, 86);">NOORDER:不需要保证序列按序创建,这是默认配置。</span> </blockquote> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">通常我们创建一个序列,会包含这些常用的参数,</span></p> <section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="body"> <section style="white-space: normal;text-align: center;"> <img src="/upload/2dbce00c0a9906e40329defb4c4c221d.png" style="border-radius: 24px;height: auto;visibility: visible !important;width: 677px;" data-type="png" class="" data-ratio="0.22037037037037038" data-w="1080"> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">要了解sequence背后,Oracle做了什么,可以执行10046事件,例如执行create sequence bisal_seq语句,10046的trace记录如下,会向seq$插入记录,从字段名称可以看出,存储的是sequence相应的参数值,</span></p> <section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="body"> <section style="white-space: normal;text-align: center;"> <img src="/upload/8ce8c6edcecb55d2925f4bea436cc81b.png" style="border-radius: 24px;height: auto;visibility: visible !important;width: 677px;" data-type="png" class="" data-ratio="0.5214521452145214" data-w="909"> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">同样检索seq$,可以和上述trace对应起来,</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><img style="box-sizing: border-box !important;word-wrap: break-word !important;width: 677px !important;visibility: visible !important;" src="/upload/84545c90592b2c6d70a097123b5166e2.png" data-type="png" class="" data-ratio="0.15348837209302327" data-w="1075"></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">同时,会向obj$插入一条对象的记录,标记序列对象,</span></p> <section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="body"> <section style="white-space: normal;text-align: center;"> <img src="/upload/84101fa0248581313a8835054376e743.png" style="border-radius: 24px;height: auto;visibility: visible !important;width: 677px;" data-type="png" class="" data-ratio="0.5202127659574468" data-w="940"> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">执行检索select bisal_seq.currval, bisal_seq.nextval from dual语句,会更新seq$,主要更新highwater高水位,因为序列要保证值唯一,</span></p> <section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="body"> <section style="white-space: normal;text-align: center;"> <img src="/upload/ec8b2316363480f22c2d5064f8b6a3cf.png" style="border-radius: 24px;height: auto;visibility: visible !important;width: 677px;" data-type="png" class="" data-ratio="0.5175824175824176" data-w="910"> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">创建序列,不带任何参数,默认参数值如下,</span></p> <section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="body"> <section style="white-space: normal;text-align: center;"> <img src="/upload/5a6faeb0d0b66b4c13a85597780c0608.png" style="border-radius: 24px;height: auto;visibility: visible !important;width: 432px;" data-type="png" class="" data-ratio="0.6666666666666666" data-w="663"> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>问题1:cache存储的是什么?</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">有些人可能认为存储的是1,2,3...20,但实际存储的是目标值,例如20,其他值存储在缓存中。</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>问题2:缓存在什么位置?</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">序列值是基于会话读取的,但并不是存储在会话中,而是存在SGA。</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">语法上,会话中首先要nextval,否则直接currval,会提示错误,使用nextval取出下一值,就可以用currval查看当前值了,</span></p> <section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="body"> <section style="white-space: normal;text-align: center;"> <img src="/upload/ec7a3078efc95bcbcdd0ac8c25342132.png" style="border-radius: 24px;height: auto;visibility: visible !important;width: 434px;" data-type="png" class="" data-ratio="0.8067632850241546" data-w="621"> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>2. sequence性能问题</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">sequence是非常普通的Oracle对象,但如果使用不当,就可能会导致一些性能问题,如下介绍了三个场景。</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>场景1:RAC下,nocache选项创建频繁使用的sequence</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">从之前介绍中,我们了解了,当需要读取的sequence值,到达了当前cache的最大值,就会更新seq$的highwater,这样做的目的,就是为了保证序列值唯一。如果创建序列,不使用cache选项,相当于每次使用序列,都要更新seq$表。如果使用的是RAC,每个节点使用了序列,都要更新seq$,可能出现的场景,就是seq$表的数据块,会在实例之间频繁地传输,进而就可能产生一些gc相关的等待事件,造成性能问题。因此RAC下,对于频繁使用的序列,用nocache选项非常危险。</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>场景2:RAC下,order选项创建频繁使用的sequence</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">创建序列,可以采用order选项,为了可以按顺序产生序列值,在RAC下,由于存在多实例,为了保证不同节点间,序列产生的值是连续的,会使用特殊的全局锁(SV)来控制,序列当前值就是通过这个锁的流转来传送,实现跨实例串行化生成序列值,频繁使用序列,就可能会出现DFS lock handle、latch: gets resource hash list、row cache lock等待事件,造成性能问题,因此尤其对于RAC,用order选项创建频繁使用的sequence非常危险。</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>场景3:sequence作为主键或者唯一键<br></strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">无论sequence无论作为主键还是唯一键,都会自动创建一个唯一索引,由于他的值是递增产生的,因此总会发生索引单向增长,如下图所示,对于递增的序列,总会在B树索引最右侧的索引块,插入新值,当数据块没有空间的时候,就会发生9-1分裂,创建新的数据块,因此争用总会发生在索引叶子节点的最右侧数据块上,</span></p> <section data-mpa-template="t" class="mpa-template" mpa-paragraph-type="body"> <section style="white-space: normal;text-align: center;"> <img src="/upload/bc364bb3c8773dd11d470406cee67f04.png" style="border-radius: 24px;height: auto;visibility: visible !important;width: 382px;" data-type="png" class="" data-ratio="0.6963350785340314" data-w="573"> </section> </section> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">其实针对这问题,之前RWP的Andrew就有介绍,另外,我们系统设计初期的POC,碰见了相同的问题,有三种解决方案。</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>方案一:将索引重建为reverse-key index</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">这种方案,可以缓解索引热块的争用,但是随着数据量的增加,索引越大,对于范围检索,一次检索可能需要读取到buffer cache的索引数据块就会越多,一方面可能会产生磁盘IO方面的等待,另一方面可能会将其他表或索引的数据挤出内存,因此,很有可能只是从索引争用,转换成另一种资源的等待,没有从根本解决这个问题。</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>方案二:将索引重建为hash partition index</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">如果是单实例,这种方案会有效,因为他将原先争用的块数据,分散到了不同的数据块,但是,如果迁移RAC,由于频繁的使用,可能会出现索引数据块在节点间频繁的传输,而且随着节点数增加,传输的可能性就会越大,还是会产生性能的问题。</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);"><strong>方案三:编码生成的智能主键</strong></span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">其实,我们所要解决的,就是这三个问题,</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">问题1:避免实例间传输</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">问题2:避免索引单向争用</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">问题3:保证序列取值不重复</span></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><br></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><span style="font-size: 14px;color: rgb(86, 86, 86);">针对问题1,我们选择实例号,作为序列的开始,保证数据插入,会保存在节点的一边,</span></p> <p style="margin: 0px;text-align: center;color: rgb(0, 0, 0);letter-spacing: 0px;font-size: 16px;line-height: 1.6;" mpa-paragraph-type="body"><img style="border-radius: 24px;box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: 419px;height: 99px;" src="/upload/ef21937a5b21ad69663d8f428f57c13e.png" data-type="png" class="" data-ratio="0.23694029850746268" data-w="536"></p> <p style="margin: 0px;text-align: left;color: rgb(0, 0, 0);letter-s
作者:じ☆ve宝贝
> 检测SQL统计的数量 **利用zabbix创建自定义监控项需要执行以下操作:** 1.在配置文件zabbix_agentd.conf中设置允许添加自定义监控项 2.在zabbix_server.conf中设置监控脚本文件存放路径 3.在指定的路径下创建监控脚本 4.在userparameter_script.conf文件中添加Item key 5.在web端创建监控项 **编辑zabbix_agentd.conf配置文件** cd /etc/zabbix/ vi zabbix_agentd.conf ``` 设置允许添加自定义脚本将 Include=/etc/zabbix/zabbix_agentd.d #并去掉前面的注释符 UnsafeUserParameters=1 ``` **编辑zabbix_server.conf** 设置创建监控脚本的存放路径,打开zabbix_server.conf配置文件,找到AlertScriptsPath,设置路径为 ``` AlertScriptsPath=/usr/lib/zabbix/alertscripts ``` **创建shell脚本** vi mysql_count.sh ``` #!/bin/bash HOSTNAME="$1" PORT=$2 USERNAME="$3" PASSWORD="$4" DBNAME="$5" # day=`date -d "-1 day" +%Y-%m-%d` #SQL查询结果列数 columnNum=1 #通过参数行数和行索引位置 function getValue(){ #调用方法传入的第一个参数,$0 表示方法名 colIndex=$1 #调用方法传入的第二个参数 rowIndex=$2 #定位到指定行,数组索引0为第一个元素 #数学算术运算使用 $((a+b)) idx=$(($columnNum*$colIndex+$rowIndex-1)) #判读索引值是否大于结果行数 #${#arrays_name[@]}获取数组长度 if [ $idx -le ${#result_attrs[@]} ]; then echo ${result_attrs[$idx]} # return ${result_attrs[$idx]} fi } SQL="$6" #echo "mysql -h${HOSTNAME} -P${PORT} -D${DBNAME} -u${USERNAME} -p${PASSWORD} -e \"${SQL}\"" result_attrs=(`/usr/bin/mysql -h${HOSTNAME} -P${PORT} -D${DBNAME} -u${USERNAME} -p${PASSWORD} -e "${SQL}"`) result=`getValue 1 1` #echo "返回结果为:${result}" echo ${result} ``` $1 MySQL 地址 $2 MySQL 端口 $3 MySQL 用户名 $4 MySQL 密码 $5 数据库名称 $6 自定义的SQL 仅支持返回一个参数 **在userparameter_script.conf文件中添加Item key ** ``` 标准格式: UserParameter=<key[*]>,<command> 当中 [*] 不强制 代表传参。 如果使用的传参 <command>需要使用 $1 $2 ... 想shell中传入参数 案例: UserParameter=script.getMysqlSQLCount[*],/usr/lib/zabbix/alertscripts/base_shell.sh $1 $2 $3 $4 $5 "$6" ``` **测试命令** ``` zabbix_get -s 127.0.0.1 -k script.getMysqlSQLCount["HOST","PORT","USERNAME","PASSWORD",DBNAME,"SQL"] ``` 127.0.0.1如果绑定了ip需替换 **在web页面创建监控** **按照步骤 执行 1 2 3步**  点击监控项后执行右上角的创建监控项 键值在这里需要手动输入 ``` script.getMysqlSQLCount["HOST","PORT","USERNAME","PASSWORD",DBNAME,"SQL"] ```  (图片来源于网络,大家注意) **执行第4步 创建触发器**  **在动作中添加接收警告信息的用户信息** **点击监测中-》最新数据找到自己上面设定的名称这个监控项,点击右侧的图形,可以看到检测到的数据数量了** **注意事项** > 我写的SQL中包含了zabbix的特殊字符我们需要编辑在zabbix_agentd.conf,修改如下参数 ``` UnsafeUserParameters=0 => UnsafeUserParameters=1并去掉前面的注释符 ``` #### 案例: 检测昨天用户新增数量 自己测试需要\"转译,而在web端配置时不用 ``` zabbix_get -s 127.0.0.1 -k script.getMysqlSQLCount["127.0.0.1","3306","root","root","test","\"SELECT count(1) FROM user where DATE_FORMAT(create_time,'%Y-%m-%d') = '`date -d \"-1 day\" +%Y-%m-%d`'\""] ``` web端配置 ``` 配置->主机->监控项->创建监控项->键值的位置直接填写如下内容: script.getMysqlSQLCount["127.0.0.1","3306","root","root","test","SELECT count(1) FROM user where DATE_FORMAT(create_time,'%Y-%m-%d') = '`date -d \"-1 day\" +%Y-%m-%d`'"] ```
作者:じ☆ve宝贝
# jdk安装步骤 安装后在 /usr/java [root@iZ23i8uyqh8Z]# rpm -qa | grep jdk #查看是否安装jdk [root@iZ23i8uyqh8Z]# rpm -e --nodeps java* #卸载已安装jdk [root@iZ23i8uyqh8Z /]# cd /usr # 创建存放安装包的文件夹 [root@iZ23i8uyqh8Z usr]# mkdir soft ### 上传文件jdk-7u75-linux-x64.rpm [root@iZ23i8uyqh8Z usr]# chmod +x jdk-7u5-linux-i586.rpm #添加执行权限 [root@iZ23i8uyqh8Z usr]# rpm -ivh jdk-7u5-linux-i586.rpm #安装命令 #配置/etc/profile文件 [root@iZ23i8uyqh8Z usr]# vi /etc/profile #在最后结尾添加下面内容(注意java_home路径) ## 配置环境变量 vi /etc/profile ``` #set java environment export JAVA_HOME=/usr/java/jdk1.7.0_75 export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$PATH:$JAVA_HOME/bin export JAVA_HOME CLASSPATH PATH ``` [root@iZ23i8uyqh8Z usr]# source /etc/profile
作者:微信小助手
<section class="xmteditor" style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"></section> <p><span style="background-color: rgb(255, 255, 255);font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 24px;text-align: start;">说在前面的话</span><br></p> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">本文是用来系统阐述在MySQL中,不同语句在各种条件下的加锁情况,并不是解释各种锁是什么(或者说加锁的本质是什么),大家如果不理解什么是<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">MVCC</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">ReadView</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">正经记录锁</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">gap锁</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">next-key锁</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">插入意向锁</code>这些概念的,可以参考<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">MySQL</code>的官方文档,或者直接参照《MySQL是怎样运行的:从根儿上理解MySQL》这本小册(里边有比官方文档更贴心,更详细的解释,文章中涉及到的所有概念均在小册中有详细解释。</p> <figure style="margin: 22px auto;text-align: left;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;background-color: rgb(255, 255, 255);"> 建议: </figure> <figure style="margin: 22px auto;text-align: left;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;background-color: rgb(255, 255, 255);"> 1. 本篇文章不适合碎片化时间阅读,最好使用电脑观看,或者将字体跳到最小效果好一些 </figure> <figure style="margin: 22px auto;text-align: left;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;background-color: rgb(255, 255, 255);"> 2. 可能一下子看不完,关注 + 收藏 + 好看 + 转发一波 <br> </figure> <p><span style="background-color: rgb(255, 255, 255);font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: left;"> 3. 不要跳着看</span><br></p> <p><span style="background-color: rgb(255, 255, 255);font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: left;"><br></span></p> <p><strong style="font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 24px;text-align: start;">事前准备</strong><br></p> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">建立一个存储三国英雄的<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">hero</code>表:</p> <pre style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 15px;line-height: 1.75;overflow: auto;text-align: start;background-color: rgb(255, 255, 255);"><code class="hljs bash" lang="bash" style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;padding: 18px 15px 12px;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;"><span style="font-size: 14px;">CREATE TABLE hero (<br> number INT,<br> name VARCHAR(100),<br> country varchar(100),<br> PRIMARY KEY (number),<br> KEY idx_name (name)<br>) Engine=InnoDB CHARSET=utf8;<br></span></code></pre> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">然后向这个表里插入几条记录:</p> <pre style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 15px;line-height: 1.75;overflow: auto;text-align: start;background-color: rgb(255, 255, 255);"><code class="hljs bash" lang="bash" style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;padding: 18px 15px 12px;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;"><span style="font-size: 14px;">INSERT INTO hero VALUES<br> (1, <span class="hljs-string" style="color: rgb(221, 17, 68);">'l刘备'</span>, <span class="hljs-string" style="color: rgb(221, 17, 68);">'蜀'</span>),<br> (3, <span class="hljs-string" style="color: rgb(221, 17, 68);">'z诸葛亮'</span>, <span class="hljs-string" style="color: rgb(221, 17, 68);">'蜀'</span>),<br> (8, <span class="hljs-string" style="color: rgb(221, 17, 68);">'c曹操'</span>, <span class="hljs-string" style="color: rgb(221, 17, 68);">'魏'</span>),<br> (15, <span class="hljs-string" style="color: rgb(221, 17, 68);">'x荀彧'</span>, <span class="hljs-string" style="color: rgb(221, 17, 68);">'魏'</span>),<br> (20, <span class="hljs-string" style="color: rgb(221, 17, 68);">'s孙权'</span>, <span class="hljs-string" style="color: rgb(221, 17, 68);">'吴'</span>);</span><br></code></pre> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">然后现在<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">hero</code>表就有了两个索引(一个二级索引,一个聚簇索引),示意图如下:</p> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <figure style="margin: 22px auto;text-align: center;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;background-color: rgb(255, 255, 255);"> <img class="lazyload inited loaded" data-height="538" data-ratio="0.6125" src="/upload/efeb4051ff83dbfd8c4c4b9699ff8459.other" data-type="other" data-w="640" data-width="878" style="width: auto;border-style: none;max-height: none;visibility: visible;background-color: transparent;background-position: 50% center;background-repeat: no-repeat;cursor: zoom-in;"> </figure> <h2 class="heading" data-id="heading-3" style="line-height: 1.5;margin-top: 35px;margin-bottom: 10px;padding-bottom: 12px;font-size: 24px;border-bottom: 1px solid rgb(236, 236, 236);font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong>语句加锁分析</strong></h2> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">其实啊,“XXX语句该加什么锁”本身就是个伪命题,一条语句需要加的锁受到很多条件制约,比方说:</p> <ul style="" class=" list-paddingleft-2"> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">事务的隔离级别</span></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">语句执行时使用的索引(比如聚簇索引、唯一二级索引、普通二级索引)</span></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">查询条件(比方说</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">=</span></code><span style="font-size: 16px;">、</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">=<</span></code><span style="font-size: 16px;">、</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">>=</span></code><span style="font-size: 16px;">等等)</span></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">具体执行的语句类型</span></p></li> </ul> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">在继续详细分析语句的加锁过程前,大家一定要有一个全局概念:<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">加锁</code>只是解决并发事务执行过程中引起的<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">脏写</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">脏读</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">不可重复读</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">幻读</code>这些问题的一种解决方案(<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">MVCC</code>算是一种解决<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">脏读</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">不可重复读</code>、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">幻读</code>这些问题的一种解决方案),一定要意识到<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">加锁</code>的出发点是为了解决这些问题,不同情景下要解决的问题不一样,才导致加的锁不一样,千万不要为了加锁而加锁,容易把自己绕进去。当然,有时候因为<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">MySQL</code>具体的实现而导致一些情景下的加锁有些不太好理解,这就得我们死记硬背了~</p> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">我们这里把语句分为3种大类:普通的<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">SELECT</code>语句、锁定读的语句、<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">INSERT</code>语句,我们分别看一下。</p> <h3 class="heading" data-id="heading-4" style="line-height: 1.5;margin-top: 35px;margin-bottom: 10px;font-size: 18px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong>普通的SELECT语句</strong></h3> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">普通的<code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;">SELECT</code>语句在:</p> <ul style="" class=" list-paddingleft-2"> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">READ UNCOMMITTED</span></code><span style="font-size: 16px;">隔离级别下,不加锁,直接读取记录的最新版本,可能发生</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">脏读</span></code><span style="font-size: 16px;">、</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">不可重复读</span></code><span style="font-size: 16px;">和</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">幻读</span></code><span style="font-size: 16px;">问题。</span></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">READ COMMITTED</span></code><span style="font-size: 16px;">隔离级别下,不加锁,在每次执行普通的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT</span></code><span style="font-size: 16px;">语句时都会生成一个</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">ReadView</span></code><span style="font-size: 16px;">,这样解决了</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">脏读</span></code><span style="font-size: 16px;">问题,但没有解决</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">不可重复读</span></code><span style="font-size: 16px;">和</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">幻读</span></code><span style="font-size: 16px;">问题。</span></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">REPEATABLE READ</span></code><span style="font-size: 16px;">隔离级别下,不加锁,只在第一次执行普通的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT</span></code><span style="font-size: 16px;">语句时生成一个</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">ReadView</span></code><span style="font-size: 16px;">,这样把</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">脏读</span></code><span style="font-size: 16px;">、</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">不可重复读</span></code><span style="font-size: 16px;">和</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">幻读</span></code><span style="font-size: 16px;">问题都解决了。</span></p><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">不过这里有一个小插曲:</span></p><pre style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1em;line-height: 1.75;overflow: auto;"><code class="hljs bash" lang="bash" style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;padding: 18px 15px 12px;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;"><span style="font-size: 12px;"><span class="hljs-comment" style="color: rgb(153, 153, 136);"># 事务T1,REPEATABLE READ隔离级别下</span><br>mysql> BEGIN;<br>Query OK, 0 rows affected (0.00 sec)<br><br>mysql> SELECT * FROM hero WHERE number = 30;<br>Empty <span class="hljs-built_in" style="color: rgb(0, 134, 179);">set</span> (0.01 sec)<br><br><span class="hljs-comment" style="color: rgb(153, 153, 136);"># 此时事务T2执行了:INSERT INTO hero VALUES(30, 'g关羽', '魏'); 并提交</span><br><br>mysql> UPDATE hero SET country = <span class="hljs-string" style="color: rgb(221, 17, 68);">'蜀'</span> WHERE number = 30;<br>Query OK, 1 row affected (0.01 sec)<br>Rows matched: 1 Changed: 1 Warnings: 0<br><br>mysql> SELECT * FROM hero WHERE number = 30;<br>+--------+---------+---------+<br>| number | name | country |<br>+--------+---------+---------+<br>| 30 | g关羽 | 蜀 |<br>+--------+---------+---------+<br>1 row <span class="hljs-keyword" style="font-weight: 700;">in</span> <span class="hljs-built_in" style="color: rgb(0, 134, 179);">set</span> (0.01 sec)</span><br></code></pre><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">在</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">REPEATABLE READ</span></code><span style="font-size: 16px;">隔离级别下,</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">T1</span></code><span style="font-size: 16px;">第一次执行普通的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT</span></code><span style="font-size: 16px;">语句时生成了一个</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">ReadView</span></code><span style="font-size: 16px;">,之后</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">T2</span></code><span style="font-size: 16px;">向</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">hero</span></code><span style="font-size: 16px;">表中新插入了一条记录便提交了,</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">ReadView</span></code><span style="font-size: 16px;">并不能阻止</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">T1</span></code><span style="font-size: 16px;">执行</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">UPDATE</span></code><span style="font-size: 16px;">或者</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">DELETE</span></code><span style="font-size: 16px;">语句来对改动这个新插入的记录(因为</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">T2</span></code><span style="font-size: 16px;">已经提交,改动该记录并不会造成阻塞),但是这样一来这条新记录的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">trx_id</span></code><span style="font-size: 16px;">隐藏列就变成了</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">T1</span></code><span style="font-size: 16px;">的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">事务id</span></code><span style="font-size: 16px;">,之后</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">T1</span></code><span style="font-size: 16px;">中再使用普通的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT</span></code><span style="font-size: 16px;">语句去查询这条记录时就可以看到这条记录了,也就把这条记录返回给客户端了。因为这个特殊现象的存在,你也可以认为</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">InnoDB</span></code><span style="font-size: 16px;">中的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">MVCC</span></code><span style="font-size: 16px;">并不能完完全全的禁止幻读。</span></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SERIALIZABLE</span></code><span style="font-size: 16px;">隔离级别下,需要分为两种情况讨论:</span></p></li> <ul style="list-style-type: square;" class=" list-paddingleft-2"> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">在系统变量</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">autocommit=0</span></code><span style="font-size: 16px;">时,也就是禁用自动提交时,普通的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT</span></code><span style="font-size: 16px;">语句会被转为</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT ... LOCK IN SHARE MODE</span></code><span style="font-size: 16px;">这样的语句,也就是在读取记录前需要先获得记录的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">S锁</span></code><span style="font-size: 16px;">,具体的加锁情况和</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">REPEATABLE READ</span></code><span style="font-size: 16px;">隔离级别下一样,我们后边再分析。</span></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">在系统变量</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">autocommit=1</span></code><span style="font-size: 16px;">时,也就是启用自动提交时,普通的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT</span></code><span style="font-size: 16px;">语句并不加锁,只是利用</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">MVCC</span></code><span style="font-size: 16px;">来生成一个</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">ReadView</span></code><span style="font-size: 16px;">去读取记录。</span></p><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">为啥不加锁呢?因为启用自动提交意味着一个事务中只包含一条语句,一条语句也就没有啥</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">不可重复读</span></code><span style="font-size: 16px;">、</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">幻读</span></code><span style="font-size: 16px;">这样的问题了。</span></p></li> </ul> </ul> <h3 class="heading" data-id="heading-5" style="line-height: 1.5;margin-top: 35px;margin-bottom: 10px;font-size: 18px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong>锁定读的语句</strong></h3> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">我们把下边四种语句放到一起讨论:</p> <ul style="" class=" list-paddingleft-2"> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">语句一:</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT ... LOCK IN SHARE MODE;</span></code></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">语句二:</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT ... FOR UPDATE;</span></code></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">语句三:</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">UPDATE ...</span></code></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">语句四:</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">DELETE ...</span></code></p></li> </ul> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 16px;">我们说</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">语句一</span></code><span style="font-size: 16px;">和</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">语句二</span></code><span style="font-size: 16px;">是</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">MySQL</span></code><span style="font-size: 16px;">中规定的两种</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">锁定读</span></code><span style="font-size: 16px;">的语法格式,而</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">语句三</span></code><span style="font-size: 16px;">和</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">语句四</span></code><span style="font-size: 16px;">由于在执行过程需要首先定位到被改动的记录并给记录加锁,也可以被认为是一种</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">锁定读</span></code><span style="font-size: 16px;">。</span></p> <h4 class="heading" data-id="heading-6" style="line-height: 1.5;margin-top: 35px;margin-bottom: 10px;padding-bottom: 5px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong><span style="font-size: 17px;">READ UNCOMMITTED/READ COMMITTED隔离级别下</span></strong></h4> <p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 16px;">在</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">READ UNCOMMITTED</span></code><span style="font-size: 16px;">下语句的加锁方式和</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">READ COMMITTED</span></code><span style="font-size: 16px;">隔离级别下语句的加锁方式基本一致,所以就放到一块儿说了。值得注意的是,采用</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">加锁</span></code><span style="font-size: 16px;">方式解决并发事务带来的问题时,其实</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">脏读</span></code><span style="font-size: 16px;">和</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">不可重复读</span></code><span style="font-size: 16px;">在任何一个隔离级别下都不会发生(因为</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">读-写</span></code><span style="font-size: 16px;">操作需要排队进行)。</span></p> <h5 class="heading" data-id="heading-7" style="line-height: 1.5;margin-top: 35px;margin-bottom: 10px;padding-bottom: 5px;font-size: 15px;font-family: -apple-system, system-ui, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong><span style="font-size: 17px;">对于使用主键进行等值查询的情况</span></strong></h5> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">使用</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT ... LOCK IN SHARE MODE</span></code><span style="font-size: 16px;">来为记录加锁,比方说:</span></p><pre style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1em;line-height: 1.75;overflow: auto;"><code class="hljs bash" lang="bash" style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;padding: 18px 15px 12px;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;"><span style="font-size: 12px;">SELECT * FROM hero WHERE number = 8 LOCK IN SHARE MODE;</span><br></code></pre><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">这个语句执行时只需要访问一下聚簇索引中</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">number</span></code><span style="font-size: 16px;">值为</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">8</span></code><span style="font-size: 16px;">的记录,所以只需要给它加一个</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">S型正经记录锁</span></code><span style="font-size: 16px;">就好了,如图所示:</span></p><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><br></p> <figure style="margin: 22px auto;text-align: center;"> <img class="lazyload inited loaded" data-height="450" data-ratio="0.4234375" src="/upload/80b73b1d5fd3ef4eca9ccfb727630961.other" data-type="other" data-w="640" data-width="1063" style="width: auto;border-style: none;max-height: none;visibility: visible;background-color: transparent;background-position: 50% center;background-repeat: no-repeat;cursor: zoom-in;"> </figure><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><br></p></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">使用</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT ... FOR UPDATE</span></code><span style="font-size: 16px;">来为记录加锁,比方说:</span></p><pre style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1em;line-height: 1.75;overflow: auto;"><code class="hljs bash" lang="bash" style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;padding: 18px 15px 12px;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;"><span style="font-size: 12px;">SELECT * FROM hero WHERE number = 8 FOR UPDATE;</span></code></pre><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">这个语句执行时只需要访问一下聚簇索引中</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">number</span></code><span style="font-size: 16px;">值为</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">8</span></code><span style="font-size: 16px;">的记录,所以只需要给它加一个</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">X型正经记录锁</span></code><span style="font-size: 16px;">就好了,如图所示:</span></p><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><br></p> <figure style="margin: 22px auto;text-align: center;"> <img class="lazyload inited loaded" data-height="407" data-ratio="0.4546875" src="/upload/52ac46a04fa26408a495d5ee8adf794c.other" data-type="other" data-w="640" data-width="895" style="width: auto;border-style: none;max-height: none;visibility: visible;background-color: transparent;background-position: 50% center;background-repeat: no-repeat;cursor: zoom-in;"> </figure><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><br></p> <blockquote class="warning" style="margin-top: 22px;margin-bottom: 22px;margin-left: 8px;border-left-width: 4px;border-left-color: rgb(247, 81, 81);padding: 1px 23px;color: rgb(102, 102, 102);background-color: rgb(248, 248, 248);"> <p style="line-height: inherit;margin-top: 10px;margin-bottom: 10px;">小贴士: 为了区分S锁和X锁,我们之后在示意图中就把加了S锁的记录染成蓝色,把加了X锁的记录染成紫色。</p> </blockquote></li> <li><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">使用</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">UPDATE ...</span></code><span style="font-size: 16px;">来为记录加锁,比方说:</span></p><pre style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1em;line-height: 1.75;overflow: auto;"><code class="hljs bash" lang="bash" style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;padding: 18px 15px 12px;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;"><span style="font-size: 12px;">UPDATE hero SET country = <span class="hljs-string" style="color: rgb(221, 17, 68);">'汉'</span> WHERE number = 8;</span></code></pre><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">这条</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">UPDATE</span></code><span style="font-size: 16px;">语句并没有更新二级索引列,加锁方式和上边所说的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">SELECT ... FOR UPDATE</span></code><span style="font-size: 16px;">语句一致。</span></p><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">如果</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">UPDATE</span></code><span style="font-size: 16px;">语句中更新了二级索引列,比方说:</span></p><pre style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1em;line-height: 1.75;overflow: auto;"><code class="hljs bash" lang="bash" style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;padding: 18px 15px 12px;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;"><span style="font-size: 12px;">UPDATE hero SET name = <span class="hljs-string" style="color: rgb(221, 17, 68);">'cao曹操'</span> WHERE number = 8;</span><br></code></pre><p style="line-height: inherit;margin-top: 22px;margin-bottom: 22px;"><span style="font-size: 16px;">该语句的实际执行步骤是首先更新对应的</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;padding: 0.065em 0.4em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;"><span style="font-size: 16px;">number</span></code><span style="font-size: 16px;">值为</span><code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-siz
作者:微信小助手
<p style="margin-bottom: 20px;white-space: normal;line-height: 1.75em;margin-left: 16px;margin-right: 16px;" data-mpa-powered-by="yiban.io"><img class="" data-copyright="0" data-ratio="0.4" data-s="300,640" data-type="png" data-w="750" src="/upload/f65931186c03d7e3c9feec291b6e213f.null" style="width: auto !important;visibility: visible !important;"><br></p> <p style="margin-bottom: 20px;white-space: normal;line-height: 1.75em;text-align: center;margin-left: 16px;margin-right: 16px;"><span style="font-size: 13px;color: rgb(0, 122, 170);">源 /</span><span style="color: rgb(64, 62, 62);font-size: 13px;"> </span><span style="font-size: 13px;"><span style="color: rgb(136, 136, 136);"><span style="font-size: 14.4px;">Java团长</span></span></span></p> <section class="output_wrapper"> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">在Java8之前的版本中,我们处理时间类型常常使用的是java.util包下的Date类。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">但使用Date类却有诸多的弊端,如:java.util.Date是非线程安全的,所有的日期类都是可变的;日期/时间类的定义并不一致,在java.util和java.sql的包下都含有Date类,在开发过程中极易出错; 日期类并不提供国际化,没有时区支持。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">为了解决以上问题,Java8在java.time包下提供了很多新的API,常用的类包括LocalDate、LocalTime、LocalDateTime,用以处理日期,时间,日期/时间等</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"><br></span></p> <h3 style="margin-left: 16px;margin-right: 16px;"><span style="color: rgb(0, 122, 170);"><strong>LocalDate类</strong></span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">LocalDate是一个不可变类,在不考虑时区的情况下可以对日期(不包括时间)进行各种操作,它的默认格式是yyyy-MM-dd</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">获取当前日期以及年、月、日</strong></span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">代码示例:</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><p style="line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;margin-bottom: 20px;margin-left: 16px;margin-right: 16px;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"><span class="hljs-comment" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(128, 128, 128);word-wrap: inherit !important;word-break: inherit !important;">//获取当前日期以及年、月、日</span><br>LocalDate localDate = LocalDate.now();<br><span class="hljs-keyword" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">int</span> year = localDate.getYear();<br><span class="hljs-keyword" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">int</span> month = localDate.getMonthValue();<br><span class="hljs-keyword" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">int</span> day = localDate.getDayOfMonth();<br>System.<span class="hljs-keyword" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">out</span>.println(<span class="hljs-string" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"当前日期:"</span> + localDate);<br>System.<span class="hljs-keyword" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">out</span>.println(<span class="hljs-string" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"年:"</span> + year + <span class="hljs-string" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">" 月:"</span> + month + <span class="hljs-string" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">" 日:"</span> + day);<br></span></p></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">运行结果:</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><p style="line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;margin-bottom: 20px;margin-left: 16px;margin-right: 16px;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">当前日期:2018-12-12<br>年:2018 月:12 日:12<br></span></p></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">获取指定的日期</strong></span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">代码示例:</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><p style="line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;margin-bottom: 20px;margin-left: 16px;margin-right: 16px;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"><span class="hljs-comment" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(128, 128, 128);word-wrap: inherit !important;word-break: inherit !important;">//获取指定的日期</span><br>LocalDate specifiedDay = LocalDate.of(<span class="hljs-number" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">2008</span>, <span class="hljs-number" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">8</span>, <span class="hljs-number" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">18</span>);<br>System.<span class="hljs-keyword" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">out</span>.println(<span class="hljs-string" style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"指定日期:"</span> + specifiedDay);<br></span></p></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin: 1.1em 16px 20px;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">运行结果:</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><p style="line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier,
作者:微信小助手
<h2><span style="letter-spacing: 1px;font-size: 14px;">MySQL<strong>主从复制</strong>,<strong>读写分离</strong>是互联网常见的数据库架构,该架构最令人诟病的地方就是,在数据量较大并发量较大的场景下,主从延时会比较严重。</span></h2> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">为什么主从延时这么大?</span></strong></p> <p><img data-ratio="0.8831615120274914" data-type="png" data-w="291" data-s="300,640" src="/upload/a5d5fae3ee7d01970ecce92070e56db1.png"><br><strong><span style="letter-spacing: 1px;font-size: 14px;">答</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:MySQL使用</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">单线程重放</span><span style="letter-spacing: 1px;font-size: 14px;">RelayLog。</span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">应该怎么优化,缩短重放时间?</span></strong></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">答</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">多线程并行重放</span><span style="letter-spacing: 1px;font-size: 14px;">RelayLog可以缩短时间。</span><br></p> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <h2><strong><span style="letter-spacing: 1px;font-size: 14px;">多线程并行重放RelayLog有什么问题?</span></strong></h2> <p><img data-ratio="0.3753280839895013" data-type="png" data-w="381" data-s="300,640" src="/upload/52058e585690f3ac0aa6cb08ac1ffc20.png"><br><strong><span style="letter-spacing: 1px;font-size: 14px;">答</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:需要考虑</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">如何分割RelayLog</span><span style="letter-spacing: 1px;font-size: 14px;">,才能够让<strong>多个数据库实例</strong>,<strong>多个线程并行<span style="display: inline !important;float: none;background-color: transparent;color: rgb(0, 0, 0);" sans="sans" helvetica="helvetica" yahei="yahei" px="px" none="none" left="left" normal="normal" gb="gb" neue="neue">重放</span></strong>RelayLog,不会出现不一致。</span></p> <p><br></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">为什么会出现不一致?</span></strong></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">答</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:如果RelayLog随机的分配给不同的重放线程,假设RelayLog中有这样三条串行的修改记录:</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">update account set money=100 where uid=58;</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">update account set money=150 where uid=58;</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">update account set money=200 where uid=58;</span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"><br></span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">如果单线程串行重放</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:能保证所有从库与主库的执行序列一致。<br></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="letter-spacing: 1px;font-size: 14px;">画外音:最后money都将为200。</span></em></span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"><br></span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">如果多线程随机分配重放</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:多重放线程并发执行这3个语句,谁最后执行是不确定的,最终从库数据可能与主库不同。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="letter-spacing: 1px;font-size: 14px;">画外音:多个从库可能money为100,150,200不确定。</span></em></span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">如何分配,多个从库多线程重放,也能得到一致的数据呢?</span></strong></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">答</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">相同库</span><span style="letter-spacing: 1px;font-size: 14px;">上的写操作,用</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">相同的线程</span><span style="letter-spacing: 1px;font-size: 14px;">来重放RelayLog;</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">不同库</span><span style="letter-spacing: 1px;font-size: 14px;">上的写操作,可以并发用多个线程并发来重放RelayLog。</span></p> <p><img data-ratio="0.39210526315789473" data-type="png" data-w="380" data-s="300,640" src="/upload/64ba0c5fd37a40103522b5adeea57603.png"><br></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">如何做到呢?</span></strong></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">答</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:设计一个哈希算法,hash(db-name) % thread-num,库名hash之后再模上线程数,就能很轻易做到,同一个库上的写操作,被同一个重放线程串行执行。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="letter-spacing: 1px;font-size: 14px;">画外音:不同库上的重放,是并行的,就起到了加速做用。</span></em></span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">这个方案有什么不足?</span></strong></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">答</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:很多公司对MySQL的使用是“</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">单库</span><span style="letter-spacing: 1px;font-size: 14px;">多表”,如果是这样的话,仍然只有一个库,还是不能提高RelayLog的重放速度。</span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">启示</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:将“单库多表”的DB架构模式</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">升级为“多库多表”的DB架构模式</span><span style="letter-spacing: 1px;font-size: 14px;">。</span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="letter-spacing: 1px;font-size: 14px;">画外音:数据量大并发量大的互联网业务场景,“多库”模式还具备着其他很多优势,例如:</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 14px;">(1)非常方便的实例扩展:DBA很容易将不同的库扩展到不同的实例上;</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 14px;">(2)按照业务进行库隔离:业务解耦,进行业务隔离,减少耦合与相互影响;</span></em></span></p> <p><span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 14px;">(3)非常方便微服务拆分:每个服务拥有自己的实例就方便了;</span></em></span></p> <p><br></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">“单库多表”的场景,多线程并行重放RelayLog还能怎么优化?</span></strong></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">答</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:即使只有一个库,</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">事务在主库上也是并发执行的</span><span style="letter-spacing: 1px;font-size: 14px;">,既然在主库上可以并行执行,在从库上也应该能够并行执行呀?</span><br></p> <p><span style="letter-spacing: 1px;font-size: 14px;"><br></span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">新思路</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:将</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">主库上同时并行执行的事务,分为一组,编一个号,这些事务在从库上的回放可以并行执行</span><span style="letter-spacing: 1px;font-size: 14px;">(事务在主库上的执行都进入到prepare阶段,说明事务之间没有冲突,否则就不可能提交),没错,MySQL正是这么做的。</span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">解法</span></strong><span style="letter-spacing: 1px;font-size: 14px;">:</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">基于GTID的并行复制</span><span style="letter-spacing: 1px;font-size: 14px;">。</span></p> <p><span style="letter-spacing: 1px;font-size: 14px;">从MySQL5.7开始,将组提交的信息存放在GTID中,使用mysqlbinlog工具,可以看到组提交内部的信息:</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">20181014 23:52 server_id 58 XXX GTID last_committed=0 sequence_numer=1</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">20181014 23:52 server_id 58 XXX GTID last_committed=0 sequence_numer=2</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">20181014 23:52 server_id 58 XXX GTID last_committed=0 sequence_numer=3</span></p> <p style="line-height: normal;"><span style="letter-spacing: 1px;font-size: 12px;">20181014 23:52 server_id 58 XXX GTID last_committed=0 sequence_numer=4</span></p> <p><img data-ratio="0.387434554973822" data-type="png" data-w="382" data-s="300,640" src="/upload/2a251a94bea032b793d8e60fe681d87d.png"><br><span style="letter-spacing: 1px;font-size: 14px;">和原来的日志相比,多了last_committed和sequence_number。</span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"><br></span></p> <p><strong><span style="letter-spacing: 1px;font-size: 14px;">什么是last_committed?</span></strong></p> <p><span style="letter-spacing: 1px;font-size: 14px;">答:它是事务提交时,上次事务提交的编号,</span><span style="color: rgb(255, 76, 0);"><span style="letter-spacing: 1px;font-size: 14px;">如果具备相同的</span><span style="letter-spacing: 1px;font-size: 12px;">last_committed</span><span style="letter-spacing: 1px;font-size: 14px;">,说明它们在一个组内,可以并发回放执行</span></span><span style="letter-spacing: 1px;font-size: 14px;">。</span></p> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <h2><strong><span style="letter-spacing: 1px;font-size: 14px;">总结</span></strong></h2> <p><span style="letter-spacing: 1px;font-size: 14px;">MySQL并行复制,缩短主从同步时延的方法,体现着这样的一些架构思想:</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">多线程</span><span style="letter-spacing: 1px;font-size: 14px;">是一种常见的缩短执行时间的方法;</span><br></p></li> </ul> <p><span style="color: rgb(0, 82, 255);"><em><span style="letter-spacing: 1px;font-size: 14px;">画外音:例如,很多crontab可以用多线程,切分数据,并行执行。</span></em></span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="letter-spacing: 1px;font-size: 14px;">多线程并发分派任务时,必须保证</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">幂等性</span><span style="letter-spacing: 1px;font-size: 14px;">:MySQL提供了“按照库幂等”,“按照commit_id幂等”两种方式,很值得借鉴;</span></p></li> </ul> <p><span style="color: rgb(0, 82, 255);"><em><span style="letter-spacing: 1px;font-size: 14px;">画外音:例如,群消息,可以按照group_id幂等;用户消息,可以按照user_id幂等。</span></em></span><br></p> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <p><span style="letter-spacing: 1px;font-size: 14px;">具体到MySQL主从同步延时:</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="letter-spacing: 1px;font-size: 14px;">mysql5.5:不支持并行复制,大伙快</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">升级MySQL版本</span><span style="letter-spacing: 1px;font-size: 14px;">;</span></p></li> <li><p><span style="letter-spacing: 1px;font-size: 14px;">mysql5.6:按照库并行复制,建议</span><span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 14px;">使用“多库”架构</span><span style="letter-spacing: 1px;font-size: 14px;">;</span></p></li> <li><p><span style="letter-spacing: 1px;font-size: 14px;">mysql5.7:按照GTID并行复制;</span></p></li> </ul> <p><span style="letter-spacing: 1px;font-size: 14px;"> </span></p> <p style="background-color: rgb(255, 255, 255);box-sizing: border-box;clear: both;color: rgb(51, 51, 51);"><span style="box-sizing: border-box;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><span style="box-sizing: border-box;color: rgb(255, 76, 0);font-size: 14px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;">思路</span><span style="box-sizing: border-box;font-size: 14px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;">比结论重要,希望大家有收获。</span></span></p> <p style="text-align: center;color: rgb(51, 51, 51);clear: both;box-sizing: border-box;background-color: rgb(255, 255, 255);"><span style="box-sizing: border-box;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><strong style="box-sizing: border-box;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><span style="box-sizing: border-box;font-size: 12px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><img width="auto" style="box-sizing: border-box;height: 130px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 677px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;visibility: visible;width: 130px;word-wrap: break-word;" data-ratio="1" data-type="jpeg" data-w="250" data-s="300,640" src="/upload/70c6338917b0840a1d6c89c07c078365.jpg"></span></strong></span></p> <p style="text-align: center;color: rgb(51, 51, 51);clear: both;box-sizing: border-box;background-color: rgb(255, 255, 255);"><span style="box-sizing: border-box;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><strong style="box-sizing: border-box;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><span style="box-sizing: border-box;font-size: 12px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;">架构师之路</span></strong><span style="box-sizing: border-box;font-size: 12px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;">-分享</span><span style="box-sizing: border-box;color: rgb(255, 76, 0);font-size: 12px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;">可落地</span><span style="box-sizing: border-box;font-size: 12px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;">的技术文章</span></span></p> <p style="background-color: transparent;box-sizing: border-box;clear: both;color: rgb(51, 51, 51);"><br style="box-sizing: border-box;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"></p> <p style="margin: 0px;padding: 0px;text-align: justify;color: rgb(51, 51, 51);text-transform: none;text-indent: 0px;letter-spacing: 0.48px;font-size: 17px;font-style: normal;font-variant: normal;font-weight: 400;text-decoration: none;word-spacing: 0px;white-space: normal;word-wrap: break-word;min-height: 17px;max-width: 677px;box-sizing: border-box;orphans: 2;-webkit-text-stroke-width: 0px;background-color: transparent;"><span style="box-sizing: border-box;font-size: 14px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><span style="display: inline !important;float: none;background-color: transparent;color: rgb(51, 51, 51);" sans="sans" helvetica="helvetica" yahei="yahei" px="px" none="none" normal="normal" gb="gb" neue="neue" break-word="break-word" justify="justify" ui="ui" sc="sc">《</span><a style="background-color: transparent;box-sizing: border-box;color: rgb(87, 107, 149);" href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651960945&idx=1&sn=d08f33c5f317fee8956252da8e0236b6&chksm=bd2d03ad8a5a8abb0370b826b7384a4095a5ed36238f0911d102b0ceee8e5d2fbe3bc80c56d9&scene=21#wechat_redirect" target="_blank">架构师之路17年精选80篇</a><span style="display: inline !important;float: none;background-color: transparent;color: rgb(51, 51, 51);" sans="sans" helvetica="helvetica" yahei="yahei" px="px" none="none" normal="normal" gb="gb" neue="neue" break-word="break-word" justify="justify" ui="ui" sc="sc">》9.5W+</span></span></p> <p style="margin: 0px;padding: 0px;text-align: justify;color: rgb(51, 51, 51);text-transform: none;text-indent: 0px;letter-spacing: 0.48px;font-size: 17px;font-style: normal;font-variant: normal;font-weight: 400;text-decoration: none;word-spacing: 0px;white-space: normal;word-wrap: break-word;min-height: 17px;max-width: 677px;box-sizing: border-box;orphans: 2;-webkit-text-stroke-width: 0px;background-color: transparent;"><span style="box-sizing: border-box;font-size: 14px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><span style="display: inline !important;float: none;background-color: transparent;color: rgb(51, 51, 51);" sans="sans" helvetica="helvetica" yahei="yahei" px="px" none="none" normal="normal" gb="gb" neue="neue" break-word="break-word" justify="justify" ui="ui" sc="sc">《<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961620&idx=1&sn=d858c302799cad451656129885214767&chksm=bd2d0cc88a5a85de11ed376570f78a22954e88aad06f0138b3fbfb7be1968699421ac0b99889&scene=21#wechat_redirect" target="_blank">关于MySQL内核,一定要知道的10件事</a>》</span></span><span style="box-sizing: border-box;font-size: 14px;letter-spacing: 1px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;margin-top: 0px;max-width: 100%;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;padding-top: 0px;word-wrap: break-word;"><span style="display: inline !important;float: none;background-color: transparent;color: rgb(51, 51, 51);" sans="sans" helvetica="helvetica" yahei="yahei" px="px" none="none" normal="normal" gb="gb" neue="neue" break-word="break-word" justify="justify" ui="ui" sc="sc"><br></span></span></p>
作者:微信小助手
<p data-mpa-powered-by="yiban.io"></p> <section class="xmteditor" style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"></section> <p></p> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;"><span style="color: rgb(172, 57, 255);font-size: 12px;text-align: justify;widows: 1;background-color: rgb(255, 255, 255);">(点击上方公众号,可快速关注一起学Java)</span><br></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><span style="max-width: 100%;color: rgb(172, 57, 255);font-size: 12px;text-align: justify;widows: 1;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></span></p> <blockquote style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"> <p style="max-width: 100%;min-height: 1em;line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;word-wrap: break-word !important;">来源:<span style="max-width: 100%;line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;">www.cnblogs.com/aylin/p/5744312.html</span></span></p> </blockquote> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;"><br></p> <h2 style="font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><span style="max-width: 100%;color: rgb(171, 25, 66);font-size: 18px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">MySQL简介</strong></span></h2> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">1、什么是数据库 ?</strong></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各种数据管理的方式。数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用。</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">主流的数据库有:sqlserver,mysql,Oracle、SQLite、Access、MS SQL Server等,本文主要讲述的是mysql</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">2、数据库管理是干什么用的?</strong></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <ul class=" list-paddingleft-2" style=""> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;">a. 将数据保存到文件或内存</p><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;">b. 接收特定的命令,然后对文件进行相应的操作</p></li> </ul> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">PS:如果有了以上管理系统,无须自己再去创建文件和文件夹,而是直接传递 命令 给上述软件,让其来进行文件操作,他们统称为数据库管理系统(DBMS,Database Management System)</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <h2 style="font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><span style="max-width: 100%;color: rgb(171, 25, 66);font-size: 18px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></strong></span></h2> <h2 style="font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><span style="max-width: 100%;color: rgb(171, 25, 66);font-size: 18px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">MySQL</strong></span><strong style="color: rgb(171, 25, 66);font-size: 18px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">安装</strong></h2> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言–结构化查询语言(SQL)进行数据库管理。在 WEB 应用方面MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">使用mysql必须具备一下条件</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <ul class=" list-paddingleft-2" style=""> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;">a. 安装MySQL服务端</p><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;">b. 安装MySQL客户端</p><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;">c. 【客户端】连接【服务端】</p><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;">d. 【客户端】发送命令给【服务端MySQL】服务的接受命令并执行相应操作(增删改查等)</p></li> </ul> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">1、下载地址:http://dev.mysql.com/downloads/mysql/</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">2、安装</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <ul class=" list-paddingleft-2" style=""> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;">windows安装请参考:http://www.cnblogs.com/lonelywolfmoutain/p/4547115.html</p><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;">linux下安装:http://www.cnblogs.com/chenjunbiao/archive/2011/01/24/1940256.html</p></li> </ul> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">注:以上两个链接有完整的安装方式,撸主也是参考他的安装的,安装完以后mysql.server start启动mysql服务</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <h2 style="font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><span style="max-width: 100%;color: rgb(171, 25, 66);font-size: 18px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></strong></span></h2> <h2 style="font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><span style="max-width: 100%;color: rgb(171, 25, 66);font-size: 18px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">MySQL</strong></span><strong style="color: rgb(171, 25, 66);font-size: 18px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">操作</strong></h2> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">一、连接数据库</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;">mysql -u user -p <br>例:mysql -u root -p</code></pre> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">常见错误如下:</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <blockquote style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 12px;box-sizing: border-box !important;word-wrap: break-word !important;">ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2), it means that the MySQL server daemon (Unix) or service (Windows) is not running.</span></p> </blockquote> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">退出连接:</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;">QUIT 或者 Ctrl+D</code></pre> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">二、查看数据库,创建数据库,使用数据库查看数据库: </p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">show</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">databases</span>;</span></code></pre> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;">默认数据库:</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span style="color: rgb(172, 57, 255);">mysql</span> - 用户权限相关数据<br><span style="color: rgb(172, 57, 255);">test</span> - 用于用户测试数据<br><span style="color: rgb(172, 57, 255);">information_schema</span> - MySQL本身架构相关数据</code></pre> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;">创建数据库: </p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">create</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">database</span> db1 <span class="hljs-keyword" style="color: rgb(249, 38, 114);">DEFAULT</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">CHARSET</span> utf8 <span class="hljs-keyword" style="color: rgb(249, 38, 114);">COLLATE</span> utf8_general_ci;</span> <span style="color: rgb(136, 136, 136);"># utf8编码</span><br><br><span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">create</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">database</span> db1 <span class="hljs-keyword" style="color: rgb(249, 38, 114);">DEFAULT</span> <span class="hljs-built_in" style="color: rgb(230, 219, 116);">CHARACTER</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">SET</span> gbk <span class="hljs-keyword" style="color: rgb(249, 38, 114);">COLLATE</span> gbk_chinese_ci; </span><span style="color: rgb(136, 136, 136);"># gbk编码</span></code></pre> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;">使用数据库:</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"> <span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">use</span> db1;</span></code></pre> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">显示当前使用的数据库中所有表:</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">SHOW</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">TABLES</span>;</span></code></pre> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">三、用户管理</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br></p> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;">创建用户</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">create</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">user</span> <span class="hljs-string" style="color: rgb(230, 219, 116);">'用户名'</span>@<span class="hljs-string" style="color: rgb(230, 219, 116);">'IP地址'</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">identified</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">by</span> <span class="hljs-string" style="color: rgb(230, 219, 116);">'密码'</span>;</span></code></pre> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;">删除用户</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">drop</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">user</span> <span class="hljs-string" style="color: rgb(230, 219, 116);">'用户名'</span>@<span class="hljs-string" style="color: rgb(230, 219, 116);">'IP地址'</span>;</span></code></pre> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;">修改用户</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">rename</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">user</span> <span class="hljs-string" style="color: rgb(230, 219, 116);">'用户名'</span>@<span class="hljs-string" style="color: rgb(230, 219, 116);">'IP地址'</span>;</span> to '新用户名'@'IP地址';</code></pre> <p style="font-variant-ligatures: normal;orphans: 2;white-space: normal;widows: 2;">修改密码</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span class="hljs-operator"><span class="hljs-keyword" style="color: rgb(249, 38, 114);">set</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">password</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114);">for</span> <span class="hljs-string" style="color: rgb(230, 219, 116);">'用户名'</span>@<span class="hljs-string" style="color: rgb(230, 219, 116);">'IP地址'</span> = <span class="hljs-keyword" style="color: rgb(249, 38, 114);">Password</span>(<span class="hljs-string" style="color: rgb(230, 219, 116);">'新密码'</span>)<span style="font-size: 12.8px;">;</span></span></code></pre> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">注:用户权限相关数据保存在mysql数据库的user表中,所以也可以直接对其进行操作(不建议)</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">四、权限管理</p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">mysql对于权限这块有以下限制:</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span style="color: rgb(255, 251, 0);">all privileges</span><span style="color: rgb(61, 167, 66);"><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>除grant外的所有权限<br><span style="color: rgb(255, 251, 0);">select:</span>仅查权限<br><span style="color: rgb(255, 251, 0);">select,insert</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>查和插入权限<br><span style="color: rgb(255, 251, 0);">...<br>usage</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>无访问权限<br><span style="color: rgb(255, 251, 0);">alter</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用alter table<br><span style="color: rgb(255, 251, 0);">alter routine<span style="font-size: 12.8px;">:</span></span>使用alter procedure和drop procedure<br><span style="color: rgb(255, 251, 0);">create</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用create table<br><span style="color: rgb(255, 251, 0);">create routine</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用create procedure<br><span style="color: rgb(255, 251, 0);">create temporary tables</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用create temporary tables<br><span style="color: rgb(255, 251, 0);">create user</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用create user、drop user、rename user和revoke all privileges<br><span style="color: rgb(255, 251, 0);">create view<span style="font-size: 12.8px;">:</span></span>使用create view<br><span style="color: rgb(255, 251, 0);">delete<span style="font-size: 12.8px;">:</span></span>使用delete<br><span style="color: rgb(255, 251, 0);">drop</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用drop table<br><span style="color: rgb(255, 251, 0);">execute</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用call和存储过程<br><span style="color: rgb(255, 251, 0);">file</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用select into outfile 和 load data infile<br><span style="color: rgb(255, 251, 0);">grant option</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用grant 和 revoke<br><span style="color: rgb(255, 251, 0);">index</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用index<br><span style="color: rgb(255, 251, 0);">insert</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用insert<br><span style="color: rgb(255, 251, 0);">lock tables</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用lock table<br><span style="color: rgb(255, 251, 0);">process</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用show full processlist<br><span style="color: rgb(255, 251, 0);">select</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用select<br><span style="color: rgb(255, 251, 0);">show databases</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用show databases<br><span style="color: rgb(255, 251, 0);">show view</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用show view<br><span style="color: rgb(255, 251, 0);">update</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用update<br><span style="color: rgb(255, 251, 0);">reload</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用flush<br><span style="color: rgb(255, 251, 0);">shutdown</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用mysqladmin shutdown(关闭MySQL)<br><span style="color: rgb(255, 251, 0);">super</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>使用change master、kill、logs、purge、master和set global。还允许mysqladmin调试登陆<br><span style="color: rgb(255, 251, 0);">replication client</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>服务器位置的访问<br><span style="color: rgb(255, 251, 0);">replication slave</span><span style="color: rgb(255, 251, 0);font-size: 12.8px;">:</span>由复制从属使用</span></code></pre> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">对于数据库及内部其他权限如下:</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size: 1em;font-variant-ligatures: normal;orphans: 2;widows: 2;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 1.2em;"><code class="hljs language-sql" style="margin-right: 0.15em;margin-left: 0.15em;padding: 0.5em;font-size: 0.8em;font-family: Consolas, Inconsolata, Courier, monospace;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);color: rgb(248, 248, 242);background: rgb(35, 36, 31);display: block !important;"><span style="color: rgb(122, 79, 214);">数据库名.* </span><span style="color: rgb(255, 169, 0);"> 数据库中的所有<br><span style="color: rgb(122, 79, 214);">数据库名.表 </span> 指定数据库中的某张表<br><span style="color: rgb(122, 79, 214);">数据库名.存储过程</span> 指定数据库中的存储过程<br><span style="color: rgb(122, 79, 214);">*.* </span> 所有数据库</span></code></pre> <p style="font-size: 16px;font-variant-ligatures: normal;orphans: 2;white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">对于用户和IP的权限如下:</p> <pre style="margin-top: 1.2em;margin-bottom: 1.2em;font-size:
作者:じ☆ve宝贝
web.xml ``` <!-- comet4j消息推送 --> <listener> <description>Comet4J容器侦听</description> <listener-class>org.comet4j.core.CometAppListener</listener-class> </listener> <servlet> <description>Comet连接[默认:org.comet4j.core.CometServlet]</description> <display-name>CometServlet</display-name> <servlet-name>CometServlet</servlet-name> <servlet-class>org.comet4j.core.CometServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CometServlet</servlet-name> <url-pattern>/test</url-pattern> </servlet-mapping> <listener> <description>CometListener</description> <listener-class>cn.harvetech.listener.CometListener</listener-class> </listener> ``` Const.java ``` public static final String MSG_CHANEL = "studyjava"; ``` CometListener ``` package cn.harvetech.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.comet4j.core.CometConnection; import org.comet4j.core.CometContext; import org.comet4j.core.CometEngine; import org.comet4j.core.event.ConnectEvent; import org.comet4j.core.event.DropEvent; import org.comet4j.core.listener.ConnectListener; import org.comet4j.core.listener.DropListener; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import cn.studyjava.service.RedisService; import cn.studyjava.util.Const; /** * * 作者: zsljava * 邮件: zsljava@163.com * 时间: 2016年3月28日 下午5:11:56 * 描述: 消息推送监听器 * 注意: tomcat7的jar包 comet4j-tomcat7.jar * tomcat6的jar包 comet4j-tomcat6.jar * tomcat下server.xml的配置 * <Connector URIEncoding="UTF-8" connectionTimeout="20000" port="80" * protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443"/> * protocol 连接方式修改成为nio的的就行了 * 注意listener生命周期不受spring管理 在listener中使用spring的beans需要用WebApplicationContextUtils */ public class CometListener implements ServletContextListener{ private static Logger logger = Logger.getLogger(CometListener.class); private RedisService redisService; public void contextInitialized(ServletContextEvent sce) { CometContext cc = CometContext.getInstance(); cc.registChannel(Const.MSG_CHANEL);// 注册应用的channel CometEngine engine = cc.getEngine(); engine.addConnectListener(new JoinListener()); //上线通知 engine.addDropListener(new LeftListener()); //离线通知 WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(cc.getServletContext()); redisService = (RedisService) context.getBean("redisService"); //获取redis logger.info("初始化comet4j消息推送框架"); } class JoinListener extends ConnectListener { public boolean handleEvent(ConnectEvent anEvent) { CometConnection conn = anEvent.getConn(); redisService.set(conn.getRequest().getSession().getId(), conn.getId());//客户端连接后存储ChanelId logger.info("接入ChanelId为:"+conn.getId() +",redis存储key为:"+conn.getRequest().getSession().getId()); CometEngine engine = CometContext.getInstance().getEngine(); engine.sendTo(Const.MSG_CHANEL, engine.getConnection(conn.getId()), "欢迎您,sessionid为:"+conn.getRequest().getSession().getId()); return true; } } class LeftListener extends DropListener { public boolean handleEvent(DropEvent anEvent) { CometConnection conn = anEvent.getConn(); if (conn != null) { HttpServletRequest request = conn.getRequest(); redisService.del(request.getSession().getId()); logger.info("删除ChanelId为:"+conn.getId() +",redis存储key为:"+conn.getRequest().getSession().getId()); CometEngine engine = CometContext.getInstance().getEngine(); engine.sendTo(Const.MSG_CHANEL, engine.getConnection(conn.getId()), "删除,sessionid为:"+conn.getRequest().getSession().getId()); } return true; } } public void contextDestroyed(ServletContextEvent sce) { } } ``` jsp ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Comet4J Hello World</title> <script type="text/javascript" src="js/comet4j.js"></script> <script type="text/javascript"> function init(){ var kbDom = document.getElementById('kb'); JS.Engine.on({ start : function(cId, channelList, engine){ // document.getElementById('cid').innerHTML=cId; alert('连接已建立,连接ID为:' + cId); }, stop : function(cause, cId, url, engine){ alert('连接已断开,连接ID为:' + cId + ',断开原因:' + cause + ',断开的连接地址:'+ url); }, harvetech : function(kb){//侦听一个channel kbDom.innerHTML = kb; } }); JS.Engine.start('test'); } </script> </head> <body onload="init()"> comet4j消息推送:<span id="kb">...</span> </body> </html> ```
作者:微信小助手
<p style="margin-top: 15px;margin-right: 8px;margin-left: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 16px;"><span style="max-width: 100%;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;">本文转载自公众号 [</span><span style="max-width: 100%;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);color: rgb(120, 172, 254);box-sizing: border-box !important;word-wrap: break-word !important;">程序员小灰</span><span style="max-width: 100%;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;">]</span></span></p> <p><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/37af23bfc68744db1ef60fc1b8f60224.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/d09ba748f39fe9f2857aab6766a8f32a.jpg" data-type="jpeg" data-w="650" style=""></p> <p><br></p> <p><br></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 20px;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">————— 第二天 —————</strong></span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/4e823cefe020d890347846bd2f9999bf.jpg" data-type="jpeg" data-w="650" style="box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: auto !important;" width="auto"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/4b4a71d9f618ec4c2a97a343efc7d843.jpg" data-type="jpeg" data-w="650" style="box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: auto !important;" width="auto"></p> <p><br></p> <p><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/db27c6cce902bf194b0006acaa485cf9.jpg" data-type="jpeg" data-w="650" style=""></p> <p><br></p> <p><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/eb0fa8ddb341d3b0a497b732877dbc5f.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/b1e496b2608ea3f1bb621f8dcd58e544.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 20px;"><strong>方法一:UUID</strong></span></p> <p style="text-align: left;"><span style="font-size: 20px;"><strong><br></strong></span></p> <p style="text-align: left;"><span style="font-size: 20px;"></span></p> <p><span style="font-size: 18px;">UUID是通用唯一识别码 (Universally Unique Identifier),在其他语言中也叫GUID,可以生成一个长度32位的全局唯一识别码。</span></p> <p><br></p> <p><span style="font-size: 18px;">String uuid = UUID.randomUUID().toString()</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;">结果示例:</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;">046b6c7f-0b8a-43b9-b35d-6489e6daee91</span></p> <p style="text-align: left;"><span style="font-size: 20px;"></span><br></p> <p style="text-align: left;"><br></p> <p><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/6be0caaa94c73c506f4f5a5f26a09ccd.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">为什么无序的UUID会导致入库性能变差呢?</span></p> <p><br></p> <p><span style="font-size: 18px;">这就涉及到 <strong>B+树索引的分裂</strong>:</span></p> <p><span style="font-size: 18px;"><strong><br></strong></span></p> <p><span style="font-size: 18px;"><strong><br></strong></span></p> <p><span style="font-size: 18px;"></span></p> <p style="text-align: center;"><img class="" data-ratio="0.48641304347826086" data-s="300,640" src="/upload/332eac4d0f1f5c4799ec22572290dbbd.png" data-type="png" data-w="368" style=""></p> <p><span style="font-size: 18px;"></span><br></p> <p><br></p> <p><span style="font-size: 18px;">众所周知,关系型数据库的索引大都是B+树的结构,拿ID字段来举例,索引树的每一个节点都存储着若干个ID。</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;">如果我们的ID按递增的顺序来插入,比如陆续插入8,9,10,新的ID都只会插入到最后一个节点当中。当最后一个节点满了,会裂变出新的节点。这样的插入是性能比较高的插入,因为这样节点的<span style="font-size: 18px;">分裂</span>次数最少,而且充分利用了每一个节点的空间。</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;"></span></p> <p style="text-align: center;"><img class="" data-ratio="0.3049403747870528" data-s="300,640" src="/upload/a9c2fa10f49c2ee48887eff3edebd5a.png" data-type="png" data-w="587" style=""></p> <p><span style="font-size: 18px;"></span><br></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;">但是,如果我们的插入完全无序,不但会导致一些中间节点产生分裂,也会白白创造出很多不饱和的节点,这样大大降低了数据库插入的性能。</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><span style="font-size: 18px;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/eb0fa8ddb341d3b0a497b732877dbc5f.jpg" data-type="jpeg" data-w="650" style="text-align: center;white-space: normal;"></span></p> <p style="text-align: center;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;"></span></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/943dee49d1891c963c7f70f9a0f9591f.jpg" data-type="jpeg" data-w="650" style=""></p> <p><span style="font-size: 18px;"></span><br></p> <p><br></p> <p><span style="font-size: 18px;"><strong style="font-size: 20px;white-space: normal;">方法二:数据库自增主键</strong></span></p> <p><br></p> <p><span style="font-size: 18px;">假设名为table的表有如下结构:</span></p> <p><br></p> <p><span style="font-size: 18px;">id feild</span></p> <p><span style="font-size: 18px;">35 a</span></p> <p><br></p> <p><span style="font-size: 18px;">每一次生成ID的时候,访问数据库,执行下面的语句:</span></p> <p><br></p> <p><span style="font-size: 16px;">begin;</span></p> <p><span style="font-size: 16px;">REPLACE INTO table ( feild ) VALUES ( 'a' );</span></p> <p><span style="font-size: 16px;">SELECT LAST_INSERT_ID();</span></p> <p><span style="font-size: 16px;">commit;</span></p> <p><br><span style="font-size: 18px;">REPLACE INTO 的含义是插入一条记录,如果表中唯一索引的值遇到冲突,则替换老数据。</span></p> <p><br></p> <p><span style="font-size: 18px;">这样一来,每次都可以得到一个递增的ID。</span></p> <p><br></p> <p><span style="font-size: 18px;">为了提高性能,在分布式系统中可以用DB proxy请求不同的分库,每个分库设置不同的初始值,步长和分库数量相等:</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;"></span></p> <p style="text-align: center;"><img class="" data-ratio="0.6447368421052632" data-s="300,640" src="/upload/1fe16db402d9d3be9abbcde64a11e0e0.png" data-type="png" data-w="532" style="width: 411px;height: 265px;"></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">这样一来,DB1生成的ID是1,4,7,10,13....,DB2生成的ID是2,5,8,11,14.....</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;"></span></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/be3ea121370f4415e2f8e31b31414bf8.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;"></span><br></p> <p style="text-align: left;"><br></p> <p><span style="font-size: 18px;"></span></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/4c85f27c0077eba6d4ae38da85b88a.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/b90e435bfea9bd4d74306e45bb284ed2.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 18px;box-sizing: border-box !important;word-wrap: break-word !important;">————————————</span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 18px;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/12aa665c1ef18d9526769504932182ef.jpg" data-type="jpeg" data-w="650" style="box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: auto !important;" width="auto"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/b8e88c0b4e7bf27994fa73f8640547d9.jpg" data-type="jpeg" data-w="650" style="box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: auto !important;" width="auto"></p> <p><br></p> <p><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/48e2202be1aa0219709695fdc5194077.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/1bd53c3aef8b248f0141bbc6d3e50641.jpg" data-type="jpeg" data-w="650" style=""></p> <p><br></p> <p><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/b51eec2dcf0e047a29261e435f3d338d.jpg" data-type="jpeg" data-w="650"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.46153846153846156" data-s="300,640" src="/upload/cd9c36ba5b9ffa3db327754ad49a26bf.jpg" data-type="jpeg" data-w="650" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><
作者:微信小助手
<p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;" data-mpa-powered-by="yiban.io"><span style="max-width: 100%;color: rgb(255, 0, 0);font-size: 14px;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;box-sizing: border-box !important;word-wrap: break-word !important;">(点击</span><span style="max-width: 100%;line-height: 22.4px;color: rgb(0, 128, 255);box-sizing: border-box !important;word-wrap: break-word !important;">上方公众号</span><span style="max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;box-sizing: border-box !important;word-wrap: break-word !important;">,可快速关注)</span></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"></p> <blockquote style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;word-wrap: break-word !important;">来源:姚登晏 ,</span></p> <p style="max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;word-wrap: break-word !important;">www.cnblogs.com/yaodengyan/p/9717080.html</span></p> </blockquote> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">绝大部分写业务的程序员,在实际开发中使用 Redis 的时候,只会 Set Value 和 Get Value 两个操作,对 Redis 整体缺乏一个认知。这里对 Redis 常见问题做一个总结,解决大家的知识盲点。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><strong><span style="color: rgb(255, 76, 65);">1、为什么使用 Redis</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">在项目中使用 Redis,主要考虑两个角度:性能和并发。如果只是为了分布式锁这些其他功能,还有其他中间件 Zookpeer 等代替,并非一定要使用 Redis。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><strong><span style="color: rgb(123, 12, 0);">性能:</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">如下图所示,我们在碰到需要执行耗时特别久,且结果不频繁变动的 SQL,就特别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求能够迅速响应。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">特别是在秒杀系统,在同一时间,几乎所有人都在点,都在下单。。。执行的是同一操作———向数据库查数据。<span style="color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);"> </span><img class="" data-ratio="0.38729763387297633" src="/upload/adbb5c2673b752a87849887bb86268db.null" data-type="png" data-w="803" height="237.016px" style="color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;width: 612px !important;visibility: visible !important;" width="612px"></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">根据交互效果的不同,响应时间没有固定标准。在理想状态下,我们的页面跳转需要在瞬间解决,对于页内操作则需要在刹那间解决。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><strong><span style="color: rgb(123, 12, 0);">并发:</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">如下图所示,在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用 Redis 做一个缓冲操作,让请求先访问到 Redis,而不是直接访问数据库。</p> <p style="white-space: normal;text-align: center;"><img class="" data-ratio="0.5846994535519126" src="/upload/ffe87926d5d14d10975359a5219344de.null" data-type="png" data-w="732" height="357.828px" style="color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;width: 612px !important;visibility: visible !important;" width="612px"></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><strong><span style="color: rgb(123, 12, 0);">使用 Redis 的常见问题</span></strong></p> <p style="white-space: normal;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="white-space: normal;">缓存和数据库双写一致性问题</p></li> <li><p style="white-space: normal;">缓存雪崩问题</p></li> <li><p style="white-space: normal;">缓存击穿问题</p></li> <li><p style="white-space: normal;">缓存的并发竞争问题</p></li> </ul> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><strong><span style="color: rgb(255, 76, 65);"> 2、单线程的 Redis 为什么这么快</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"> 这个问题是对 Redis 内部机制的一个考察。很多人都不知道 Redis 是单线程工作模型。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><span style="color: rgb(123, 12, 0);"><strong>原因主要是以下三点:</strong></span></p> <p style="white-space: normal;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="white-space: normal;">纯内存操作</p></li> <li><p style="white-space: normal;">单线程操作,避免了频繁的上下文切换</p></li> <li><p style="white-space: normal;">采用了非阻塞 I/O 多路复用机制</p></li> </ul> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">仔细说一说 I/O 多路复用机制,打一个比方:小名在 A 城开了一家快餐店店,负责同城快餐服务。小明因为资金限制,雇佣了一批配送员,然后小曲发现资金不够了,只够买一辆车送快递。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><strong><span style="color: rgb(123, 12, 0);">经营方式一</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">客户每下一份订单,小明就让一个配送员盯着,然后让人开车去送。慢慢的小曲就发现了这种经营方式存在下述问题:</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">时间都花在了抢车上了,大部分配送员都处在闲置状态,抢到车才能去送。</p> <p style="white-space: normal;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="white-space: normal;">随着下单的增多,配送员也越来越多,小明发现快递店里越来越挤,没办法雇佣新的配送员了。</p></li> <li><p style="white-space: normal;">配送员之间的协调很花时间。</p></li> <li><p style="white-space: normal;">综合上述缺点,小明痛定思痛,提出了经营方式二。</p></li> </ul> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><strong><span style="color: rgb(123, 12, 0);">经营方式二</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">小明只雇佣一个配送员。当客户下单,小明按送达地点标注好,依次放在一个地方。最后,让配送员依次开着车去送,送好了就回来拿下一个。上述两种经营方式对比,很明显第二种效率更高。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">在上述比喻中:</p> <p style="white-space: normal;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="white-space: normal;">每个配送员→每个线程</p></li> <li><p style="white-space: normal;">每个订单→每个 Socket(I/O 流)</p></li> <li><p style="white-space: normal;">订单的送达地点→Socket 的不同状态</p></li> <li><p style="white-space: normal;">客户送餐请求→来自客户端的请求</p></li> <li><p style="white-space: normal;">明曲的经营方式→服务端运行的代码</p></li> <li><p style="white-space: normal;">一辆车→CPU 的核数</p></li> </ul> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">于是有了如下结论:</p> <p style="white-space: normal;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="white-space: normal;">经营方式一就是传统的并发模型,每个 I/O 流(订单)都有一个新的线程(配送员)管理。</p></li> <li><p style="white-space: normal;">经营方式二就是 I/O 多路复用。只有单个线程(一个配送员),通过跟踪每个 I/O 流的状态(每个配送员的送达地点),来管理多个 I/O 流。</p></li> </ul> <p style="white-space: normal;"><br></p> <p style="white-space: normal;">下面类比到真实的 Redis 线程模型,如图所示:</p> <p style="white-space: normal;text-align: center;"><img class="" data-ratio="0.40976645435244163" src="/upload/278785b0124fec8cdf91cfee7512905d.null" data-type="png" data-w="942" height="250.766px" style="color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;width: 612px !important;visibility: visible !important;" width="612px"></p> <p style="white-space: normal;text-align: left;">Redis-client 在操作的时候,会产生具有不同事件类型的 Socket。在服务端,有一段 I/O 多路复用程序,将其置入队列之中。然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(255, 76, 65);">3、Redis 的数据类型及使用场景</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">一个合格的程序员,这五种类型都会用到。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">String</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">最常规的 set/get 操作,Value 可以是 String 也可以是数字。一般做一些复杂的计数功能的缓存。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">Hash</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">这里 Value 存放的是结构化的对象,比较方便的就是操作其中的某个字段。我在做单点登录的时候,就是用这种数据结构存储用户信息,以 CookieId 作为 Key,设置 30 分钟为缓存过期时间,能很好的模拟出类似 Session 的效果。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">List</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">使用 List 的数据结构,可以做简单的消息队列的功能。另外,可以利用 lrange 命令,做基于 Redis 的分页功能,性能极佳,用户体验好。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">Set</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">因为 Set 堆放的是一堆不重复值的集合。所以可以做全局去重的功能。我们的系统一般都是集群部署,使用 JVM 自带的 Set 比较麻烦。另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">Sorted Set</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">Sorted Set 多了一个权重参数 Score,集合中的元素能够按 Score 进行排列。可以做排行榜应用,取 TOP N 操作。Sorted Set 可以用来做延时任务。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(255, 76, 65);">4、Redis 的过期策略和内存淘汰机制</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">Redis 是否用到家,从这就能看出来。比如你 Redis 只能存 5G 数据,可是你写了 10G,那会删 5G 的数据。怎么删的,这个问题思考过么?</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">正解:Redis 采用的是定期删除+惰性删除策略。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(123, 12, 0);">为什么不用定时删除策略</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">定时删除,用一个定时器来负责监视 Key,过期则自动删除。虽然内存及时释放,但是十分消耗 CPU 资源。在大并发请求下,CPU 要将时间应用在处理请求,而不是删除 Key,因此没有采用这一策略。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(123, 12, 0);">定期删除+惰性删除如何工作</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">定期删除,Redis 默认每个 100ms 检查,有过期 Key 则删除。需要说明的是,Redis 不是每个 100ms 将所有的 Key 检查一次,而是随机抽取进行检查。如果只采用定期删除策略,会导致很多 Key 到时间没有删除。于是,惰性删除派上用场。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(123, 12, 0);">采用定期删除+惰性删除就没其他问题了么</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">不是的,如果定期删除没删除掉 Key。并且你也没及时去请求 Key,也就是说惰性删除也没生效。这样,Redis 的内存会越来越高。那么就应该采用内存淘汰机制。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">在 redis.conf 中有一行配置:</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"># maxmemory-policy volatile-lru</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">该配置就是配内存淘汰策略的:</p> <p style="white-space: normal;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="white-space: normal;text-align: left;">noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。</p></li> <li><p style="white-space: normal;text-align: left;">allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 Key。(推荐使用,目前项目在用这种)(最近最久使用算法)</p></li> <li><p style="white-space: normal;text-align: left;">allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 Key。(应该也没人用吧,你不删最少使用 Key,去随机删)</p></li> <li><p style="white-space: normal;text-align: left;">volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 Key。这种情况一般是把 Redis 既当缓存,又做持久化存储的时候才用。(不推荐)</p></li> <li><p style="white-space: normal;text-align: left;">volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 Key。(依然不推荐)</p></li> <li><p style="white-space: normal;"><br></p></li> <li><p style="white-space: normal;text-align: left;">volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 Key 优先移除。(不推荐)</p></li> </ul> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(255, 76, 65);">5、Redis 和数据库双写一致性问题</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">一致性问题还可以再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。前提是如果对数据有强一致性要求,不能放缓存。我们所做的一切,只能保证最终一致性。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">另外,我们所做的方案从根本上来说,只能降低不一致发生的概率。因此,有强一致性要求的数据,不能放缓存。首先,采取正确更新策略,先更新数据库,再删缓存。其次,因为可能存在删除缓存失败的问题,提供一个补偿措施即可,例如利用消息队列。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(255, 76, 65);">6、如何应对缓存穿透和缓存雪崩问题</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">这两个问题,一般中小型传统软件企业很难碰到。如果有大并发的项目,流量有几百万左右,这两个问题一定要深刻考虑。缓存穿透,即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><span style="color: rgb(123, 12, 0);"><strong>缓存穿透解决方案:</strong></span></p> <p style="white-space: normal;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="white-space: normal;text-align: left;">利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。</p></li> <li><p style="white-space: normal;text-align: left;">采用异步更新策略,无论 Key 是否取到值,都直接返回。Value 值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。</p></li> <li><p style="white-space: normal;text-align: left;">提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的 Key。迅速判断出,请求所携带的 Key 是否合法有效。如果不合法,则直接返回。</p></li> </ul> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">缓存雪崩,即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><span style="color: rgb(123, 12, 0);"><strong>缓存雪崩解决方案:</strong></span></p> <p style="white-space: normal;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="white-space: normal;text-align: left;">给缓存的失效时间,加上一个随机值,避免集体失效。</p></li> <li><p style="white-space: normal;text-align: left;">使用互斥锁,但是该方案吞吐量明显下降了。</p></li> <li><p style="white-space: normal;text-align: left;">双缓存。我们有两个缓存,缓存 A 和缓存 B。缓存 A 的失效时间为 20 分钟,缓存 B 不设失效时间。自己做缓存预热操作。</p></li> <li><p style="white-space: normal;text-align: left;">然后细分以下几个小点:从缓存 A 读数据库,有则直接返回;A 没有数据,直接从 B 读数据,直接返回,并且异步启动一个更新线程,更新线程同时更新缓存 A 和缓存 B。</p></li> </ul> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(255, 76, 65);">7、如何解决 Redis 的并发竞争 Key 问题</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">这个问题大致就是,同时有多个子系统去 Set 一个 Key。这个时候要注意什么呢?大家基本都是推荐用 Redis 事务机制。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">但是我并不推荐使用 Redis 的事务机制。因为我们的生产环境,基本都是 Redis 集群环境,做了数据分片操作。你一个事务中有涉及到多个 Key 操作的时候,这多个 Key 不一定都存储在同一个 redis-server 上。因此,Redis 的事务机制,十分鸡肋。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong>如果对这个 Key 操作,不要求顺序</strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做 set 操作即可,比较简单。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong>如果对这个 Key 操作,要求顺序</strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">假设有一个 key1,系统 A 需要将 key1 设置为 valueA,系统 B 需要将 key1 设置为 valueB,系统 C 需要将 key1 设置为 valueC。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">期望按照 key1 的 value 值按照 valueA > valueB > valueC 的顺序变化。这种时候我们在数据写入数据库的时候,需要保存一个时间戳。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong>假设时间戳如下</strong>:</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">系统 A key 1 {valueA 3:00}</p> <p style="white-space: normal;text-align: left;">系统 B key 1 {valueB 3:05}</p> <p style="white-space: normal;text-align: left;">系统 C key 1 {valueC 3:10}</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">那么,假设系统 B 先抢到锁,将 key1 设置为{valueB 3:05}。接下来系统 A 抢到锁,发现自己的 valueA 的时间戳早于缓存中的时间戳,那就不做 set 操作了,以此类推。其他方法,比如利用队列,将 set 方法变成串行访问也可以。</p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="color: rgb(255, 76, 65);">8、总结</span></strong></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: left;">Redis 在国内各大公司都能看到其身影,比如我们熟悉的新浪,阿里,腾讯,百度,美团,小米等。学习 Redis,这几方面尤其重要:Redis 客户端、Redis 高级功能、Redis 持久化和开发运维常用问题探讨、Redis 复制的原理和优化策略、Redis 分布式解决方案等。</p> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section class="" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;box-sizing: border-box;text-align: left;word-wrap: break-word !important;"> <section class="" style="padding: 10px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 668px;border-width: 1px;border-style: solid;border-color: rgb(226, 226, 226);box-shadow: rgb(226, 226, 226) 0px 16px 1px -13px;word-wrap: break-word !important;"> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;word-wrap: break-word !important;"> <section class="" style="max-width: 100%;box-sizing: border-box;word-wrap: break-word !important;"> <section class="" style="max-width: 100%;box-sizing: border-box;color: rgb(93, 93, 93);word-wrap: break-word !important;"> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;word-wrap: break-word !important;"><br></p> </section> </section> </section> </section> </section> </section>