文章目录
MySQL
事务的基本要素(ACID)
-
原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
-
一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
-
隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
-
持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
事务的并发问题
-
脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
-
不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
-
幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
MySQL默认是“可重复读”(REPEATABLE READ)
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 |
读已提交(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
数据库查重复数据
例:重复记录是根据单个字段(peopleId)来判断
select * from people
where peopleId in
(select peopleId from people group by peopleId having count(peopleId) > 1)
注:数据量小时可以使用,数据量大的时候,比如上亿条数据,该如何处理?
InnoDB 锁
锁类型
- Record Lock,锁定单条记录
- Gap Lock,锁定一个范围的记录,但不包括记录本身
- Next-Key Lock,锁定一个范围的记录,并且包含记录本身,这是默认的锁类型
显示加锁
select ... lock in share mode
,加 S 锁select ... for update
,加 X 锁
Redis
数据类型
Redis内部使用一个redisObject对象来表示所有的key和value。
redisObject主要的信息包括数据类型(type)、编码方式(encoding)、数据指针(ptr)、虚拟内存(vm)等。type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部式。
String类型
字符串是Redis值的最基础的类型。Redis中使用的字符串是通过包装的,基于c语言字符数组实现的简单动态字符串(simple dynamic string, SDS)一个抽象数据结构。其源码定义如下:
struct sdshdr {
int len; //len表示buf中存储的字符串的长度。
int free; //free表示buf中空闲空间的长度。
char buf[]; //buf用于存储字符串内容。
};
Hash类型
Hash是一个String类型的field和value之间的映射表,即redis的Hash数据类型的key(hash表名称)对应的value实际的内部存储结构为一个HashMap,因此Hash特别适合存储对象。相对于把一个对象的每个属性存储为String类型,将整个对象存储在Hash类型中会占用更少内存。
应用场景
用一个对象来存储用户信息,商品信息,订单信息等等。
常用命令
- hset——设置key对应的HashMap中的field的value
- hget——获取key对应的HashMap中的field的value
- hgetall——获取key对应的HashMap中的所有field的value
List类型
Redis的List类型其实就是每一个元素都是String类型的双向链表。我们可以从链表的头部和尾部添加或者删除元素。这样的List既可以作为栈,也可以作为队列使用。
应用场景
如好友列表,粉丝列表,消息队列,最新消息排行等。
常用命令
- lpush——在key对应的list的头部添加一个元素。
- lrange——获取key对应的list的指定下标范围的元素,-1表示获取所有元素。
- lpop——从key对应的list的尾部删除一个元素,并返回该元素。
- rpush——在key对应的list的尾部添加一个元素。
- rpop——从key对应的list的尾部删除一个元素,并返回该元素。
Set类型
Redis 集合(Set类型)是一个无序的String类型数据的集合,类似List的一个列表,与List不同的是Set不能有重复的数据。实际上,Set的内部是用HashMap实现的,Set只用了HashMap的key列来存储对象。
应用场景
集合有取交集、并集、差集等操作,因此可以求共同好友、共同兴趣、分类标签等。
常用命令
- sadd——在key对应的set中添加一个元素。
- smembers——获取key对应的set的所有元素。
- spop——随机返回并删除key对应的set中的一个元素。
- sdiff——求给定key对应的set与第一个key对应的set的差集
- suion——求给定key对应的set并集
- sinter——求给定key对应的set交集
SortSet
SortSet顾名思义,是一个排好序的Set,它在Set的基础上增加了一个顺序属性score,这个属性在添加修改元素时可以指定,每次指定后,SortSet会自动重新按新的值排序。
sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score。
应用场景
如按时间排序的时间轴。
常用命令
- zadd ——在key对应的zset中添加一个元素
- zrange——获取key对应的zset中指定范围的元素,-1表示获取所有元素
- zrem——删除key对应的zset中的一个元素
Redis常用命令
键值常用命令
keys/exits/del/expire/ttl/move/persist/randomkey/rename/type
服务器常用命令
ping/echo/select/quit/dbsize/info/config get/flushdb/flushall
MyBatis
缓存
一级缓存
一级缓存是SqlSession级别的缓存,是基于HashMap的本地缓存,不同的SqlSession之间的缓存数据区域互不影响。
二级缓存
默认采用的PerpetualCache,HashMap存储,存储作用域为Mapper(Namespace),并且可自定义存储源,如Ehcache,Redis
更新机制:当某一个作用域(一级缓存Sessioni、二级缓存Namespace)进行了C/U/D操作后,清除缓存
-
BaseCache基础缓存 : 为缓存数据最终存储的处理类,默认为PerpetualCache,基于Map存储;可自定义处理,如使用EhCache、Redis
-
EvictionCache排除算法缓存:当缓存数量达到一定大小后,将通过算法对缓存进行清除。默认采用LRU。
- LRU – 最近最少使用的:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
- WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
-
DecoratorCache装饰器缓存:缓存put/get处理前后的装饰器,如使用 LoggingCache 输出缓存命中日志信息、使用 SerializedCache 对 Cache的数据 put或get进行序列化及反序列化处理、当设置flushInterval(默认1/h)后,则使用 ScheduledCache 对缓存数据进行定时刷新等。
-
一般缓存框架的数据结构基本上都是 Key-Value 方式存储,MyBatis 对于其 Key 的生成采取规则为:[hashcode : checksum : mappedStementId : offset : limit : executeSql : queryParams]。
-
对于并发 Read/Write 时缓存数据的同步问题,MyBatis 默认基于 JDK/concurrent中的ReadWriteLock,使用ReentrantReadWriteLock 的实现,从而通过 Lock 机制防止在并发 Write Cache过程中线程安全问题。
配置
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
在指定的Mapper的namespace下配置
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"></cache>
其它
- 面试中常问的数据库方面问题:https://mp.weixin.qq.com/s/9iBO-fEv14W9ruZq5YWKOQ
- 常见面试题整理–数据库篇:https://blog.csdn.net/weinierzui/article/details/71054964