分享人:许东杰
1.背景介绍
2.知识剖析
3.常见问题
4.解决方案
5.编码实战
6.扩展思考
7.参考文献
1.背景介绍
脏数据:从目标中取出的数据已经过期、错误或者没有意义,这种数据就叫做脏数据。
脏读:读取出来脏数据就叫脏读。
数据库中的并发事务处理问题:
脏读:在并发访问的情况下,不同的事务对相同的数据进行操作,在事务A修改数据还未提交的时候,事务B对该数据进行读取,读出了事物A修改过后的数据,但是事物A最终没有提交,这种情况就是数据库中的脏读情况
更新丢失:对于同一行数据不同事务进行更新,结果覆盖
幻读:事务A前后两次读取,后一次读取的数据变多了,事物B在两次读取中间已经进行数据插入
不可重复读:事务A读取了事务B修改前后的两次数据,不符合隔离型
隔离等级:可以解决上述问题,mysql默认可重复读的隔离等级,只会存在读取的数据和数据库不一致的问题
mybati一级缓存中的脏数据:
mybatis的一级缓存:默认是SqlSession级别,只要通过session查过的数据,都会放在session上,下一次再查询相同id的数据,都直接冲缓存中取出来,而不用到数据库里去取了。
mybatis一级缓存脏数据:当有不同的sqlSession在对数据库进行操作,一级缓存只能保证当前sqlSession中的增删改在一级缓存中自动更新,就会产生脏数据。
mybati二级缓存中的脏数据:
mybatis二级缓存:是SessionFactory级别,和namespace绑定,同一个namespace放到一个缓存对象中,当这个namaspace中执行了非sselect语句的时候,整个namespace中的缓存全部清除掉。
mybatis二级缓存脏数据:引起脏读的操作通常发生在多表关联操作中,比如在两个不同的mapper中都涉及到同一个表的增删改查操作,当其中一个mapper对这张表进行查询操作,此时另一个mapper进行了更新操作刷新缓存,然后第一个mapper又查询了一次,那么这次查询出的数据是脏数据。出现脏读的原因是他们的操作的缓存并不是同一个。
所以不推荐使用mybatis的自带一二级缓存,推荐使用第三方缓存:memcached或者redis。
redis中怎么更新缓存避免脏读?
读写部分: if(redis存在数据){ 读取redis数据 }else{ 数据库读取,同时存redis+设置超时时间
更新部分: if(数据库update){ 更新redis+设置超时时间
演示读写部分和更新部分
还有哪些其他方式进行redis数据更新
1、主动更新:后台点击更新缓存按钮,从DB查找最新数据集合,删除原缓存数据,存储新数据到缓存(或者用定时任务来做)
问题:更新过程中删除掉缓存后刚好有业务在查询,那么这个时候返回的数据会是空,会影响用户体验,如果高并发穿透DB,可能导致服务器崩溃
2、由用户触发更新:前台获取数据时发现没有缓存数据就会去数据库同步数据到缓存
问题:当并发请求获取缓存数据不存在的时候,就会产生并发的查询数据的操作
3、提前加载好数据:后台点击更新缓存按钮,从DB查找最新数据集合,这里不删除缓存,通过遍历数据覆盖和删除掉无效的数据
问题:逻辑相对麻烦,而且更新机制无法通用
百度、谷歌
感谢观看,如有出错,恳请指正
BY :许东杰