开往未来的列车|这是我见过最有用的Mysql面试题,面试了无数公司总结的( 三 )

  1. 小明开启事务current_version=6查询名字为'王五'的记录 , 发现不存在 。
  2. 小红开启事务current_version=7插入一条数据 , 结果是这样:

开往未来的列车|这是我见过最有用的Mysql面试题,面试了无数公司总结的
  1. 小明执行插入名字'王五'的记录 , 发现唯一索引冲突 , 无法插入 , 这就是幻读 。
8. 那你知道什么是间隙锁吗?间隙锁是可重复读级别下才会有的锁 , 结合MVCC和间隙锁可以解决幻读的问题 。 我们还是以user举例 , 假设现在user表有几条记录
开往未来的列车|这是我见过最有用的Mysql面试题,面试了无数公司总结的当我们执行:
begin;select * from user where age=20 for update;begin;insert into user(age) values(10); #成功insert into user(age) values(11); #失败insert into user(age) values(20); #失败insert into user(age) values(21); #失败insert into user(age) values(30); #失败只有10可以插入成功 , 那么因为表的间隙mysql自动帮我们生成了区间(左开右闭)
(negative infinity , 10],(10,20],(20,30],(30,positive infinity)由于20存在记录 , 所以(10,20] , (20,30]区间都被锁定了无法插入、删除 。
如果查询21呢?就会根据21定位到(20,30)的区间(都是开区间) 。
需要注意的是唯一索引是不会有间隙索引的 。
9. 你们数据量级多大?分库分表怎么做的?首先分库分表分为垂直和水平两个方式 , 一般来说我们拆分的顺序是先垂直后水平 。
垂直分库
基于现在微服务拆分来说 , 都是已经做到了垂直分库了
开往未来的列车|这是我见过最有用的Mysql面试题,面试了无数公司总结的垂直分表
如果表字段比较多 , 将不常用的、数据较大的等等做拆分
开往未来的列车|这是我见过最有用的Mysql面试题,面试了无数公司总结的水平分表
首先根据业务场景来决定使用什么字段作为分表字段(sharding_key) , 比如我们现在日订单1000万 , 我们大部分的场景来源于C端 , 我们可以用user_id作为sharding_key , 数据查询支持到最近3个月的订单 , 超过3个月的做归档处理 , 那么3个月的数据量就是9亿 , 可以分1024张表 , 那么每张表的数据大概就在100万左右 。
比如用户id为100 , 那我们都经过hash(100) , 然后对1024取模 , 就可以落到对应的表上了 。
10. 那分表后的ID怎么保证唯一性的呢?因为我们主键默认都是自增的 , 那么分表之后的主键在不同表就肯定会有冲突了 。 有几个办法考虑:
  1. 设定步长 , 比如1-1024张表我们分别设定1-1024的基础步长 , 这样主键落到不同的表就不会冲突了 。
  2. 分布式ID , 自己实现一套分布式ID生成算法或者使用开源的比如雪花算法这种
  3. 分表后不使用主键作为查询依据 , 而是每张表单独新增一个字段作为唯一主键使用 , 比如订单表订单号是唯一的 , 不管最终落在哪张表都基于订单号作为查询依据 , 更新也一样 。
11. 分表后非sharding_key的查询怎么处理呢?
  1. 可以做一个mapping表 , 比如这时候商家要查询订单列表怎么办呢?不带user_id查询的话你总不能扫全表吧?所以我们可以做一个映射关系表 , 保存商家和用户的关系 , 查询的时候先通过商家查询到用户列表 , 再通过user_id去查询 。


    推荐阅读