您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

大厂为何禁止使用Mybatis的一级和二级缓存?

时间:2023-04-20 14:15:57  来源:今日头条  作者:Java编程世界

MyBatis具有很多特性,包括支持一级和二级缓存。尽管缓存是提高性能的重要手段,但MyBatis的一级和二级缓存并不被建议使用。所以我们今天就来看看到底会有什么问题?

一、什么是MyBatis的一级和二级缓存?

在深入了解MyBatis的一级和二级缓存的缺点之前,我们需要先了解什么是MyBatis的一级和二级缓存。在MyBatis中,缓存可以提高查询性能,因为它们可以避免频繁地向数据库发送查询。MyBatis提供了两种缓存机制:一级缓存和二级缓存。

一级缓存是在MyBatis的SqlSession级别上运作的。在同一个SqlSession中执行的查询会被缓存起来,以便在后续的查询中重用。默认情况下,MyBatis启用了一级缓存。

二级缓存是在MApper级别上运作的。这意味着在多个SqlSession之间,查询的结果可以被缓存起来并重用。MyBatis使用基于命名空间的二级缓存,这意味着每个Mapper都有自己的缓存。

尽管缓存可以提高查询性能,但使用MyBatis的缓存机制并不总是最好的选择。

二、一级缓存示例

假设我们有一个UserMapper接口和一个User类,我们可以使用以下代码来演示MyBatis的一级缓存:

public interface UserMapper {
    User getUserById(int id);
}

SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

// 第一次查询
User user1 = userMapper.getUserById(1);

// 第二次查询
User user2 = userMapper.getUserById(1);

System.out.println(user1 == user2); // true

在上面的代码中,我们首先获取一个SqlSession,并通过该Session获取一个UserMapper实例。然后我们执行两次getUserById方法来查询ID为1的用户对象。

由于MyBatis默认启用了一级缓存,因此第二次查询将不会再次查询数据库,而是从一级缓存中获取数据。因此,两次查询返回的User对象是同一个对象,user1 == user2的结果为true。

 

三、MyBatis的一级缓存存在的问题

  1. 没有缓存命中率

MyBatis的一级缓存只适用于同一个SqlSession,因此它在多个SqlSession之间是无效的。这意味着如果您需要执行多个查询,并且这些查询需要在不同的SqlSession中执行,那么一级缓存就无法提供任何帮助。这种情况下,每次查询都需要从数据库中获取数据,因此缓存命中率为0。

  1. 线程安全问题

MyBatis的SqlSession并不是线程安全的,因此在多线程环境下使用一级缓存可能会导致问题。如果两个线程共享同一个SqlSession,并且其中一个线程执行了一个查询,那么另一个线程可能会从缓存中获取到不正确的结果。因此,如果您在多线程环境中使用MyBatis,请确保每个线程都有自己的SqlSession。

  1. 没有清除机制

MyBatis的一级缓存没有自动清除机制。这意味着如果您在SqlSession中执行了更新、插入或删除操作,那么这些操作将会使缓存失效。但是,如果您在执行这些操作之前没有清除缓存,那么缓存中的数据将会是旧的,这可能会导致应用程序中的错误。

  1. 内存泄漏问题

MyBatis的一级缓存存储在内存中,因此如果您在应用程序中长时间使用同一个SqlSession,那么缓存中的数据可能会占用大量内存。这可能会导致内存泄漏问题,尤其是在长时间运行的应用程序中。

基于这些问题,我们可以看出MyBatis的一级缓存并不是最好的选择。因此,如果您需要缓存查询结果以提高性能,可以考虑使用二级缓存。

四、二级缓存示例

我们可以使用以下代码演示MyBatis的二级缓存:

<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
public interface UserMapper {
    @Select("select * from users where id = #{id}")
    @ResultMap("userResultMap")
    User getUserById(int id);
}

