MySQL——索引、事务与存储引擎
索引
什么是索引?
索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址.
索引的作用
索引的作用:
- 加快表的查询速度,还可以对字段排序
- 可以加快表与表之间的连接。
索引的副作用:
- 会额外占用磁盘空间,更新包含索引的表会花费更多时间,效率会更慢。
索引是如何工作的?
没有索引的情况下,要根据条件查询某行数据时,需要先扫描全表,再定位某行数据的位置
有了索引后,会先通过查询条件的字段值找到其索引对应的行记录的数据的物理地址,然后根据物理地址访问相应的行记录的数据,就像根据书目录的也没快速找到所需的内容
在什么场景要适合创建索引呢?
- 表中的记录行数较多时,一般超过300行的表建议要有索引
- 建议在表中的主键字段,外键字段,多表连接使用的公共关键字段,唯一性较好的字段,不经常更新的字段,经常出现在where,group by,order by子语句的字段,短小的字段上面创建索引
- 不建议在唯一性较差的字段,更新太频繁的字段,大文本字段上面创建索引
索引的类型
普通索引:最基本的索引类型,没有唯一性之类的限制
create index 索引名 on 表名 (字段/列名(指定字符长度)); alter table 表名 add index 索引名 (字段);
唯一索引:与普通索引类似,但区别是唯一索引列的每个值都唯一。
唯一索引允许有空值(注意和主键不同)。如果是用组合索引创建,则列值的组合必须唯一。添加唯一键将自动创建唯一索引。
create unique index 索引名 on 表名 (字段);
alter table 表名 add unique 索引名 (字段);
主键索引:是一种特殊的唯一索引,必须指定为“PRIMARY KEY”。
一个表只能有一个主键,不允许有空值。 添加主键将自动创建主键索引。
create table 表名 (,primary key (字段));
alter table 表名 add primary key (字段);
create index 索引名 on 表名 (字段1,字段2,..); create unique index 索引名 on 表名 (字段1,字段2,...); alter table 表名 index 索引名 (字段1,字段2); alter table 表名 unique 索引名 (字段1,字段2); select ... from 表名 where 字段1=xx and 字段2=xx..; #用and做逻辑运算符多字段查询时,要创建组合索引且要满足最左原则 #用or做逻辑运算符多字段查询时,所有字段都要单独创建单索引
全文索引:适合在进行模糊查询的时候使用,可用于在一篇文章中检索文本信息。
create fulltext index 索引名 on 表名 (字段)
#支持模糊查询
select ... from 表名 where match (字段) against('单词');
如何查看索引?
show create table 表名;
show index from 表名;
show keys from 表名;
各字段的含义
Table:表的名称。 Non_unique:如果索引不能包括重复词,则为 0;如果可以,则为 1。 Key_name:索引的名称。 Seq_in_index:索引中的列序号,从 1 开始。 Column_name:列名称。 Collation:列以什么方式存储在索引中。在 MySQL 中,有值‘A’(升序)或 NULL(无分类)。 Cardinality:索引中唯一值数目的估计值。 Sub_part:如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则为 NULL。 Packed:指示关键字如何被压缩。如果没有被压缩,则为 NULL。 Null:如果列含有 NULL,则含有 YES。如果没有,则该列含有 NO。 Index_type:用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。 Comment:备注。
删除索引:
drop index 索引名 on 表名;
alter table 表名 drop index 索引名;
alter table 表名 drop primary key;#删除主键
1)先使用explain 分析select 语句,看key字段,确定select语句使用索引或者索引使用是否正确
事务
什么是事务?
事务就是一组数据库操作序列(包含一个或多个SQL操作命令),事务会把所有操作看作是一个不可分割的整体向数据库系统提交或撤销操作,所有操作要么都执行,要么都不执行
事务的ACID特性:原子性、一致性、隔离性、持久性
原子性:
一致性:
隔离性:事务隔离的手段
使多个事务并发操作同一个表数据时,每个事务都有各自独立的数据空间,事务的执行不会受到其他事务的干扰。可通过设置隔离级别解决不同的一致性问题
持久性:事务管理的结果
当事务被提交以后,事务中的命令操作修改的结果会被持久保存,且不会被回滚
隔离级别:
未提交读 read uncommitted: 允许 脏读 不可重复读 幻读
提交读 read committed: 允许 不可重复读 幻读,不允许 脏读
可重复读 repeatable read: 有条件的允许 幻读(innodb存储引擎可以不允许) , 不允许 脏读 不可重复读
串行读 serializable: 都不允许,相当于表级锁定,但是会影响数据库的读写效率和性能
隔离级别 | 脏读 | 不可重复读 | 幻读 |
未提交读 | √ | √ | √ |
提交读 | × | √ | √ |
可重复读 | × | × | InnoDB不可以 |
串行读 | × | × | × |
脏读:
当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据
不可重复读:
指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)
幻读:
一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,另一个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,操作前一个事务的用户会发现表中还有一个没有修改的数据行,就好象发生了幻觉一样。
设置隔离级别:
set global transaction isolation level 隔离级别名称;
#全局级别的设置,可在所有会话有效,需要重新登录才可生效
set session transaction isolation level 隔离级别名称;
#会话级别的设置,在当前会话中立即生效
查看隔离级别:
show global variables like '%isolation%';
#查看全局级别的 show session variables like '%isolation%';
#查看会话级别的
事务管理的操作:
begin;
#开启一个事务 ..... insert into updata xx set delete from
#事务性操作 savepoint xx; #在事务中创建回滚点 rollback ro xx; #在事务中回滚操作到指定的回滚点位置 commit;或 rollback; #提交或回滚结束事务
事务的自动提交:
set global/session autocommit=0; #关闭自动提交 set global/session autocommit=1; #开启自动提交,mysql默认为1 show global/session variables like 'autocommit'; #查看mysql中的autocommit值
存储引擎
什么是存储引擎?
存储引擎是mysql数据库中的组件,负载执行实际的数据I/O操作(数据的存储和提取),工作在文件系统之上,数据库的数据会先传到存储引擎,在按照存储引擎的格式保存到文件系统
常用的存储引擎:InnoDB MyISAM
MyISAM:
不支持事务,不支持外键约束,只支持全文索引
访问速度快,对事务完整性没有要求
适合查询、插入为主的应用
在磁盘上存储成三个文件,文件名和表名都相同,但是扩展名分别为:
- .frm 文件存储表结构的定义
- 数据文件的扩展名为.MYD(MYData)
- 索引文件的扩展名是.MYI(MYIndex)
MyISAM 表支持 3 种不同的存储格式:
(2)动态表 动态表包含可变字段,记录不是固定长度的,这样存储的优点是占用空间较少,但是频繁的更新、删除记录会产生碎片,需要定期执行 OPTIMIZE TABLE 语句或 myisamchk -r 命令来改善性能,并且出现故障的时候恢复相对比较困难。
(3)压缩表 压缩表由 myisamchk 工具创建,占据非常小的空间,因为每条记录都是被单独压缩的,所以只有非常小的访问开支。
myisam适用的生产场景:
公司业务不需要事务的支持
单方面读取或写入数据比较多的业务
myisam存储引擎数据读写都比较频繁的场景不适合
使用读写并发访问相对较低的业务
对数据业务一致性要求不是非常高的业务
服务器硬件资源相对比较差
InnoDB
支持事务,支持4个事务隔离级别
MySQL从5.5.5版本开始,默认的存储引擎为InnoDB
读写阻塞与事务隔离级别相关
能非常高效的缓存索引和数据
表与主键以族的方式存储
支持分区、表空间,类似oracle数据库
支持外键约束,5.5前不支持全文索引,5.5后支持全文索引
对硬件资源要求还是比较高的场合
innodb适用生产场景:
业务需要事务的支持 行级锁定对高并发有很好的适应能力,但需确保查询是通过索引来完成业务数据更新较为频繁的场景 如:论坛,微博等 业务数据一致性要求较高。 如:银行业务 硬件设备内存较大,利用nnoDB较好的缓存能力来提高内存利用率,减少磁盘IO的压力
MyISAM:
不支持事务、外键约束,只支持表级锁定,适合单独的查询和插入的操作,读写会相互阻塞,支持全文索引,硬件资源占用较小,数据文件和索引文件是分开存储的(存储成三个文件:表结构文件.frm、数据文件.MYD、索引文件.MYI)
使用场景:适用于不需要事务支持,单独的查询或插入数据的业务场景
InnoDB:
支持事务、外键约束,支持行级锁定(在全表扫描时仍然会表级锁定),读写并发能力较好,支持全文索引(5..5版本之后),缓存能力较好可以减少磁盘io的压力,数据文件也是索引文件(存储成两个文件:表结构文件.frm、数据文件.ibd)
使用场景:适用于需要事务的支持,一致性要求较高,数据会频繁更新,读写并发高的业务场景
查看表的存储引擎
show create table 表名; show table status [from 库名] where name='表名' \G show engines;
修改表的存储引擎
alter table 表名 engine=innodb/myisam; #针对已存在的表修改存储引擎 create table 表名(...)engine=innodb/myisam; #新建表时指定存储引擎 vim /etc/my.cnf [mysqld] default-storage-engine=INNODB/myisam #设置新建表的默认存储引擎
什么是死锁?
死锁是指两个或多个事务在同一个资源上相互占用,并请求对方的锁定资源,从而导致恶性循环的现象
如何避免死锁
1)设置事务超时等待时间 innodb_lock_wait_timeout
2)设置开启死锁检测 innodb _deadlock_detect
3)为表添加合理的索引,减少表锁发生的概率
4)如果业务允许,可以降低隔离级别,比如使用 “提交读” 隔离级别
5)建议开发人员尽量使用更合理的业务逻辑
6)建议开发人员尽量保持事务简短
7)建议开发人员在读多写少的场景下使用乐观锁机制
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~