mysql
创建:2023-10-27 16:41
更新:2025-05-05 19:04

安装

docker run -d --restart=always \
    --log-opt max-size=10m \
    -m 1024MB \
    -p 3306:3306 \
    -v $(pwd)/data/mysql/conf:/etc/mysql/conf.d \
    -v $(pwd)/data/mysql/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=123456 \
    --name mysql \
    mysql:8
mysql -uroot -p

create user 'test'@'%' identified by '123456';
grant all privileges on *.* to 'test'@'%';  

B树和B+树区别

  • B树的所有节点既存放 键(key) 也存放 数据(data);而B+树只有叶子节点存放 key 和 data,其他内节点只存放key。
  • B树的叶子节点都是独立的;B+树的叶子节点有一条引用链指向与它相邻的叶子节点。
  • B树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而B+树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显。

索引类型

create index index_name on table_name (column_name);

alter table `table_name` add primary key ( `column` ); -- 添加primary key(主键索引)
alter table `table_name` add unique ( `column` ); -- 添加unique(唯一索引) 
alter table `table_name` add index index_name ( `column` ); -- 添加index(普通索引) 
alter table `table_name` add index index_name (column_name(length)); -- 添加index(前缀索引) 
alter table `table_name` add fulltext ( `column`);  -- 添加fulltext(全文索引) 
alter table `table_name` add index index_name ( `column1`, `column2`, `column3` ); -- 添加多列索引
  1. 主键索引
  2. 唯一索引(Unique Key) :唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为NULL,一张表允许创建多个唯一索引。建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
  3. 普通索引(Index) :普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和NULL。
  4. 前缀索引(Prefix) :前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,
    因为只取前几个字符。
  5. 全文索引(Full Text) :全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6之前只有MYISAM引擎支持全文索引,5.6之后InnoDB也支持了全文索引。
  6. 联合索引/多列索引

联合索引的最左前缀原则:

MySQL中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如User表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下:

sql select * from user where name=xx and city=xx; --可以命中索引 select * from user where name=xx; --可以命中索引 select * from user where city=xx; --无法命中索引
这里需要注意的是,查询的时候如果两个条件都用上了,但是顺序不同,如 city= xx and name =xx,那么现在的查询引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。

由于最左前缀原则,在创建联合索引时,索引字段的顺序需要考虑字段值去重之后的个数,较多的放前面。ORDER BY子句也遵循此规则。