在上面的代码中,我们首先在MyBatis的配置文件中添加了一个cache元素来配置二级缓存。该元素包含了eviction、flushInterval、size和readOnly属性。

然后我们在UserMapper接口中添加了一个@Select注解来声明一个SQL查询,并将其与一个@ResultMap注解关联。这个查询方法将会被缓存。

最后,我们可以使用以下代码来测试二级缓存:

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();

UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

// 第一次查询
User user1 = userMapper1.getUserById(1);

// 将SqlSession1中的缓存写入到二级缓存
sqlSession1.commit();

// 第二次查询
User user2 = userMapper2.getUserById(1);

System.out.println(user1 == user2); // true

在上面的代码中,我们首先获取两个SqlSession,并通过每个Session获取一个UserMapper实例。然后我们在第一个Session中执行getUserById方法来查询ID为1的用户对象,并将其缓存到一级缓存和二级缓存中。

接下来,我们将Session1中的缓存刷新到二级缓存中,并关闭Session1。

然后我们在Session2中执行getUserById方法来查询ID为1的用户对象。由于该查询方法被缓存到二级缓存中,因此第二次查询将从二级缓存中获取数据,而不是从数据库中查询。因此,两次查询返回的User对象是同一个对象,user1 == user2的结果为true。

 

五、MyBatis的二级缓存存在的问题

虽然MyBatis的二级缓存在某些情况下可以提高查询性能,但是它也存在一些问题。

  1. 缓存同步问题

MyBatis的二级缓存是在多个SqlSession之间共享的,这意味着如果您在一个SqlSession中执行了更新、插入或删除操作,那么其他SqlSession中的缓存将会失效。但是,MyBatis并没有提供缓存同步机制,因此在更新、插入或删除操作之后,其他SqlSession中的缓存将不再可用,直到缓存被刷新为止。

  1. 数据库事务问题

MyBatis的二级缓存是在内存中存储的,因此如果应用程序中使用了多个数据库事务,那么可能会导致数据不一致的问题。例如,如果一个事务中更新了一个表中的数据,而另一个事务中使用了这个表中的数据,那么就会出现数据不一致的情况。

  1. 内存占用问题

MyBatis的二级缓存存储在内存中,因此如果缓存中的数据量很大,那么可能会导致内存占用过高的问题。这可能会导致性能问题,并且可能需要定期刷新缓存以避免内存泄漏问题。

基于这些问题,我们可以看出MyBatis的二级缓存并不是最好的选择。因此,如果您需要缓存查询结果以提高性能,可以考虑使用其他缓存解决方案,例如redis或Memcached。

四、结论

在本文中,我们探讨了为什么MyBatis的一级和二级缓存都不建议使用。虽然缓存可以提高查询性能,但MyBatis的缓存机制在某些情况下会导致性能问题和数据不一致的问题。因此,如果您需要缓存查询结果以提高性能,请考虑使用其他缓存解决方案,并定期刷新缓存以避免内存泄漏问题。

如果您仍然需要使用MyBatis的缓存机制,请使用以下建议来最大化性能和可靠性:

  • 使用二级缓存而不是一级缓存,因为二级缓存可以在多个SqlSession之间共享。
  • 避免在缓存中存储大量数据,因为这可能会导致内存占用过高的问题。
  • 定期刷新缓存以避免内存泄漏问题。
  • 避免在更新、插入或删除操作之后未及时清除缓存。
  • 避免在多个数据库事务中使用缓存。


