. Z O, O3 V% J! L T问了一圈,身边朋友公司要么用自研,要么就清一色的MySQL,所以想看Oracle的朋友可能要失望了,但是不影响你了解数据库的通用知识。 d' G' s8 ]5 U v: P. F. q3 }. v, v6 D: K2 ^% o$ ^: i
正文+ T2 X( y U Y0 }
! w; A! B1 @. d& o3 X
你知道MySQL的基本架构么?你能在纸上给我大致画出这个示意图么?' C+ Q, y6 ?& w5 F$ x, e `0 M
8 d8 Q3 \7 j$ M/ s, M4 W6 t这里需要注意的是,我们数据库的客户端太久没响应,连接器就会自动断开了,这个时间参数是wait_timeout控制住的,默认时长为8小时。 0 N! L2 v. N" n5 w. R7 l+ q8 n$ r. |. A1 i9 U, @
断开后重连的时候会报错,如果你想再继续操作,你就需要重连了。 " g' W$ z3 v$ H4 R. G' H8 w& D$ j# `% i2 x, \4 B! L
这个有个我看过的书本的案例:9 N# @. ~2 }/ ], G! w
) d2 c2 c8 L- O q" Y, T一个在政府里的朋友说,他们的系统很奇怪,每天早上都得重启一下应用程序,否则就提示连接数据库失败,他们都不知道该怎么办。: E8 v- L) D) X
我分析说,按照这个错误提示,应该就是连接时间过长了,断开了连接。数据库默认的超时时间是8小时,而你们平时六点下班,下班之后系统就没有人用了,等到第二天早上九点甚至十点才上班,这中间的时间已经超过10个小时了,数据库的连接肯定就会断开了。6 o# \6 B' s, K4 k# n0 L0 k9 I
是的,就是超出了超时时间,然后写代码的人也没注意到这个细节,所以才会出现这个问题。4 a& t7 S# T3 h! o6 B! v
& r( _1 v) x f0 k2 ^2 Y% E
把超时时间改得长一点,问题就解决了。 & f3 [- y* M P6 p : k- n, W8 S, Q2 y这种参数其实我们平时不一定能接触到,但是真的遇到问题的时候,知道每个参数的大概用法,不至于让你变成无头苍蝇。4 O% o4 V! g& J7 Y
1 X" n5 B; K1 }7 l/ q那除了重新链接,还有别的方式么?因为建立链接还是比较麻烦的。1 e& G" m$ S; x$ y
使用长连接。 * q2 Y4 |+ Q* b. W3 k" l4 \ z3 o- Z- U/ h Y* }0 |
但是这里有个缺点,使用长连接之后,内存会飙得很快,我们知道MySQL在执行过程中临时使用的内存是管理在连接对象里面的。 4 R7 ?/ w7 e* f6 `* l% t; ^2 L s3 N0 H9 R E
只有在链接断开的时候才能得到释放,那如果一直使用长连接,那就会导致OOM(Out Of Memory),会导致MySQL重启,在JVM里面就会导致频繁的Full GC。 " V. a5 O2 x0 n! m( z3 w: I9 c& a5 E6 [ Y) N( g2 ?
那你会怎么解决?: a: F+ b8 _3 L/ }, s# u( Y
我一般会定期断开长连接,使用一段时间后,或者程序里面判断执行过一个占用内存比较大的查询后就断开连接,需要的时候重连就好了。+ u# i+ L, y0 W
8 ~' s" q a" `9 l+ }6 o
还有别的方法么?你这种感觉不优雅呀小老弟。 0 \- b7 k. J l5 A7 p. c. M, N执行比较大的一个查询后,执行mysql_reset_connection可以重新初始化连接资源。这个过程相比上面一种会好点,不需要重连,但是会初始化连接的状态。 1 {$ i9 n0 w! S 5 l# X4 s8 }, Q" t0 u你了解MySQL的查询缓存么?* B; o/ h. ?+ {: d" b+ t3 f h
MySQL拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。$ F3 u0 X& o V' o& i n5 ]
) ~' C8 h' x/ Z7 |大家是不是好奇同一条语句在MySQL执行两次,第一次和后面的时间是不一样的,后者明显快一些,这就是因为缓存的存在。" `9 c- j7 h+ S. `6 j, I
8 W& U7 Y6 e/ r9 r) M他跟Redis一样,只要是你之前执行过的语句,都会在内存里面用key-value形式存储着。 " Q3 a. [* x: T, D! b- v' [/ Y: U
查询的时候就会拿着语句先去缓存中查询,如果能够命中就返回缓存的value,如果不命中就执行后面的阶段。8 f5 T: m0 F' `* `! m* P