美文网首页
mysql的连接

mysql的连接

作者: supremecsp | 来源:发表于2021-03-12 16:39 被阅读0次

    mysql的逻辑架构可分为Server层和存储引擎层,在Server层中又包括连接器、查询缓存、分析器、优化器、执行器;
    其中连接器就是与mysql建立连接的模块,连接器采用的是TCP连接,在完成握手之后需要对当前用户进行身份认证。
    由于建立连接的过程通常是比较复杂的,所以建议一般使用长连接
    但是全部使用长连接后,你可能会发现,有些时候MySQL占用内存涨得特别快,这是因为 MySQL在执行过程中临时使用的内存是管理在连接对象里面的。
    这些资源会在连接断开的时候 才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现 象看就是MySQL异常重启了。 怎么解决这个问题呢?
    你可以考虑以下两种方案。

    1. 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开 连接,之后要查询再重连。
    2. 如果你用的是MySQL 5.7或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection来重新初始化连接资源。这个过程不需要重连和重新做权限验证, 但是会将连接恢复到刚刚创建完时的状态。

    对于JAVA来说,与mysql的jdbc连接,若是手动操作的话可以操控连接时间与结束时机
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306", "XXX", "XXX");
    // 释放连接
    conn.close();
    而使用mybatis的话mybatis 和 spring 是通过代理方式完成 connection连接的关闭.而且是通过jdk的代理.
    具体可以看https://www.cnblogs.com/lishuaiqi/p/11050187.html
    此时引出一个SqlSession的概念,Connection 交由SqlSession 一起关闭
    前面说了连接是比较耗时的操作,为什么一次session就关了,其实此时的Connection.close()方法是将这个Connection放回连接池、而不是关闭。https://www.kancloud.cn/digest/andyalien-mybatis/190199

    至于SqlSession属于一次会话:如果多个请求同一个事务中,那么多个请求都在共用一个SqlSession,反之每个请求都会创建一个SqlSession。简单来说每次访问数据库时都需要创建它。

    说到连接,在业务开发中有个原则不建议在for循环操作数据库,这是为什么呢?
    由于for循环不开事务的话会创建多个SqlSession,频繁从连接池获取连接,还要多次IO到数据库,所以就不建议用它了
    替换方案,方法加事务注解@Transactional或者mapper foreach批量处理。这两种分别有对应的使用场景(以下说明建立在对应字段拥有索引的前提)
    批量处理:foreach使用一般是在配合in使用,此时有个概念叫局部性原理,linux一页的数据一次性会都全部拿到mysql缓存起来,所以in里面的数据若是连续的话,那么linux和mysql的交互次数会少很多,因此foreach多用于in中数据连续的时候
    当然,in的缺陷也有,它最多只能查200个数据,超过的话索引失效,使用时考虑好
    @Transactional:不是什么时候for循环操作数据库都能转化成in的,此时Transactional排上用场了,把for循环整个包装成一个事务执行,一次连接;缺点不能滥用,大事务造成的影响很大,有时间开篇文章
    其实Transactional和foreach批量处理,压测的发现效率差不了多少,不必太在意选择哪个

    注:局部性原理,二维数据行列遍历经典例子(https://blog.csdn.net/Shuffle_Ts/article/details/89420651),行会比列遍历快很多

    相关文章

      网友评论

          本文标题:mysql的连接

          本文链接:https://www.haomeiwen.com/subject/dmdzqltx.html