mysql索引、事务、存储引擎

目录

一、索引:

1、索引的作用:

2、索引的缺点

3、创建表的时候需要考虑的因素:

4、如何创建索引:

5、索引的类型:

6、索引的使用

6.1、普通索引

6.2、唯一索引:和unique相关

6.3、主键索引:

6.4全文索引:

6.5、联合索引:指定一个索引名,一个索引名对应多个列名

二、MySQL的事务:

1、事务的特点:ACID

2、MySQL支持的隔离级别(4种):

3、事务并发导致的问题:

4、事务的隔离级别:

5、事务隔离的作用范围:

6、以上情况如何避免:脏读、幻读、不可重复读、丢失更新

7、事务的控制语句:

三、存储引擎

1、存储引擎的功能:

2、MySQL的存储引擎分类:

3、MYISAM和INNODB分析和对比:

3.1、MYISAM:

3.2、INNODB:

4、语句:

4.1、查看支持的存储引擎:

4.2、查看表使用的存储引擎:

4.3、改存储引擎:

5、INNODB的行锁和索引的关系,以及表锁 排他锁 死锁

6、如何尽可能的避免死锁:


一、索引:

是一个排序的列表,列表中存储的是索引的值和包含这个值的数据所在行的物理地址。

1、索引的作用:

加快查询速度

  1. 利用索引数据库可以快速定位,大大加快查询速度
  2. 标的数据很多,查询需要关联多个表,这个时候索引也可以提高查询速度
  3. 加快表与表之间的连接速度
  4. 使用分组和排序时,可以大大减少时间
  5. 可以提高数据库恢复数据时的速度

2、索引的缺点

·会额外占用磁盘空间;

·更新包含索引的表会花费更多时间,效率会更慢。

mysql索引、事务、存储引擎_第1张图片

3、创建表的时候需要考虑的因素:
  1. 关联程度(最多三张),选好关联字段
  2. 每个字段的长度,也要考虑
  3. 设计合理的索引列
  4. 表数据,要控制在合理的范围之内。可以在牺牲一定性能的条件下满足需求。5秒以上就要考虑优化了,10秒以上一般是出问题了(前端缓存失效,缓存击穿。缓存雪崩。)

4、如何创建索引:

索引创建的原则:

如果有索引,数据库会进行索引查询,然后定位数据,索引如果使用不当,反而会增加数据库的负担。

正确创建:

·主键外键必须要有索引(创建好主键和外键自动就是索引,不需要额外声明了)

·如果一个表超过300行的记录,必须要有索引,否则数据库会遍历表的所有数据。

·互相之间有关联得表,在这个关联字段应该设置索引

·唯一性太差的字段,不适合创建索引

·更新太频繁的字段,不适合做索引

·经常被where条件匹配的字段,尤其是表数据比较多的,应该创建索引

·经常进行group by(分组) order by(排序)的字段要建立索引

·索引的列的字段越小越好,长文本的字段不适合建立索引

5、索引的类型:

查看表的索引:

show index from 表名;

B-树索引 BTREE:默认就是Btree

树型结构的索引,也是大部分数据库的默认索引类型

根节点:输的最顶端的分支节点

分支节点:指向索引里其他的分支节点,也可以是叶子节点

叶子结点:直接指向表里的数据行

mysql的默认引擎:INNODB默认的索引类型就是Btree

mysql索引、事务、存储引擎_第2张图片

哈希hash索引:散列索引 把任意长度的输入,通过散列算法变换成固定长度的输出。新成散列值——分别对应数据里的列和行

MEMORY引擎可以支持hash,也是他的默认索引

先算散列值,然后再对应,速度比较慢,比Btree慢

hash的索引匹配:= in () <=>

hash索引排序时,索引是无效的

将默认的Btree改成hash索引:

alter table 表名 engine=memory;

将表的引擎改为memory,索引就变成hash了

6、索引的使用

查看表的索引信息

show index from 表名;

查看表的结构信息(包含索引名和外键名)

show create table 表名;

练习:

1、创建用户,声明网段 test 网段任选  123456

create user 'test'@'20.0.0.0/24' identified by '123456';

2、创建一个库,库名:test1

create database test1;

3、在库中创建两个表

table1

ID 主键

name 不能为空

sex  不能为空

table2

id  主键

address 可以为空,默认地址不详

phone 可以为空不能重复

mysql索引、事务、存储引擎_第3张图片

test 可以对test1的库进行 select INSERT

mysql索引、事务、存储引擎_第4张图片

把 test的用户名改成 test_123

rename user 'test'@'20.0.0.0/24' to 'test_123'@'20.0.0.0/24';

把密码修改 abc123

mysql索引、事务、存储引擎_第5张图片

删除权限:INSERT

mysql索引、事务、存储引擎_第6张图片

table1的索引是hash类型,sex列做索引

mysql索引、事务、存储引擎_第7张图片mysql索引、事务、存储引擎_第8张图片

table2的索引是btree, phone做索引

mysql索引、事务、存储引擎_第9张图片

6.1、创建索引:

普通索引、唯一索引、主键索引、全文索引、联合索引

查看索引信息

show index from 表名;

查看索引类型

show create table 表名;

能在建表时创建好的条件,尽量在创建把条件约束好。不要创完之后再添加

最好不要事后添加


6.1、普通索引

表中直接创建索引:

create table member (

id int(4) PRIMARY KEY,

name varchar(10),

card_id int(18),

phone int(11),

index name_index (name)

);

index name_index (name)

name_index:自定义索引名

(name):索引对象

mysql索引、事务、存储引擎_第10张图片

show index from member;

查看索引

通过命令添加索引:

alter table test add index name_index(name);

mysql索引、事务、存储引擎_第11张图片

6.2、唯一索引:和unique相关

与普通索引类似,唯一索引的每个值都是为1,唯一索引允许空值的。只有添加唯一键,才会创建唯一索引。

unique最好是不要为空。所以一般unique和not null一起使用。

创建唯一索引:

先插入新的列:

alter table member add COLUMN address varchar(40) not null;

在创建unique唯一索引:

alter table member add UNIQUE address_index(address);

创建唯一索引,而且不能为空,就算不给unique,他也自带unique,值是唯一的不能为空

create table test1 (

id int(4) PRIMARY KEY,

name varchar(10),

card_id int(18) not null,

phone int(11) not null,

unique cardid_index (card_id),

UNIQUE phone_index (phone)

);

mysql索引、事务、存储引擎_第12张图片

创建唯一索引之后,接相当于给列加上了一个unique约束,插入值不能重复

mysql索引、事务、存储引擎_第13张图片

命令方式创建唯一索引:

create UNIQUE index phone_index on member (phone);

6.3、主键索引:

创建表的时候指定的主键就是索引。添加主键自动就是主键索引

主键:值唯一 一个表只能有一个主键,不允许有空值,创建主键,自动主键索引

mysql索引、事务、存储引擎_第14张图片

命令方式创建主键索引:

alter table 表名 add primary key(字段);

删除主键索引:

删除主键索引不能用drop直接删除索引,只能删除主键约束,然后主键索引自动删除

alter table 表名 drop primary key;

6.4全文索引:
  • 适合在进行模糊查询的时候使用,可以在一边文章中检索文本信息

text

建表时创建:

create table test3 (

id int(4) PRIMARY KEY,

name varchar(10),

card_id int(18) not null,

phone int(11) not null,

notes text,

FULLTEXT notes_index (notes)

);

建表时创建全文索引:

create FULLTEXT index notes_index on test3 (notes);

使用全文索引查询:

like不能检测全文索引,要用WHERE MATCH(列名) AGAINST('查询内容');

SELECT * FROM 表名 WHERE MATCH(列名) AGAINST('查询内容');

mysql索引、事务、存储引擎_第15张图片

6.5、联合索引:
指定一个索引名,一个索引名对应多个列名

创建联合索引:

create index index_union on test3 (card_id,phone);

mysql索引、事务、存储引擎_第16张图片mysql索引、事务、存储引擎_第17张图片

联合索引,查询时必须按照创建时的顺序来进行查询

explain select * from test3 where card_id = 322 and phone = 333;

联合索引,从左到右侧开始,不能跳过索引,否则索引会失效

范围查询时有可能右侧的索引会失效

mysql索引、事务、存储引擎_第18张图片

mysql机制:默认会找最短的索引列。最优索引选择

如果索引是字符串,到那会是不加引号,索引也会失效

使用or作为条件的时候,MySQL无法同时使用多个索引

explain select * from test5 where id =8 or phone='111';

使用where is null 或where is not null时,有可能索引会失效

where is null:如果数据绝大多数都是空值,索引一定失效

where is not null:如果数据多数不为null,索引失效

删除索引:

drop index索引名 on 表名;

drop index notes_index on test3;

模糊查询:

select * from 表名 where 列名 like '%';

1%:查询1开头的

%1:查询1结尾的

查看索引是否生效:在select查询命令之前加上explain,查看key那一列,有则生效

EXPLAIN select * from 表名 where 列名 like '%';

检测全文索引:

explain select * from 表名 where match(列名) against(查询对象);

创建索引时,注意索引失效的情况

explain 加载查询语句前面可以查看索引的使用情况

现在一张表的查询速度是7.62s

你该如何解决?

答:

首先查缓存,看是不是直接请求到后端MySQL数据库了(缓存击穿)

再看索引,请求的列值不是默认的索引,添加一下即可

explain 查询命令

二、MySQL的事务:

事务是一种机制,一个操作序列。包含了一组数据库的操作命令,所有命令都是一个整体,向系统提交或者撤销的操作,要么都执行,要么都不执行。

他是一个不可分割的单位

1、事务的特点:ACID

A:原子性,最小单位,事务里的所有单位都是一个整体,不可分割,要么都成功,要么都失败

C:一致性,事务开始之前和事务结束之后数据库的完整性约束没有被破坏。

事务完成时,数据必须属于一致状态

事务开始前,数据库中的存储数据处于一致状态

进行中的事务,数据可能处于不一致的状态

当事务最终完成时,必须再次回到已知的一致状态

可能导致脏读

I:隔离性,指在并发环境中不同事物同事操纵相同的数据时,每个事务都有各自的完整的数据空间

对数据进行修改的所有并发事务是彼此隔离的,表明事务必须是独立的

修改数据的事务,可在另一个使用相同数据的事务开始之前。或者在另一个相同事务结束之后访问这些数据

D:持久性,事务一旦被提则不可逆,被持久化到数据库中,接下来即使数据库发生故障也不应该对其有任何影响

2、MySQL支持的隔离级别(4种):
  1. 未提交读,允许脏读,允许一个事务可以看到其他事务未提交的修改
  2. 提交读:事务只能查看只能提交的修改,未提交的修改是不可见的。他可以防止脏读

orcale sql-server

  1. 可重复读:也是MySQL的默认隔离级别。确保如果在一个事务中执行两次相同的select语句时,都能得到相同的结果,不管其他事务是否提交修改。可以防止脏读以及不可重复读
  2. 串行读:锁表,完全串行化,完全隔离。每一个事务都隔离,读写之间都会堵塞。会降低数据库的效率

3、事务并发导致的问题:

脏读:指一个事务读取了另外一个事务未提交的数据

不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同

虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致

丢失更新: 两个事务同时读取同一条记录,导致修改结果覆盖

4、事务的隔离级别:
  1. 未提交读:Read Uncommitted

允许脏读,即允许一个事务可以看到其他事务未提交的修改

  1. 提交读:Read Committed

允许一个事务只能看到其他事务已经提交的修改,未提交的修改是不可见的,防止脏读

  1. 可重复读:Repeatable Read——MySQL默认的隔离级别

确保如果实在一个事务中执行两次相同的select语句,都能得到相同的结果,不管其他事务是否提交这些修改。可以防止脏读和不可重复读

  1. 串行读:serializable——相当于锁表

完全串行化的读,将一个事务与其他事务完全地隔离。每次读都需要获得表级共享锁,读写相互都会阻塞。可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的执行效率

5、事务隔离的作用范围:
  1. 全局级:对所有的会话有效
  2. 会话级:

show global variables like '%isolation';

查询全局事务的隔离级别

select @@global.tx_isolation;

查询全局事务的隔离级别

查询会话事务的隔离级别

show session variables like'%isolation';

查询会话事务的隔离级别

select @@session.tx_isolation;

全局隔离级别修改:未提交读

set global TRANSACTION ISOLATION level read UNCOMMITTED;

修改全局的隔离级别

set @@global.tx_isolation='read UNCOMMITTED';

临时修改全局隔离,重启失效

修改会话隔离级别

set session TRANSACTION ISOLATION level read UNCOMMITTED;

set @@session.tx_isolation='read UNCOMMITTED';

脏读:

mysql索引、事务、存储引擎_第19张图片mysql索引、事务、存储引擎_第20张图片

不可重复读:一个事务内,多次读同一数据

前一个事务还没有结束,另一个事务也访问该数据

在一个事务之内,两次查询到的结果不一致。读不到相同的数据内容

mysql索引、事务、存储引擎_第21张图片

幻读:一个事务对一个表中的数据进行了修改,可能会涉及到表中的全部数据。另一个事务也修改了这个表的数据。前一个事务会发现表中还有数据还没有修改,类似于幻觉。

丢失更新:两个事务同时修改一条记录,A先记录B也修改记录,B一旦提交,会覆盖A的结果

不管如何操作,都以最后commit提交为主

6、以上情况如何避免:脏读、幻读、不可重复读、丢失更新
  1. 权限控制(核心)

根据情况来使用隔离级别

  1. 生产环境——最好是提交读和可重复读

测试环境——无所谓

  1. 生产环境只能允许一个人对一个事务进行操作。其他人不允许操作。

持久性:数据一旦提交,事务的效果将会被永久的保留在数据库中,而且不会被回滚。

实际生活中会主从复制、高可用、备份、权限控制多层保险

总结:在事务管理中,原子性是基础,隔离性是手段,一致性是目的持久性是最终的结果。

7、事务的控制语句:

开始事务:

begin开始

start transaction 显示的开启事务

提交事务:

commit

commit work

回滚:能撤销正在进行的所有未提交的修改

rollback

rollback work

回滚点:

savepoint s1(自定义名):创建回滚点,一个事务可以有多个回滚点

回到回滚点:

rollback to s1:回滚到s1还原点

一旦提交所有的还原点全部消失,不能还原

  1. 多点还原 s1 s2

如果说还原到s1,s2则消失

如果提交所有还原点全部消失

mysql 提交事务默认是自动提交(不begin 就是默认提价命令,不能rollback)

练习:

可以用set来设置MySQL提交方式:

set autocommit=0;

关闭自动提交

show variables like 'autocommit';

查看自动提交情况

关闭自动提交就相当于开启了,未提交读,也就是允许脏读,必须手动commit提交修改,才能同步数据,不然会脏读

三、存储引擎

存储引擎:MySQL中数据用各种不同的技术存储在文件中,每一种技术都使用不同的存储机制,索引技巧,锁定水平以及最终提供的不同的功能和能力,这些就是我们说的存储引擎

1、存储引擎的功能:
  1. MySQL将数据存储在文件系统的一种方式和格式
  2. 存储引擎负责执行实际的数据I/O操作(读写操作)
  3. 存储引擎介于数据和文件系统之间,数据会先保存到存储引擎,再按照存储引擎的格式保存到文件系统(硬盘)

2、MySQL的存储引擎分类:
  1. INNODB:5.5版本之后MySQL的默认存储引擎。事务性速记引擎。支持ACID事务。支持锁行,锁表。写入和查询性能比较好
  2. MYISAM:5.5版本之前的默认存储引擎。有较高的插入数据性能,查询速度也很优秀,但是他不支持事务(ACID)
  3. memory:所有数据都保存在内存的存储引擎。插入数据更新数据、查询数据速度比较快,到那时占用空间比较大。他会占用和数据量成正比的内存空间。MySQL一旦重启内容丢失
  4. csv:由逗号分割数据的存储引擎。他会在数据库子目录里为每一个数据表创建一个.csv的文件。就是一种普通的文本文件。每个数据行占用一个文本行。csv不支持索引
  5. Archive:他非常适合存储大量的独立的,而且是历史数据的引擎。不需要被经常读取。插入的速度很快,查询的效率比较低。
  6. blackhole:黑洞引擎,写入的任何数据都会消失。

3、MYISAM和INNODB分析和对比:
3.1、MYISAM:

不支持事务,也不支持外键,只支持全文索引,数据文件和索引文件是分开的,

访问速度快

适用场景:查询和插入数据为主的应用。

在磁盘上有三个文件:

文件名和表名相同。但是扩展名不同:

.frm:存储的表结构

.MYD:存储的数据文件

.MYI:索引文件

MYISAM的特点:

  1. 表级锁定:更新数据时,整个都将锁定
  2. 数据库在读写过程中相互堵塞

支持的存储格式:

  1. 静态表,固定长度表,静态表是MYISAM的默认存储格式。静态表中字段都是非可变字段。每个记录哦度黑丝固定长度。

优点:存储快,方便缓存,有了故障容易恢复

缺点:占用的空间比较大

  1. 动态表:动态表可以包含可变字段,记录的长度是不固定的。优点是占用空间少。频繁更新数据、删除记录,会产生记录碎片,需要定期清理。

定期清理命令:myisamchk -r 出现故障恢复比较困难

  1. 压缩表:myisamchk工具创建的表,占据的空间非常小,每条记录都是单独压缩的。

3.2、INNODB:
  1. 支持事务,支持四个事务的隔离级别。5.5版本之后是MySQL的默认存储引擎
  2. 读写阻塞和隔离级别相关。
  3. 支持高效的缓存索引以及缓存数据。
  4. 表与主键以簇的方式存储Btree
  5. 支持外键约束,5.5之后INNODB也可以支持全文索引
  6. 对硬件资源的要求较高
  7. 支持行锁定,也可以支持表锁定(全表扫描)

注意点:

  1. 使用like模糊查询,会进行全表扫描,锁定整个表
  2. 对没有创建索引的字段进行增 删 改,也会进行全表扫描。锁定整个表。
  3. 使用索引,进行增 删 改,则是行级索引

INNODB的特点:
1、不保存表的行数,统计表的行数,会扫描一遍整个表来计算有多少行

2、自增长字段,INNODB中必须包含只有该字段的索引

  1. delete清空表,一行一行删速度比较慢,推荐用truncate

适用场景:

  1. 业务需要事务的支持
  2. 论坛、微博,对数据一致性比较高的场景适用
  3. 访问量和并发量比较高的场景,INNODB可以支持缓存,减少后台服务器的压力

INNODB三个文件:

表名.frm(表结构文件)

表名.idb(即使数据文件,也是索引文件)

dp.opt:(表的属性文件)

4、语句:
4.1、查看支持的存储引擎:

show engines;

show engines\G;

mysql索引、事务、存储引擎_第22张图片

4.2、查看表使用的存储引擎:

方法一:

show table status from 库名 where name='表名'\G

show table status from ku where name='test'\G;

mysql索引、事务、存储引擎_第23张图片

方法二:

use 库名;

show create table 表名;

mysql索引、事务、存储引擎_第24张图片

4.3、改存储引擎:

方法一:alter table修改:

alter table 表名 engine=存储引擎名;

alter table test engine=MyISAM;

mysql索引、事务、存储引擎_第25张图片

方法二:修改配置文件

通过修改/etc/my.cnf配置文件,指定默认存储引擎并重启服务。

此方法只对修改了配置文件并重启mysql服务后 新创建的表有效已经存在的表不会更改。

mysql索引、事务、存储引擎_第26张图片

重启mysqld

systemctl restart mysqld.service

mysql索引、事务、存储引擎_第27张图片

方法三:通过create table创建表时指定存储引擎

mysql索引、事务、存储引擎_第28张图片

表结构文件所在目录:(编译安装)

mysql索引、事务、存储引擎_第29张图片

5、INNODB的行锁和索引的关系,以及表锁 排他锁 死锁

使用隔离级别:默认的可重复读

mysql索引、事务、存储引擎_第30张图片

锁行:对索引键操作

两边begin 操作索引时,会形成行锁,一个发送另一个同一行改不掉

如果说使用的id的字段是主键,INNODB对主键使用聚簇索引,锁定整行的记录

解决方法:commit之后立即生效

设置id为主键索引,name为普通索引:

mysql索引、事务、存储引擎_第31张图片

mysql索引、事务、存储引擎_第32张图片

前一个的修改没有结束,后面的操作不能进行

解决方法:commit提交操作。行锁取消

mysql索引、事务、存储引擎_第33张图片

mysql索引、事务、存储引擎_第34张图片

操纵索引对行进行过滤,锁定整行,其他行不影响。必须行的前一个操作结束,才能进行行的另一个操作

锁表:锁定表,要对一个非索引行操作(没有索引要全表扫描,以至于锁定整个表)

解决方法:commit之后立即生效

对非索引参数进行操作:

mysql索引、事务、存储引擎_第35张图片

mysql索引、事务、存储引擎_第36张图片

解决方式也是对上一个操作进行commit提交,提交之后才能进行下一个操作:

mysql索引、事务、存储引擎_第37张图片

当一个事务对非索引列进行操作,因为要全表扫描过滤,所以整张表都会被锁定,另一个事务只能查询操作

排它锁:

又叫悲观锁。一个事务在操作,另一个事务的操作无法执行,只能查。排它锁只能加一个。

for update 排他锁

select * from test where id = 2 for update;

mysql索引、事务、存储引擎_第38张图片mysql索引、事务、存储引擎_第39张图片

死锁:(基于排它锁)

事务之间相互等待对方资源,最后会形成一个环路造成的。

死锁基于排它锁形成

死锁形成时:

  1. 发生死锁的时候,数据库会自动选择一个事务作为受害者,然后先接触死锁,在回滚
  2. mysql默认的死锁机制,一旦发生死锁,会选择一个事务作为死锁的牺牲品,直接终止其中一个事务,但是不会自动回滚

mysql索引、事务、存储引擎_第40张图片

mysql索引、事务、存储引擎_第41张图片

总结:

索引只会锁行

非索引锁表

排它锁

死锁,会自动选择一个事务作为牺牲品,结束死锁。

乐观锁:不会有任何提示,只是数据不能写入而已。数据提交更新时,他会进行校验,发生冲突,数据不生效而已,没有其他的报错或者是卡停

一般来说,我们会在表中配置version字段,通过自增校验来查看数据是否冲突

除了version 也可以用时间戳timestreap

存储引擎只能是INNODB

mysql默认隔离级别即可

6、如何尽可能的避免死锁:
  1. 业务的逻辑要合理,以固定的顺序访问表和行
  2. 如果事务的类型比较复杂,要进行拆分,在业务允许的情况下,把大事务拆小,分次执行
  3. 在同一事物中,尽可能的一次锁定所有需要的资源。可以减少死锁的概率
  4. 隔离级别,read committed可以避免死锁
  5. 添加合理的索引(操作索引只锁行),减少死锁的概率

mysql索引、事务、存储引擎_第42张图片

mysql索引、事务、存储引擎_第43张图片

核心内容:

索引和行锁之间的关系

非索引的锁表以及死锁

排它锁

INNODB的机制和存储文件的格式。

你可能感兴趣的:(数据库,oracle,数据库,运维,mysql,1024程序员节)