主键 id 用自增和 uuid 有什么区别?
● uuid 有 16 个字节,比 int(4 byte)和 bigint(8 byte)占用更多存储空间
有大量数据的时候 uuid 主键不会像自增主键那样越界,如果使用自增 id,字段类型一般选择 bigint
● 如果 InnoDB 表的数据写入顺序能和 B + 树索引的叶子节点顺序一致的话,这时候存取效率是最高的,uuid 由于无序性,插入和查询比自增主键差
● uuid 做主键相对安全,不能简单的从 uuid 获取信息,但是如果自增,则容易暴露信息,如果一个客户 id 是 123456,很容易猜到有客户 id 是 123456
● uuid 保证数据在表和库都是独立的,有利于处理分布式存储的数据表
uuid 主要解决的是分布式生成唯一编号的问题,但是不一定非要用现有的 uuid 方法,可以把每个机器都编个号,这样机器号加自增 id 也是一种 uuid
主键自增 id 衍生问题
Ⅰ、初始 3 条数据,最大 id 是 3
Ⅱ、delete 第 3 条数据
Ⅲ、insert 一条数据
我们可以看到主键 id 不连续,MySQL innodb 表的自增变量的值是内存中的临时值
● 删除命令:
针对整张表数据(保留表结构)的删除,可以使用 DELETE 或者 TRUNCATE,二者的区别如下:
① TRUNCATE 在各种表上无论是大的还是小的都非常快。如果有 ROLLBACK 命令 DELETE 将被撤销,而 TRUNCATE 则不会被撤销
② TRUNCATE不能进行回滚操作,DELETE 语句执行删除的过程是每次从表中删除一行,并且同时将该行的的删除操作作为事务记录在日志中保存以便进行进行回滚操作
③ 当表被 TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小,而 delete 操作不会减少表或索引所占用的空间
④ 不能 TRUNCATE 一个带有外键的表,如果要删除首先要取消外键,然后再删除
⑤ TRUNCATE 全表后,主键自增 id 会重新从 1 开始,而 delete 全表后自增 id 不从 1 开始
● 面试题 Ⅰ
如果 DELETE 第 3 行数据后,MySql 服务挂了,手动重启 MySql 服务,请问在 InnoDB 和 MyISAM 存储引擎中,新增一条数据,自增 id 的值是 3 还是 4?
MyISAM 引擎:MyISAM 表会把自增主键的最大 ID 记录到数据文件里,重启 MySQL 自增主键的最大 ID 也不会丢失。
InnoDB 引擎:InnoDB 表把自增主键的最大 ID 记录到内存中,重启数据库后,都会导致最大自增 ID 重置。当我们执行 insert 操作的时候,MySQL 会默认获取到自增长的最大值,类似于使用
SELECT MAX(id) FROM student FOR UPDATE; 然后再 + 1
所以说正确答案选 C
注意:在 MySql 8.0 版本中新增特性,「 自增主键持久化 」
将自增主键的计数器持久化到 redo log 中。每次计数器发生改变,都会将其写入到 redo log 中。如果数据库发生重启,InnoDB 会根据 redo log 中的计数器信息来初始化其内存值。为了尽量减小对系统性能的影响,计数器写入到 redo log 中,并不会马上刷新。
● 面试题 Ⅱ
主键 id 不连续的解决办法(假设主键 id 与其他表无关联)
① 去掉 id 主键自增
② 增加一列 idd 作为主键,设置为自动递增
③ 让 id 列从 1 开始自增
④ 删除idd
⑤ 将 id 重新设置为主键,加上自动递增
>>>Python 之 MySql“未解之谜”10--我以为我很懂MySql索引(下)