关于面试时面试官提出的一些疑问,求解答
source link: https://www.v2ex.com/t/793477
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
问题 2:面试官问 redis 缓存和数据库一致性问题,我说:增删改的时候先删 redis 缓存再操作数据库。面试官问如果 redis 删除失败了怎么办?我说:redis 操作失败了就抛出异常,不会再对数据库操作。面试官问:如果需要 redis 操作失败的情况下也需要对数据库增删改成功,并且避免读出脏数据,改怎么做?我没想出来。
第 1 条附言 · 6 小时 15 分钟前
问题 1:像这种联合索引碰到范围查询后的字段就不会走索引了, 也就是 a 和 b 会走索引,而 c 不会走索引,因为在 B+树中,会根据条件 a=1 和 b>2 找到相应的叶子节点,查询出来的结果如果为(1,3,1),(1,5,0),那么根据 order by c 就要重新排序为,(1,5,0),(1,3,1),所以 c 是不会用到索引的。但是索引还是会走这个联合索引。
问题 2:可以用消息队列延迟双删。先删缓存,再操作数据库,数据库操作完成事务提交后,再去向消息队列发一个延迟消息(延迟时间在业务允许的范围内),这个延迟消息用来删除缓存。
CEBBCAT 18 小时 9 分钟前 via Android
但第二个这题目的背景我想可以转换为 Redis 不可达,在这种情况下还不想读到脏数据,你鲨了我吧
levelworm 17 小时 24 分钟前
https://dev.mysql.com/doc/refman/8.0/en/multiple-column-indexes.html
>MySQL can use multiple-column indexes for queries that test all the columns in the index, or queries that test just the first column, the first two columns, the first three columns, and so on. If you specify the columns in the right order in the index definition, a single composite index can speed up several kinds of queries on the same table.
感觉和索引中列的顺序有关,比如下面的例子给了:
如果对 last_name,first_name 建立联合索引,但是仅仅查询 first_name,就不会用到这个索引。感觉说的和你一样啊,只要是最左前缀匹配就可以了,除非他建立索引的顺序不是 a, b, c 。
sagaxu 16 小时 49 分钟前
yinusxxxx 10 小时 36 分钟前
yidinghe 8 小时 29 分钟前 via Android
wugq 8 小时 0 分钟前
chenshun00 7 小时 44 分钟前
chenshun00 7 小时 37 分钟前
CREATE TABLE `test_table` (
`action` varchar(64) NOT NULL,
`projectId` int(11) NOT NULL COMMENT 'yapi 项目 ID',
`projectName` varchar(32) NOT NULL COMMENT '项目名字',
`catId` int(11) NOT NULL COMMENT 'API 分类 ID',
`catName` varchar(64) NOT NULL COMMENT 'API 分类名字',
`apiDesc` varchar(512) NOT NULL COMMENT 'API 分类描述',
`title` varchar(64) NOT NULL COMMENT 'API 标题',
`path` varchar(64) NOT NULL COMMENT 'http 请求路径',
`method` varchar(12) NOT NULL COMMENT 'api 请求方法',
`upTime` datetime NOT NULL DEFAULT '2020-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`addTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间',
`version` varchar(32) NOT NULL COMMENT '版本',
`status` varchar(16) NOT NULL COMMENT 'api 状态(上线 /下线)',
`fullinfo` text NOT NULL COMMENT 'API fullinfo 信息',
`visibility` tinyint(4) NOT NULL DEFAULT '0',
`session` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`action`),
KEY `test_table_projectId_catId_path_index` (`projectId`,`catId`,`path`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
```
desc select * from test_table where projectId = '11111' and catId >2 order by path;
key: test_table_projectId_catId_path_index
extra: Using index condition; Using filesort
EmptyDX 7 小时 13 分钟前
fkname 6 小时 59 分钟前
whoosy 6 小时 31 分钟前
atalia 6 小时 13 分钟前
第二题缓存层和持久层操作顺序都是先持久层,再缓存层把。至于面试官的要求估计只能保证单进程级别的,跨进程除非用通信去通知所有进程标记。
eric96 6 小时 5 分钟前
实际使用,是用了这个联合索引来查找的,然后由于 b>2,导致无法用这个索引来做排序,需要用到 file sort
admol 5 小时 55 分钟前 2
事物隔离级别:RR,引擎:innoDB ; MYSQL 版本:8.0.22
创建表:
CREATE TABLE `test` (
`id` int NOT NULL AUTO_INCREMENT,
`a` int DEFAULT NULL,
`b` int DEFAULT NULL,
`c` int DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ids_a_b_c` (`a`,`b`,`c`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
插入测试数据:
INSERT INTO `my`.`test`(`id`, `a`, `b`, `c`) VALUES (1, 1, 1, 1);
INSERT INTO `my`.`test`(`id`, `a`, `b`, `c`) VALUES (2, 2, 2, 2);
INSERT INTO `my`.`test`(`id`, `a`, `b`, `c`) VALUES (5, 2, 3, 3);
INSERT INTO `my`.`test`(`id`, `a`, `b`, `c`) VALUES (6, 2, 3, 4);
INSERT INTO `my`.`test`(`id`, `a`, `b`, `c`) VALUES (3, 3, 3, 3);
INSERT INTO `my`.`test`(`id`, `a`, `b`, `c`) VALUES (4, 4, 4, 4);
执行计划:
explain select * from test WHERE a = 2 and b > 2 ORDER BY c;
mysql> explain select * from test WHERE a = 2 and b > 2 ORDER BY c;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+------------------------------------------+
| 1 | SIMPLE | test | NULL | range | ids_a_b_c | ids_a_b_c | 10 | NULL | 2 | 100.00 | Using where; Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+------------------------------------------+
1 row in set (0.02 sec)
结果:
type 为 range
key 为 ids_a_b_c (建的联合索引)
Extra 为 Using where; Using index; Using filesort
Using index 说明相应的 select 操作中使用了覆盖索引
Using filesort 说明排序确实没走索引
第二题:
延迟双删,保证数据的最终一致性
“redis 操作失败的情况下也需要对数据库增删改成功,并且避免读出脏数据” 这种情况下,可以用 Canal 订阅 binlog 完成数据同步,保证数据的最终一致性。
WillLiao 5 小时 44 分钟前
问题 1,楼主说满足最左匹配会使用索引没有问题,a 等值,b 范围,范围后的操作不会使用索引,但总体来看还是用到了组合索引
问题 2,就是在瞎扯,这种情况就应该说做不到,没有必要保持强一致性,要保持强一致性你还引入 redis 干嘛?
offswitch 5 小时 26 分钟前
https://dev.mysql.com/doc/refman/8.0/en/order-by-optimization.html
第二题,操作失败也要保证增删成功,避免读出脏数据,那么你就要考虑 redis 与服务节点之间网络分区恢复的问题,考虑单节点、多节点数据的问题,要在节点标记数据为脏数据,网络恢复后,根据节点脏数据过滤,读 db.
allAboutDbmss 5 小时 2 分钟前
```
jigao=# create table A (a int, b int, c int);
CREATE TABLE
jigao=# insert into A values (1, 2, 3);
INSERT 0 1
jigao=# insert into A values (1, 3, 4);
INSERT 0 1
jigao=# insert into A values (2, 5, 6);
INSERT 0 1
jigao=# select * from A;
a | b | c
---+---+---
1 | 2 | 3
1 | 3 | 4
2 | 5 | 6
(3 rows)
jigao=# select * from A where a=1 and b > 2 order by c;
a | b | c
---+---+---
1 | 3 | 4
(1 row)
jigao=# explain select * from A where a=1 and b > 2 order by c;
QUERY PLAN
---------------------------------------------------------
Sort (cost=40.62..40.63 rows=3 width=12)
Sort Key: c
-> Seq Scan on a (cost=0.00..40.60 rows=3 width=12)
Filter: ((b > 2) AND (a = 1))
(4 rows)
jigao=# create index id on A (a, b, c);
CREATE INDEX
jigao=# select * from A where a=1 and b > 2 order by c;
a | b | c
---+---+---
1 | 3 | 4
(1 row)
jigao=# explain select * from A where a=1 and b > 2 order by c;
QUERY PLAN
--------------------------------------------------------
Sort (cost=1.05..1.06 rows=1 width=12)
Sort Key: c
-> Seq Scan on a (cost=0.00..1.04 rows=1 width=12)
Filter: ((b > 2) AND (a = 1))
(4 rows)
jigao=# drop index id;
DROP INDEX
jigao=# explain select * from A where a=1 and b > 2 order by c;
QUERY PLAN
--------------------------------------------------------
Sort (cost=1.05..1.06 rows=1 width=12)
Sort Key: c
-> Seq Scan on a (cost=0.00..1.04 rows=1 width=12)
Filter: ((b > 2) AND (a = 1))
(4 rows)
```
观察现象是: 没用使用到 index
但是这个主要是 cost-based 这些不一定是可以这样面试情况下有一个确定答案 我觉得就是问一个思路而已
fkdog 2 小时 38 分钟前
然而事实上大部分系统并不需要强一致性, 对于这类对一致性要求并不高的系统, 可以通过消息队列等手段达到最终一致性效果.
weizhen199 2 小时 16 分钟前
小表就 table scan 了
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK