MySQL 基础

什么是事务?

事务就是满足 ACID 特性的一组操作,可以用 commit 提交一个事务,也可以用 rollback 回滚事务。

MySQL 基础_第1张图片

AUTOCOMMIT

MySQL 默认 自动提交模式。也就是说,如果不显式使用 START TRANSACTION 语句来开始一个事务,那么每个查询都会被当做一个事务自动提交

存储引擎

MySQL 支持多种存储引擎,甚至你可以自己写一个专属的存储引擎,可以看一下 MySQL 的多存储引擎架构

MySQL 基础_第2张图片

简介

MySQL 中的数据用各种不同的技术存储在文件或内存中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁实现并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能。存储引擎其实就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。
如何选择引擎?

MySQL 5.5 以前的默认存储引擎是 MyISAM, 5.5 之后换成了 Innodb。

MyISAM

特性

  • 并发性和锁级别(只有表锁,读锁和写锁互斥)
  • 表损坏修复
  • 支持全文索引
  • 支持表压缩

应用场景

  • 没有事务
  • 只读类应用(读多写少)
  • 空间类应用(唯一支持空间类函数的引擎)
  • 做很多 count 的计算(MyISAM 会保存表的行数,不需要扫描,Innodb 没有保存,需要扫描)

Innodb

特性

  • 支持事务
  • 完全支持事务的 ACID 特性
  • Redo log (实现事务的持久性) 和 Undo log (实现事务的原子性,存储未完成事务 log, 用于回滚)
  • 支持行锁(通过间隙锁(GAP)在 RR 级别解决了幻读的问题)
  • 锁粒度是支持 mvcc(多版本并发控制) 的行级锁

应用场景

  • 可靠性要求比较高,或者要求事务
  • 表的更新和查询都很频繁,并且行锁定的机会比较大

问:如何选择存储引擎

  • 是否需要事务

    • Innodb 支持事务,MyISAM 不支持事务
  • 可靠性要求

    • Innodb 支持完全的 ACID 特性,支持崩溃恢复,而 MyISAM
  • 应用场景

    • 频繁读取,不频繁插入和更新的场景建议使用 MyISAM
    • 读写都频繁,要求事务选择 Innodb
  • 存储引擎的特性

别的引擎

MySQL 中的引擎只是一个插件,如果技术好且有需要,甚至自己写一个引擎来使用也是可以的。在这里列举一些别的引擎,特性就不去看了,以后如果有机会用到再写

CSV

Archive

Memory

Merge

MaxDB

MySQL 中的数据类型

1、整数

整数包括了 TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT;
占用内存空间的情况

TINYINT SMALLINT MEDIUMINT INT BIGINT
1 byte 2byte 3 byte 4 byte 8 byte

INT(1)、INT(10) 中的数字只是规定显示字符的个数,但是对于存储和计算是没有影响的。

2、浮点数

浮点数包括 FLOAT 和 DOUBLE,还有一个 DECIMAL,是高精度小数类型,可以存比 BIGINT 还大的整数,因为 DECIMAL 是用字符串来保存的。。。。

还有关于单精度和双精度也记录一下
类型 符号位 指数位 小数位
单精度 1 位 8 位 23 位
双精度 1 位 11 位 52 位

3、字符串

字符串包括 char 和 varchar,区别在于 char 是定长的,而 varchar 是变长的,varchar 会根据实际需要的大小来进行存储,但是会额外占用一个字节(长度超过 255 时会占用两个字节)。
VARCHAR 会保留字符串末尾的空格,而 CHAR 会删除。

4、时间和日期

datetime 和 timestamp
datetime 与时区无关,而 timestamp 与时区有关

索引

基于Innodb引擎

MySQL 中选择索引是优化器的工作,如果有多个索引都可以查到数据,优化器会估算使用每个索引的成本然后进行选择。

如何创建索引?

创建索引有 3 种方式

  1. 直接创建

    create index indexName on tableName(columnName(lenth));
  2. 在建表的时候创建索引

    create table tableName (
        id int not null,
        columnName varchar(16) not null,
        key indexName (columnName),
    );
  3. 修改表结构

     alter table tableName add index indexName(columnName);

这里还遇到个小问题,之前一直没有注意过,原来 MySQL 中有 key 和 index 两个关键字,但是他们其实是一样的,在官方有介绍:

KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY can also be specified as just KEY when given in a column definition. This was implemented for compatibility with other database systems.

索引的分类

唯一索引

唯一索引是指索引列没有重复的索引,包括了主键索引和其它索引。

主键索引

主键索引也可以称作聚簇索引,我们都知道,Innodb 底层是用 B+ 树实现的,在叶子节点存储的是数据,并且每一条数据肯定都有对应的键。如果在建表的时候没有指定主键索引,MySQL 会自动生成一个自增的主键。用一张图来展示一下数据在主键中的存储情况。

其它

泛指定义为唯一索引但是又不是主键索引的索引

创建唯一索引的方式和上面类似,只不过需要多一个 unique 关键字,而且 Innodb 引擎允许唯一索引值为 null。

初始化表


mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0, 
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;

insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

MySQL 基础_第3张图片

图片来自 极客时间专栏,丁奇老师的《MySQL45讲》真的很赞。

如果在上面的表中执行这条语句 select * from T where k between 3 and 5 执行流程是怎样的呢?

  1. 用 k 索引树找到 k = 3,得到主键索引 ID = 300
  2. 将 ID = 300 带回 ID 索引树查到 R3.
  3. 再从 k 索引树找到 K = 5, 对应的 ID = 500
  4. 回到 ID 索引树查到 ID = 500 的 R4
  5. 回到 k 索引树找下一个 k = 6,不满足条件,结束查询
  • 统计:查 k 索引树三次,ID 索引树 2 次,其中从 k 索引树取到主键的值,再回到主键索引树查询的过程称之为回表。

普通索引

普通索引没有索引列必须唯一的限制。

区别

在查询的时候,唯一索引和普通索引还是有点区别的。如果使用的是普通索引,那么查询语句会在找到第一个不满足条件的时候结束查询,而唯一索引只要找到一个满足条件就会结束查询。不过在查询方面,唯一索引和普通索引的消耗是差不多的,因为在 MySQL 中数据是按页存储的,一次读入一整页,一页可以存上千条 key,但是再更新的时候,两者就有区别了。

覆盖索引

文章开头创建的索引都是只有一列的,也叫单列索引,而覆盖索引也叫多列索引。借用丁奇老师的例子,对一个城市中的市民建立索引,如果用名字来做索引肯定不行,重名的人很多,还需要其他的判断条件来进行筛选。既然如此,可以选择用身份证号码来做索引,但是这也会有一个问题,如果我要查询的是姓名,但是索引里只有身份证号,这个时候就需要回表去主键索引上查找,多了一次查询。为了解决这个问题,就可以用姓名和身份证号建立联合索引,减少一个回表的消耗。


CREATE TABLE `tuser` (
  `id` int(11) NOT NULL,
  `id_card` varchar(32) DEFAULT NULL,
  `name` varchar(32) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `ismale` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `id_card` (`id_card`),
  KEY `name_age` (`name`,`age`)    //覆盖索引必须保证索引列没有重复
) ENGINE=InnoDB

最左前缀原则

要知道,索引在存储的时候是有序的,对于多列索引而言,先保证第一列有序,然后在此基础上第二列有序,以此类推。因此在使用多列索引的时候,会先对第一列索引字段进行匹配,然后再匹配第二列。

公众号:没有梦想的阿巧 后台回复 "群聊",一起学习,一起进步

你可能感兴趣的:(golang)