xiaohanliang
Database
Database
  • review
  • MySQL
    • 0. 索引就是树吗
    • 1. 索引是怎么发挥作用的
    • 2. 聊聊怎么估时间
    • 3. 主键玄学
    • 4. 事务的执行过程@ACD
    • 5. MVCC就是用undolog回退
    • 6. 事务如何彼此隔离@I
    • 7. 如何人为的制造死锁
    • 8. 引擎是干什么的
    • 9. 主从复制怎么做到的
    • 10. 寻找同步起始点GTID
    • 11. 预解析Statement
  • Redis
    • 0. Hash@数据结构
    • 1. ZSet@数据结构
    • 2. 场景与玩法@数据结构
    • 3. 可能的风险点
    • 4. Redis的落盘
    • 5. 关于效率的讨论
    • 6. 主从模式@集群化
    • 7. [WIP]Proxy实现@集群化
    • 8. 标准玩法@集群化
  • KV/Distributed
    • 0. 面临的问题
    • 1.Raft@原理
    • 2. LSM@原理
    • 3. [WIP]分布式事务@原理
Powered by GitBook
On this page
  • Introduction
  • 内存? 那我重启
  • 说到主键...
  • 与唯一键的区别
  • 为什么不使用复杂/复合主键
  • 主键为什么是无意义的

Was this helpful?

  1. MySQL

3. 主键玄学

Introduction

关于主键, 常见的问题包含

  1. 什么是主键, 什么是唯一键

  2. 什么是自增键, 自增键是怎么做到的

  3. 为什么自增主键可以是不连续的

  4. 主键跟唯一键之间什么关系

  5. 可以用符合主键吗? 为什么不推荐使用复合主键

  6. 为什么建议使用无意义的字段作为主键

  7. snowflake的存在意义是什么

我们常用auto_increment来表示一个自增主键, 每次使用就加一, 按理说没什么问题, 用多就会发现有坑, 这东西可能会遭遇写入失败的问题, 原因竟然能是主键重复

auto_increment的实现原理是在内存里维护一个值, 每次使用就加一下, 而常规的insert操作是不会对这个值加锁的, 并发写入就有可能导致主键重复.

好, 那我们不搞常规, 用事务来写入, 这种情况下的确会上锁, 假设现在两个事务, 按照自增主键一个id=10, 一个id=11, 现在第一个事务回滚了, 而第二个id=11却得以保留, 这直接会导致自增主键不连续. 除此之外, 删除也会搞的主键不连续.

内存? 那我重启

这个值既然是维护在内存里面, 那重启的时候怎么恢复这个值? 在很久以前, 我们通过select max(id)的方式来恢复这个值, 但是这种方法有点危险.

假设现在插入一条id=10, 然后在另一个表里插入一个外键where id=10, 然后我们只删主表里的id=10, 另一个表里的不管, 然后重启. 下次重启的时候我们通过select max(id)得出下一条插入的id应该等于10. 想想这种情况, 那么这条记录一插入就能立刻得到另一个表里有where id=10关联着. 这是非常严重的错误.

说到主键...

与唯一键的区别

唯一键本身并不是键哈, 正确叫法是"唯一索引", 索引跟键差别就挺大的了

  • 主键是key, 唯一索引是index, 键的本质是一种约束, 而索引只是一个方便你查询的冗余数据结构

  • 主键不能为空, 而唯一索引可以为空

  • 每个主键都会生成出一个唯一索引

为什么不使用复杂/复合主键

理论上主键是可以复合的, 但不建议这样做, 我们上面说了主键会生成(聚簇)索引, 按照主键值会进行叶节点排序, 你搞复杂的排序不方便

主键为什么是无意义的

无意义的唯一目的就是为了保证唯一, 换句话说主键不应该跟任何业务含义有挂钩, 因为任何有意义的字段都有潜在的冲突风险

我们举个例子, 18位的身份证号, 除去地区/生日/checksum以外只有3位表示性别+编号. 这意味着同一天, 同一个地区里, 男性新生儿只能有500个, 女性新生儿500个, 你想想海淀有多大, 500个应该还是挺容易突破的吧. 这就是id不应该跟业务产生挂钩的原因

另一个例子是snowflake, snowflake会产生64位的数字id, 其中包含有 毫秒时间戳 + 机房编号 + 机器编号, 最后只有12位表示序号, 这意味着同一个机房的同一个机器, 一毫秒内最多生产2^12次方个id

Previous2. 聊聊怎么估时间Next4. 事务的执行过程@ACD

Last updated 4 years ago

Was this helpful?