其他问题

  1. 关系型数据库和非关系型数据库的理解

    1. 关系型数据库强调字段与字段,表与表之间的关系,可以联表操作。关系型数据库一般都支持事务、存储过程等
    2. 非关系型数据库需要应用层维护关系,联表查询和事务的支持弱或者不支持
    3. 常见的关系型数据库有:mysql, pgsql, oracle, sql server, sqlite等,非关系型数据库有 redis、mongo等
  2. mysql的数据类型

    1. 数值: int, bigint, tinyint, smallint, mediumint, float, double, decimal(定点型)
    2. 字符串: char, varchar, text, longtext, blob, longblob等
      char是定长字符串,varchar是变长字符串
    3. 时间:year, time, date, datetime, timestamp等
      • date只存储年月日,time只存储时分秒,datetime存储年月日时分秒. 都是按照字符串进行存储的
      • datetime没有时区,timestamp是时间戳;
        • datetime:1000-01-01 00:00:00 ~ 9999-12-31 23:59:59;
        • timestamp:1970-01-01 00:00:01 ~ 2037-12-31 23:59:59
  3. null和''的区别

    1. ''的长度是 0,是不占用空间的,而null 是需要占用空间的。
    2. null 代表一个不确定的值,就算是两个 null,它俩也不一定相等。例如,select null=null的结果为 false,但是在使用distinct,group by,order by时,null又被认为是相等的。
    3. null 会影响聚合函数的结果。例如,sum、avg、min、max 等聚合函数会忽略 null 值。 count 的处理方式取决于参数的类型。如果参数是 (count()),则会统计所有的记录数,包括 null 值;如果参数是某个字段名(count(列名)),则会忽略 null 值,只统计非空值的个数。
    4. 查询 null 值时,必须使用 is null 或 is not null 来判断,而不能使用 =、!=、 <、> 之类的比较运算符。而''是可以使用这些比较运算符的。

    因此:my_sql 不建议使用 null 作为列默认值

  4. boolean类型如何表示

    my_sql 中没有专门的布尔类型。用int代替

  5. 常用sql语句

    select database();
    select now(), user(), version();
    
    create database [if not exists] 数据库名 [character set charset_name | collate collation_name]
    show databases [like 'pattern']
    show create database 数据库名
    alter database 库名 选项信息
    drop database[if exists] 数据库名
    
    create table [if not exists] [库名.]表名 (列名 列类型, ....) [表选项]
    show tables from  库名
    drop table[ if exists] 表名 ...
    truncate [table] 表名  
    
    insert [into] 表名 [(字段列表)] values (值列表)[, (值列表), ...]
    select 字段列表 from 表名[ 其他子句]
    delete from 表名[ 删除条件子句]
    update 表名 set 字段名=新值[, 字段名=新值] [更新条件]
    
  6. 数据库经常使用的函数

    count(*/column):返回行数
    sum(column): 返回指定列中唯一值的和
    max(column):返回指定列或表达式中的数值最大值
    min(column):返回指定列或表达式中的数值最小值
    avg(column):返回指定列或表达式中的数值平均值
    date(Expression): 返回指定表达式代表的日期值
    
  7. my_sql 支持哪些存储引擎?默认使用哪个?

    1. 可以通过 show engines 命令来查看
    2. 5.5之后默认 innodb, 常用的有 innodb 和 my_isam
    3. my_sql 存储引擎采用的是 插件式架构 ,支持多种存储引擎,甚至可以为不同的数据库表设置不同的存储引擎以适应不同场景的需要。存储引擎是基于表的,而不是数据库。
    4. 可以根据 my_sql 定义的存储引擎实现标准接口来编写一个属于自己的存储引擎
  8. myisam 和 innodb

    1. myisam 不支持行级锁, 只有表级锁. innodb 支持行级锁和表级锁,默认为行级锁。
    2. myisam 不支持事务. innodb 提供事务支持,实现了 sql 标准定义了四个隔离级别,具有提交(commit)和回滚(rollback)事务的能力。并且,inno_db 默认使用的 repeatable-read(可重读)隔离级别是可以解决幻读问题发生的(基于 mvcc 和 next-key lock)。
    3. myisam 不支持外键,而 innodb 支持。
    4. myisam 不支持数据库异常崩溃后的安全恢复,innodb 支持。使用 inno_db 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 redo log 。
    5. myisam 不支持 mvcc, innodb 支持。
    6. 索引实现不一样。myisam 引擎和 innodb 引擎都是使用 b+tree 作为索引结构。innodb 引擎中,其数据文件本身就是索引文件。相比 myisam,索引文件和数据文件是分离的,其表数据文件本身就是按 b+tree 组织的一个索引结构,树的叶节点 data 域保存了完整的数据记录。
    7. my_isam 更适合读取密集的场景
    8. myisam 支持全文索引,innodb不支持
    9. myisam 不自持hash索引,innodb支持
  9. my_sql 中常见的日志有哪些?

    • 错误日志(error log)
    • 查询日志(query log)
    • 中继日志(relay log)
    • 常规查询日志(general query log)
    • 慢查询日志(slow query log)
      是 mysql 中用于记录查询执行时间超过指定阈值的 sql 语句的日志。这个阈值可以通过 longquery_time 参数进行设置。慢查询日志的主要用途是帮助数据库管理员找出执行效率低下的 sql 语句,以便进行优化。
    • 二进制日志(binary log 或 binlog):
      主要记录了所有改变数据库数据的 sql 语句,包括 ddl(如 create table、alter table)和 dml(如 insert、update、delete)操作。binlog 主要用于 my_sql 的主从复制和数据恢复。
    • 事务日志(redo/undo log)
      redo log 是 innodb 存储引擎特有的日志,它记录了对数据库进行的所有修改操作,但并不记录具体的 sql 语句。redo log 是循环写的,当达到一定大小后会从头开始写。当 mysql 发生异常重启时,innodb 存储引擎可以通过 redo log 恢复数据,从而保证事务的持久性。 undo log 也是 innodb 存储引擎特有的日志,它记录了数据的旧版本信息。当一个事务需要回滚时,inno_db 可以通过 undo log 恢复数据的旧版本,从而保证事务的原子性。此外,undo log 还用于实现多版本并发控制(mvcc),即在读取数据时使用 undo log 来获取数据的快照,以便提供一致性读。

    binlog 与 redo log 的区别:binlog 是 mysql 的服务器层实现的,所有的存储引擎都可以使用,它记录的是 sql 语句;而 redo log 是 innodb 存储引擎特有的,它记录的是对数据页的物理修改操作。另外,binlog 是追加写的,当文件达到一定大小后会生成新的文件;而 redo log 是循环写的,当文件达到一定大小后会从头开始写。

  10. 事务 ACID 特性

    1. 原子性(atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
    2. 一致性(consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
    3. 隔离性(isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
    4. 持久性(durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

    A、I、D 是手段,C 是目的

  11. MySQL 如何保证 ACID 的
    原子性(Atomicity):

    • 事务管理:MySQL 中,事务是确保原子性的关键。事务中的所有操作要么全部成功,要么全部失败。如果事务中的任何操作失败,那么整个事务都会回滚到事务开始之前的状态。
    • 回滚日志(Undo Log):MySQL 使用回滚日志来记录事务中每个操作的旧值。如果事务失败或者被回滚,MySQL 可以使用这些信息来将数据恢复到事务开始之前的状态。

    一致性(Consistency)

    • 约束检查:MySQL 强制执行数据的完整性约束,比如主键、外键、唯一性、检查约束等,以确保数据库的一致性。
    • 触发器和存储过程:触发器和存储过程可以定义复杂的业务规则,确保数据操作遵循这些规则,维护数据库状态的一致性。

    隔离性(Isolation)

    • 多版本并发控制(MVCC):在 InnoDB 存储引擎中,MVCC 通过保留数据在某一时刻的快照来实现,这样即使数据被其他事务修改,每个事务仍然可以看到数据的一致状态。
    • 锁:MySQL 提供了不同级别的锁,如行锁、表锁,以及更细粒度的锁定机制,用于控制并发事务对共享数据的访问,确保事务的隔离性。
    • 隔离级别:MySQL 支持不同的事务隔离级别,包括 READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。这些隔离级别提供了不同程度的隔离,以满足不同的并发需求。

    持久性(Durability)

    • 重做日志(Redo Log):MySQL 的 InnoDB 存储引擎使用重做日志来确保事务的持久性。即使在系统崩溃或电源故障后,重做日志也可以用来重演已经提交事务的修改,确保这些修改不会丢失。
    • 写入前日志(Write-Ahead Logging, WAL):重做日志被设计为先写日志,后写磁盘的方式,这样即使数据库发生故障,也能通过重做日志恢复到最后一次提交的状态。
  12. 并发事务带来哪些问题

    • 脏读
    • 丢失修改
    • 不可重复读
    • 幻读
  13. 不可重复读和幻读有什么区别?

    • 不可重复读的重点是内容修改或者记录减少比如多次读取一条记录发现其中某些记录的值被修改;
    • 幻读的重点在于记录新增比如多次执行同一条查询语句(dql)时,发现查到的记录增加了
  14. sql的事务隔离级别

    离级别 脏读 不可重复读 幻读
    read-uncommitted(读取未提交)
    read-committed(读取已提交) ×
    repeatable-read(可重复读) × ×
    serializable (可串行化) × × ×
    • read-uncommitted(读取未提交) :最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
    • read-committed(读取已提交) :允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
    • repeatable-read(可重复读) :对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
    • serializable(可串行化) :最高的隔离级别,完全服从 acid 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

    my_sql 的隔离级别基于锁和 mvcc 机制共同实现的。serializable 隔离级别是通过锁来实现的,read-committed 和 repeatable-read 隔离级别是基于 mvcc 实现的。不过, serializable 之外的其他隔离级别可能也需要用到锁机制,就比如 repeatable-read 在当前读情况下需要使用加锁读来保证不会出现幻读。

    mysql innodb 存储引擎的默认支持的隔离级别是 repeatable-read(可重读)。可以通过select @@tx_isolation;命令来查看

  15. MySQL数据的锁的种类,加锁的方式

    按照类型来分有乐观锁和悲观锁
    根据粒度来分有行级锁,页级锁,表级锁(粒度一个比一个大) (仅BDB,Berkeley Database支持页级锁)
    根据作用来分有共享锁(读锁)和排他锁(写锁)。

  16. 什么是共享锁和排他锁

    • 共享锁是读操作的时候创建的锁,一个事务对数据加上共享锁之后,其他事务只能对数据再加共享锁,不能进行写操作直到释放所有共享锁。
    • 排他锁是写操作时创建的锁,事务对数据加上排他锁之后其他任何事务都不能对数据加任何的锁(即其他事务不能再访问该数据)
  17. 乐观锁与悲观锁解释一下, 乐观锁与悲观锁是怎么实现的

    一般的数据库都会支持并发操作,在并发操作中为了避免数据冲突,所以需要对数据上锁,乐观锁和悲观锁就是两种不同的上锁方式。

    悲观锁假设数据在并发操作中一定会发生冲突,所以在数据开始读取的时候就把数据锁住。而乐观锁则假设数据一般情况下不会发生冲突,所以在数据提交更新的时候,才会检测数据是否有冲突。

    实现:

    悲观锁有行级锁和页级锁两种形式。行级锁对正在使用的单条数据进行锁定,事务完成后释放该行数据,而页级锁则对整张表进行锁定,事务正在对该表进行访问的时候不允许其他事务并行访问。

    悲观锁要求在整个过程中一直与数据库有一条连接,因为上一个事务完成后才能让下一个事务执行,这个过程是串行的。

    乐观锁有三种常用的实现形式:

    一种是在执行事务时把整个数据都拷贝到应用中,在数据更新提交的时候比较数据库中的数据与新数据,如果两个数据一摸一样则表示没有冲突可以直接提交,如果有冲突就要交给业务逻辑去解决。
    一种是使用版本戳来对数据进行标记,数据每发生一次修改,版本号就增加1。某条数据在提交的时候,如果数据库中的版本号与自己的一致,就说明数据没有发生修改,否则就认为是过期数据需要处理。
    最后一种采用时间戳对数据最后修改的时间进行标记。与上一种类似。

  18. my_sql 中并发事务的控制方式

    1. 锁 和 mvcc; 锁可以看作是悲观控制的模式,多版本并发控制(mvcc,multiversion concurrency control)可以看作是乐观控制的模式。
    2. 共享锁(s 锁):又称读锁, 排他锁(x 锁):又称写锁/独占锁
    3. mvcc 是多版本并发控制方法,即对一份数据会存储多个版本,通过事务的可见性来保证事务能看到自己应该看到的版本。通常会有一个全局的版本分配器来为每一行数据设置版本号,版本号是唯一的。 mvcc 在 my_sql 中实现所依赖的手段主要是: 隐藏字段、read view、undo log。undo log :
      • undo log 用于记录某行数据的多个版本的数据。
      • read view 和 隐藏字段 : 用来判断当前版本数据的可见性。
  19. inno_db 有哪几类行锁?

    • 记录锁(record lock):也被称为记录锁,属于单个行记录上的锁。
    • 间隙锁(gap lock):锁定一个范围,不包括记录本身。
    • 临键锁(next-key lock):record lock+gap lock,锁定一个范围,包含记录本身,主要目的是为了解决幻读问题(my_sql 事务部分提到过)。记录锁只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁。

    在 innodb 默认的隔离级别 repeatable-read 下,行锁默认使用的是 next-key lock。但是,如果操作的索引是唯一索引或主键,innodb 会对 next-key lock 进行优化,将其降级为 record lock,即仅锁住索引本身,而不是范围。

    innodb 的行锁是针对索引字段加的锁,表级锁是针对非索引字段加的锁。当执行 update、delete 语句时,如果 where条件中字段没有命中唯一索引或者索引失效的话,就会导致扫描全表对表中的所有行记录进行加锁。这个在日常工作开发中经常会遇到,一定要多多注意!!!不过,很多时候即使用了索引也有可能会走全表扫描,这是因为 mysql 优化器的原因。

  20. 事务回滚有什么实现机制?除了日志之外呢?

  21. mysql性能优化

    1. 不要外键
    2. 查询更多的建索引,写入多的尽可能不要建立索引了
    3. 尽可能少join, join前确保数据过滤后数据量小
    4. 尽可能过滤数据,在小范围数据执行操作类函数,例如计算,count, like等
    5. where中尽可能少使用计算或者转换类函数,可以改成比较函数
    6. 对于事务性不强的,可以关闭事务,使用批量更新等
    7. 分表分库

    高频访问:

    • 分表分库:将数据库表进行水平拆分,减少表的长度
    • 增加缓存: 在web和DB之间加上一层缓存层
    • 增加数据库的索引:在合适的字段加上索引,解决高频访问的问题

    并发优化:

    • 主从读写分离:只在主服务器上写,从服务器上读
    • 负载均衡集群:通过集群或者分布式的方式解决并发压力
  22. mysql索引类型

    1. 主键索引

    2. 唯一索引(unique key) :唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为null,一张表允许创建多个唯一索引。建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。

    3. 普通索引(index) :普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和null。

    4. 前缀索引(prefix) :前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,
      因为只取前几个字符。

    5. 全文索引(full text) :全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。mysql5.6之前只有myisam引擎支持全文索引,5.6之后inno_db也支持了全文索引。

    6. 联合索引/多列索引

      联合索引的最左前缀原则:
      my_sql中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如user表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下:

      select * from user where name=xx and city=xx ; //可以命中索引
      select * from user where name=xx ; // 可以命中索引
      select * from user where city=xx ; // 无法命中索引     
      
         
      

      这里需要注意的是,查询的时候如果两个条件都用上了,但是顺序不同,如 city= xx and name =xx,那么现在的查询引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。

      由于最左前缀原则,在创建联合索引时,索引字段的顺序需要考虑字段值去重之后的个数,较多的放前面。order by子句也遵循此规则。

      联合索引中间可以有 null 值吗,为什么

  23. mysql索引如何实现

    MySQL中的索引主要是通过B-Tree(平衡多路查找树)和Hash(哈希)两种数据结构来实现的。其中,B-Tree是MySQL中最常用的索引类型,它被用于MyISAM、InnoDB、Memory等存储引擎。

    B-Tree索引:B-Tree索引可以处理等于、不等于、大于、小于、范围查询、LIKE 'abc%'等各种类型的查询。在B-Tree中,所有的值都存储在树的叶子节点上,非叶子节点不存储数据,只存储键值和指向子节点的指针。这样做的好处是每次查找的次数都相同,所以查找效率稳定。

    Hash索引:Hash索引基于哈希表实现,只有Memory存储引擎显式支持。它能以O(1)的时间复杂度进行查找,但是这种超高效的查找速度是以牺牲其他功能为代价的。Hash索引仅支持等值查询,不支持范围查询和排序操作,也无法利用索引完成部分匹配查找。同时,Hash索引在处理大量数据时可能会出现哈希冲突的问题,且Hash索引无法避免表扫描。

  24. B树和B+树的区别是什么?B+ 树的特点,原理?

    B树(Balance Tree)和B+树(Balance Plus Tree)都是一种自平衡的多路搜索树,主要用于大量数据的存储系统中,如数据库和文件系统。它们都可以保持数据的有序性,并且可以在对数时间内完成查找、插入和删除操作。然而,它们之间还是存在一些重要的差别的。

    1. B树的所有节点都包含键和值,即所有节点都可以是叶子节点,也都可以是内部节点。而B+树的内部节点只存储键,不存储值,只有叶子节点存储键和值。这意味着,在B+树中,所有的数据都存储在叶子节点上。

    2. B+树的叶子节点之间通过指针相连,形成了一个链表结构,这使得范围查询更加高效。而B树并没有这样的链表结构,范围查询需要通过深度优先搜索来完成。

    3. 由于B+树的内部节点不存储数据,所以每个内部节点可以存储更多的键,因此B+树的树高通常比B树要低,这使得在大数据量的情况下,B+树的查询效率更高。

    B+树的特点主要包括:

    1. 所有关键字都出现在叶子节点的链表中(稠密索引),且链表中的关键字恰好是有序的,不仅可以快速查询,也方便范围查找。而B树则做不到,只有分支节点才包含所有关键字,叶子节点并不包含所有关键字。

    2. 非叶子节点的子树指针与关键字个数相同。非叶子节点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(注意最后一个子树指针P[m],指向关键字值大于等于K[m]的子树)。

    3. 非叶子节点的关键字K[i],是其子树指针P[i+1]指向的子树中所有关键字的最小值。也就是说,非叶子节点中的关键字是分割左右子树的。

    原理:B+树的查找过程是这样的,首先从根节点开始,通过二分查找的方式找到关键字K[i],使得K[i] <= key < K[i+1],然后沿着指针P[i+1]继续在下一层节点查找,直到查找到叶子节点。在叶子节点上按照从小到大的顺序查找到相应的关键字,如果找到了就返回该关键字及其对应的记录,否则就返回“查找失败”。

  25. sql中索引失效的场景

    联合索引不满足最左匹配原则,索引列上有计算或者函数,字段类型不同,比如varchar类型的字段与数字比较就不走索引,但是与字符串比较就走索引,模糊匹配,如果%在最左

  26. 主从同步如何实现

    binlog。

    复制过程中可能会遇到的问题包括网络延迟、主从数据不一致等。因此,在部署和监控MySQL主从复制时,需要考虑故障恢复、数据一致性校验以及延迟监控等因素。

  27. MySQL的存储结构

    表空间,段(包括数据段:即B+树的叶子结点,索引段:非叶子节点,回滚段),区(默认1M,64个连续页),页(InnoDB存储引擎磁盘管理的最小单元,默认16k),行

  28. 数据库的范式

    1. 第一范式(确保每列保持原子性)

      第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
      比如 学生 选课(包括很多课程) 就不符合第一范式

    2. 第二范式(确保表中的每列都和主键相关)

      在满足第一范式的前提下,(主要针对联合主键而言)第二范式需要确保数据库表中的每一列都和主键的所有成员直接相关,由整个主键才能唯一确定,而不能只与主键的某一部分相关或者不相关。
      比如一张学生信息表,由主键(学号)可以唯一确定一个学生的姓名,班级,年龄等信息。但是主键 (学号,班级) 与列 姓名,班主任,教室 就不符合第二范式,因为班主任跟部分主键(班级)是依赖关系

    3. 第三范式(确保非主键的列没有传递依赖)

    在满足第二范式的前提下,第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。非主键的列不能确定其他列,列与列之间不能出现传递依赖。
    比如一张学生信息表,主键是(学号)列包括 姓名,班级,班主任 就不符合第三范式,因为非主键的列中 班主任 依赖于 班级

    1. BCNF范式(确保主键之间没有传递依赖)

    主键有可能是由多个属性组合成的复合主键,那么多个主键之间不能有传递依赖。也就是复合主键之间谁也不能决定谁,相互之间没有关系。