dduo518 / hexo-blog

hexo静态blog点击 https://github.com/chong0808/hexo-blog/issues
3 stars 0 forks source link

MySQL中的自增id #61

Open dduo518 opened 2 years ago

dduo518 commented 2 years ago

问题: 由于定义model的时候,model的基类插入的钩子函数会对id进行重新改写,如果在子类没有对id进行重新声明为自增类型的时候,父类中的插入钩子函数中会将id默认生成一个uuid类型的字符串进行赋值(对属性进行任意类型的赋值,弱类型语言可真难)。 如何对数据进行重新整理 有2种方案:

  1. 利用中间表
  2. 对id重新排序,且重置自增起始值 对自增id进行重新排序
    set @max_id = (select max(id) from table_name);
    select @max_id;
    UPDATE table_name set id = (@id := @id+1) order by created_at;
    UPDATE table_name set id = id - @max_id;

重置自增起始值 对于MySQL中id起始值。InnoDB 引擎的自增值,其实是保存在了内存里,并且到了 MySQL 8.0 版本后,才有了“自增值持久化”的能力,也就是才实现了“如果发生重启,表的自增值可以恢复为 MySQL 重启前的值”,具体情况是:在 MySQL 5.7 及之前的版本,自增值保存在内存里,并没有持久化。每次重启后,第一次打开表的时候,都会去找自增值的最大值 max(id),然后将 max(id)+1 作为这个表当前的自增值。 举例来说,如果一个表当前数据行里最大的 id 是 10,AUTO_INCREMENT=11。这时候,我们删除 id=10 的行,AUTO_INCREMENT 还是 11。但如果马上重启实例,重启后这个表的 AUTO_INCREMENT 就会变成 10。 也就是说,MySQL 重启可能会修改一个表的 AUTO_INCREMENT 的值。 在 MySQL 8.0 版本,将自增值的变更记录在了 redo log 中,重启的时候依靠 redo log 恢复重启之前的值。 所以对于MySQL 8.0以下的版本,重置有俩种方式

  1. 重启MySQL服务
  2. 利用DDL进行重置
    select @max_id:=max(id) from table_name;
    ALTER TABLE table_name AUTO_INCREMENT=@max_id;

    如果用强类型语言Golang的话应该这样设计更合理,在钩子函数中,将属性id默认为int类型且自增,将属性uuid默认为字符串类型,然后在插入的时候生成一个去掉'-'的uuid。