Tags:Mybatis   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Mybatis参数映射搞不明白?来试试这个工具吧!
之前在《使用技巧-Mybatis参数映射》《使用技巧-Mybatis参数映射(2)》提到了Mybatis的一些参数映射技巧,但是平时使用的时候有些小伙伴可能不知道自己写的#{}表达式能不能获取...【详细内容】
2024-02-28  Search: Mybatis  点击:(33)  评论:(0)  加入收藏
如何在Spring项目中配置MP(MyBatis-Plus)集成?
在Spring项目中集成MP,需要进行以下配置:1. 引入依赖:在项目的pom.xml文件中添加MP相关依赖,例如:```xml<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plu...【详细内容】
2024-01-09  Search: Mybatis  点击:(87)  评论:(0)  加入收藏
Mybatis占位符#和$的区别?源码解读
本文针对笔者日常开发中对 Mybatis 占位符 #{} 和 ${} 使用时机结合源码,思考总结而来 &bull; Mybatis 版本 3.5.11 &bull; Spring boot 版本 3.0.2 &bull; mybatis-spring...【详细内容】
2023-10-27  Search: Mybatis  点击:(399)  评论:(0)  加入收藏
看完这篇文章,你也可以手写MyBatis部分源码(JDBC)
一、持久化机制持久化(persistence): 把数据保存到可调电式存储设备中以供之后使用。大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以”固化...【详细内容】
2023-10-09  Search: Mybatis  点击:(332)  评论:(0)  加入收藏
Mybatis-Flex初体验
本篇文章内容主要包括: MyBatis-Flex 介绍MyBatis-Flex 是一个优雅的 MyBatis 增强框架,它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用 Mybaits-Flex 链接任何...【详细内容】
2023-09-24  Search: Mybatis  点击:(196)  评论:(0)  加入收藏
MyBatis简单易用的背后隐藏的挑战
MyBatis,作为一款备受欢迎的持久层框架,它的简单易用以及灵活的配置吸引了无数的开发者。然而,随着项目的不断发展,规模的逐渐扩大,MyBatis的一些挑战也开始逐渐浮出水面。首先,由...【详细内容】
2023-09-15  Search: Mybatis  点击:(242)  评论:(0)  加入收藏
MyBatis缓存机制
MyBatis 的缓存机制属于本地缓存,适用于单机系统,它的作用是减少数据库的查询次数,提高系统性能。MyBaits 中包含两级本地缓存: 一级缓存:SqlSession 级别的,是 MyBatis 自带的缓...【详细内容】
2023-09-12  Search: Mybatis  点击:(229)  评论:(0)  加入收藏
对比 MyBatis 和 MyBatis-Plus 批量插入、批量更新的性能和区别
1 环境准备1.1 搭建 MyBatis-Plus 环境 创建 maven springboot 工程 导入依赖:web 启动器、jdbc、、java 连接 mysql、Lombok、druid 连接池启动器、mybatis-plus 启动器 编...【详细内容】
2023-09-08  Search: Mybatis  点击:(191)  评论:(0)  加入收藏
Spring Data JPA 和 MyBatis 谁更强?
我无法明确的告诉你JPA和MyBatis在国内哪个会更流行,我本人更喜欢JPA,但是我本人日常开发用MyBatis多。但是我的回答绝对不是在划水,而是我多年来自己的一点小小的思考。MyBati...【详细内容】
2023-08-22  Search: Mybatis  点击:(335)  评论:(0)  加入收藏
Mybatis-Plus可能会导致数据库死锁
一、场景还原1.版本信息MySQL版本:5.6.36-82.1-logMybatis-Plus的starter版本:3.3.2存储引擎:InnoDB2.死锁现象A同学在生产环境使用了Mybatis-Plus提供的com.baomidou.mybatisp...【详细内容】
2023-08-14  Search: Mybatis  点击:(171)  评论:(0)  加入收藏
▌简易百科推荐
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(6)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(13)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(9)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(11)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(9)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
Kubernetes 究竟有没有 LTS?
从一个有趣的问题引出很多人都在关注的 Kubernetes LTS 的问题。有趣的问题2019 年,一个名为 apiserver LoopbackClient Server cert expired after 1 year[1] 的 issue 中提...【详细内容】
2024-03-15  云原生散修  微信公众号  Tags:Kubernetes   点击:(6)  评论:(0)  加入收藏
站内最新
站内热门
站内头条