mysql 8.0 默认认证插件为 caching_sha2_password,导致旧客户端连接 localhost 失败;应改用 mysql_native_password 插件,并按行为拆分关注、拉黑等关系表,避免单表膨胀。

MySQL 8.0 安装后连不上 localhost?检查这三处
默认安装完 MySQL 8.0,mysql -u root -p 报 access denied for user 'root'@'localhost',不是密码错了,而是认证插件变了。MySQL 8.0 默认用 caching_sha2_password,老客户端(比如某些 Python 的 mysql-connector-python 旧版)不认。
- 临时解决:启动时加
--default-authentication-plugin=mysql_native_password - 长期方案:进 MySQL 后执行
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 确认生效:查
select Host,User,plugin FROM mysql.user;,确保root@localhost对应的plugin是mysql_native_password
用户关系表设计别直接上 friendship 表
社交场景里“关注”“拉黑”“双向好友”逻辑不同,硬塞一张 friendship 表,后期加状态字段、索引爆炸、查询变慢。更稳的做法是按行为拆表。
-
follows:记录单向关注,字段至少含follower_id、followee_id、created_at,联合索引(follower_id, followee_id)必加 -
blocks:拉黑关系,同样结构,但查“谁能看到我”时得先排除blocks里的记录 - 真要存双向好友,用应用层判断:查
follows里A→B和B→A是否同时存在,别冗余存is_mutual
用 INSERT IGNORE 还是 ON DUPLICATE KEY UPDATE 处理重复关注?
用户点两次“关注”,后端不能报错或静默失败,得明确告诉前端“已关注”。这时候不能只靠唯一索引 + INSERT IGNORE,它会吞掉所有错误,包括磁盘满、锁超时等非业务问题。
- 推荐用
INSERT ... ON DUPLICATE KEY UPDATE updated_at = NOW(),唯一索引设在(follower_id, followee_id)上 - 成功插入返回
affected_rows == 1,更新返回2(MySQL 8.0+),可据此区分“新关注”和“已存在” - 避免用
REPLACE INTO:它本质是删+插,会触发自增 ID 跳变、外键级联风险高
查“共同关注”为什么越查越慢?
类似“你和张三都关注了哪些人”,用 INNER JOIN 查两个用户的 follows 表,数据量一过百万,响应就卡住。不是 SQL 写得不对,是缺少覆盖索引和结果集预估。
- 必须建联合索引:
CREATE INDEX idx_followee_follower ON follows(followee_id, follower_id);(注意顺序!) - 加
LIMIT 50强制约束结果大小,不然用户刷到底部时可能扫全表 - 别在应用层用两个
SELECT结果做内存交集,数据库的JOIN在索引到位时比 Pythonset.intersection()快一个数量级
关系链的边界永远比想象中模糊——比如“被拉黑的人是否还出现在搜索建议里”,这种逻辑不会写在建表语句里,得靠每次查询时主动 LEFT JOIN blocks 过滤。漏一次,就是一次数据泄露。