treehollow / treehollow-backend

T大树洞 的Golang后端
https://thuhole.com/
GNU Affero General Public License v3.0
167 stars 47 forks source link

数据库 attentions 字段风险问题 #34

Closed rcy17 closed 4 years ago

rcy17 commented 4 years ago

涉及代码

init_db.sql 可以看到 user_infoattentions 字段的的定义如下:

create table user_info
(
    email_hash CHAR(64) NOT NULL,
    token      CHAR(32) NOT NULL,
    timestamp  INT      NOT NULL,
    attentions VARCHAR(10000),
    PRIMARY KEY (email_hash),
    INDEX (token)
) DEFAULT CHARSET = ascii;

而关于这个长度上限为 10000 的字符串 attentions 的核心解析如下:

func charToInt(c int) int {
    if c <= '9' {
        return c - int('0')
    } else {
        return c - int('a') + 10
    }
}

func hexToIntSlice(str string) []int {
    rtn := make([]int, len(str)/8)

    res := int(0)
    for i, r := range str {
        res = res + charToInt(int(r))<<(4*(7-(i%8)))
        if (i+1)%8 == 0 {
            rtn[i/8] = res
            res = 0
        }
    }
    return rtn
}

func intSliceToHex(array []int) string {
    var rtn string
    for _, n := range array {
        rtn += fmt.Sprintf("%08x", n)
    }
    return rtn
}

潜在风险

如果我没理解错的话,这个设定有以下问题:

  1. 在没有必要用 VARCHAR 的场合使用它,对数据库空间利用率不高;
  2. 在查询、添加关注时,都需要对 attentions 字符串进行遍历与解析,效率不高;
  3. 当前树洞已经有近四千条,不出几日即可达到万规模,而这个设定下最多仅能容纳 1250 条,且用的是栈式结构,如果数据库用的是 mysql 的 ANSI 模式,将会在第 1251 个关注时由于记录截断而出现关注失败的情况。

建议

  1. 老老实实建立多对多关系表吧
  2. 我不知道现在关注最多到了什么量级,从个人使用来看不会特别多,因为目前仅发帖和回复会关注,但是倘若出现增长速率过快导致优化结构前达到 1250 的水准,可以考虑把栈式结构改为队列结构,对用户而言就不会有bug体验。
thuhole commented 4 years ago

这个问题实际上被吐槽很多次了hhh将在#20修复

thuhole commented 4 years ago

如果有PR欢迎啊

thuhole commented 4 years ago

毕竟是,敏捷开发hhhhh你可以看看历史commit的开发频率是什么样的hhh

thuhole commented 4 years ago

https://github.com/thuhole/thuhole-go-backend/commit/693db3fe2986807e34868ad317baa9360ea9a583 fixed