1索引
索引的概念:
数据库索引
是一个排序的列表,存储着索引值和这个值所对应的物理地址,无须对整个表进行扫描,通过物理地址就可以找到所需数据,是表中一列或者若千列值排序的方法,需要额外的磁盘空间
类似于图书馆中寻找书,通过标签进行查找,提高查找的速度
索引就是一种帮助系统能更快速地查找信息的数据结构
索引的作用:
- 数据库利用各种快速定位技术,能够大大加快查询速率
- 当表很大或查询涉及到多个表时,可以成千上万倍地提高查询速度
- 可以降低数据库的IO成本,并且还可以降低数据库的排序成本
- 通过创建唯一性索引保证数据表数据的唯一性
- 可以加快表与表之间的连接
- 在使用分组和排序时,可大大减少分组和排序时间
索引的副作用:
- 索引需要占用额外的磁盘空间:对于MyISAM引擎而言,索引文件和数据文件是分离的,索引文件用于保存数据记录的地址。而innoDB引擎的表数据文件本身就是索引文件当表很大或查询涉及到多个表时,可以成千上万倍地提高查询速度
- 在插入和修改数据时要花费更多的时间,因为索引也要随之变动
创建索引的原则依据:
- 表的主键、外键必须有索引
- 记录数超过300行的表应该有索引
- 经常与其他表进行连接的表,在连接字段上应该建立索引
- 唯一性太差的字段不适合建立索引
- 更新太频繁地字段不适合创建索引
- 经常出现在where子句中的字段,特别是大表的字段应该建立索引
- 索引应该建在选择性高的字段上
- 索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引
索引的分类:
创建方式:
- 创建索引并且指向索引的字段
- 修改表的字段来添加索引
- 创建表直接创建索引
索引的分类方式
先创建一个表,并定义格式
create table qw (id int(10) ,name varchar(15) ,cardid varchar(18),phone varchar(11),address varchar(40),remark text);
添加数据进入表中
mysql> select * from qw;
+------+------+-----------+-----------+----------+----------+
| id | name | cardid | phone | address | remark |
+------+------+-----------+-----------+----------+----------+
| 1 | zs | 741852963 | 123456789 | nanjing | youxi |
| 2 | ls | 123456789 | 147258369 | beijing | youyong |
| 3 | ww | 123412385 | 147258741 | shanghai | youyong |
| 4 | zl | 987654321 | 147258982 | hainan | dengshan |
| 5 | zy | 123456789 | 147258258 | hainan | dengshan |
+------+------+-----------+-----------+----------+----------+
1、普通索引:
最基本的索引类型,没有唯一性之类的限制,针对所有字段,没有特殊的需求和规则
创建普通索引的方式
mysql> create index index_name on qw (name); 创建索引mysql> select name from qw; 通过索引搜索;
查看创建的索引方式:
1、
mysql> show create table qw;
2、通过表达式或者修改的方式进行创建
mysql> alter table qw add index id_inde(id);
mysql> mysql> alter table qw add index (id);
3、创建表的时候建立索引
mysql> create table at(id int(4) not null,name varchar(20) not null,cardid varchar(18) not null,index name_index (name));
Query OK, 0 rows affected (0.01 sec
2、唯一索引
与“普通索引”基本相同,与普通索引的区别是索引列的所有值只能出现一次,即必须唯一
针对唯一字段,仅允许出现一次空置
错误示范:
创建索引的列有重复条目,不符合唯一性,所以创建失败
成功案例:
create unique index phone_index on qw (phone);
唯一索引创建成功
组合索引:
可以是单列上创建的索引,也可以是在多列上创建的索引最左原则,从左往右依次执行
多列/多字段组合形式的索引 按照排序的顺序 否则无效.
新创建一个表,并写入数据
create table z4(id int not null,name varchar(20),cardid varchar(20),index index_zuhe (id,name));
insert into z4 values(1,'zsan','41278963');
组合索引定义成功
需要根据索引的设定来进行查询
全文索引:
varchar char text blob clob 检索内部信息来做字段的索引
主键索引:
直接创建主键即可
针对唯一字段,且不可为空,同时一张表只允许包含一个主键得索引
索引的查看与删除
查看索引:
格式:
show index from 表名
show keys from 表名
mysql> show index from z4;
删除索引:
格式:
drop index 索引名 on 表名
修改表的方式删除索引
alter table 表名 drop index 索引名
删除主键索引
alter table 表名 drop primary key;
事务
1、事务的概念
- 是一种机制、一个操作序列,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行
- 是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时,事务是最小的控制单元
- 适用于多用户同时操作的数据库系统的场景,如银行保险公司及证券交易系统等等
- 通过事务的整体性以保证数据的一致性
2、事务的ACID特点:
原子性(Atomicity)
事务是一个完整的操作,事务的各元素是不可分的,事务中的所有元素必须作为一个整体提交或回滚如果事务中的任何元素失败,则整个事务将失败
一致性 (Consistency)
当事务完成时,数据必须处于一致状态。在事务开始前,数据库中存储的数据处于一致状态。在正在进行的事务中,数据可能处于不一致的状态。当事务成功完成时,数据必须再次回到已知的一致状态
隔离性 (Isolation)
对数据进行修改的所有并发事务是彼此隔离的,表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务,修改数据的事务可在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数
持久性 (Durability)
指不管系统是否发生故障,事务处理的结果都是永久的。一旦事务被提交,事务的效果会被永久地保留在数据库中
3、事务之间的互相影响
不可重复读
概述
不可重复读是指在数据库并发事务处理中,一个事务在同一查询过程中多次读取同一数据,但每次读取的结果却不一致。
不可重复读通常发生在以下情况下:
1. 一个事务在查询某个数据行时,另一个事务在此期间修改了该数据行,并且提交了更改。这导致第一个事务在后续读取操作中看到了不同的数据内容。
2. 在一个事务中,多次查询同一范围内的数据行,而其他事务在这些查询之间进行了插入或删除操作。这样,每次查询时返回的数据行数可能会有所变化。
不可重复读可能会破坏事务的隔离性和数据的一致性,因为同一个事务在读取数据时得到的结果不一致。
如何避免不可重复读问题,
可以采取以下策略:
1. 使用合适的事务隔离级别:选择更高级别的隔离级别,如可重复读或串行化,以确保在同一事务中多次读取相同数据时,获得一致的结果。
2. 锁定机制:通过对需要读取的数据行进行锁定,防止其他事务对其进行修改,从而避免不可重复读问题。
3. 快照隔离:数据库系统可以通过创建事务快照来实现隔离,每个事务在开始时读取一致的数据快照,并在整个事务期间使用该快照进行读取操作,而不受其他事务的修改影响。
需要根据具体情况选择适当的并发控制策略和事务隔离级别,以确保数据的一致性和可靠性。
脏读
概述
脏读是指在数据库并发事务处理中,一个事务读取了另一个事务未提交的数据。换句话说,当一个事务对数据进行修改操作时,另一个事务却在此时读取了尚未提交的数据,导致读取到的数据可能是不一致或无效的。
脏读通常发生在以下情况下:
1. 一个事务在修改数据时,未提交(或回滚)该事务,而另一个事务在此时读取了这些未提交的数据。
2. 并发事务中,一个事务在读取数据时,另一个事务正在修改同一数据,但尚未提交。
脏读会破坏数据的一致性和可靠性,因为读取到的数据可能是临时的、不正确的或不完整的。
如何避免脏读问题,
可以采取以下策略:
1. 使用合适的事务隔离级别:选择适当的事务隔离级别,如读已提交或可重复读,以确保只能读取到已经提交的数据。
2. 锁定机制:通过对需要修改的数据行进行锁定,防止其他事务在未提交的情况下读取该数据,从而避免脏读。
3. 乐观并发控制:使用版本号或时间戳等机制,在事务提交之前检查数据是否被其他事务修改,以避免脏读的问题。
需要注意的是,在使用事务时,应根据具体情况选择适当的并发控制策略,以确保数据的一致性和可靠性。
幻读
概述
幻读是一种数据库中的并发控制问题,也被称为"不可重复读"。它指的是在一个事务中,当另一个事务在读取数据时,第一个事务可能会多次读取相同的数据行,但这个数据行的值可能会发生变化。这种情况可能导致事务的结果出现不一致性。
幻读通常发生在以下情况下:
1. 一个事务在读取某个范围内的数据时,另一个事务插入了新的数据行,导致第一个事务读取到了额外的数据行。
2. 一个事务在读取某个范围内的数据时,另一个事务删除了符合条件的数据行,导致第一个事务读取时发现少了一些数据行。
如何解决幻读问题,
数据库系统引入了一些机制,如锁定和多版本并发控制(MVCC)。
- 锁定:通过给相关的数据行加锁,可以防止其他事务对其进行修改,从而避免幻读的发生。
- MVCC:数据库系统可以通过为每个事务创建一个快照来实现多版本并发控制。当一个事务读取数据时,它只会看到在该事务开始之前已经提交的数据版本,而不会看到其他事务尚未提交的数据。
丢失更新
概述
丢失更新是指在并发事务处理中,一个事务的更新操作被另一个事务的更新操作所覆盖,导致前一个事务的更新结果丢失,最终数据的一致性受到破坏。
丢失更新通常发生在以下情况下:
1. 并发事务同时读取同一数据,并对其进行修改。如果两个事务都读取相同的初始值,并在提交时都写入了自己的修改结果,那么后提交的事务会覆盖先提交的事务的修改,从而导致前一个事务的更新结果丢失。
2. 并发事务之间存在依赖关系,其中一个事务的提交依赖于另一个事务的结果。如果后提交的事务修改了前一个事务所依赖的数据,那么前一个事务的更新结果也会丢失。
如何解决丢失更新问题,
可以采取以下策略:
1. 锁定机制:
通过对需要更新的数据行进行锁定,确保同一时间只有一个事务能够修改该数据,避免并发修改导致的丢失更新问题。
2. 事务隔离级别:
选择合适的事务隔离级别(如读已提交、可重复读等),以控制并发事务之间的影响,减少丢失更新的可能性。
3. 乐观并发控制:
通过使用版本号或时间戳等机制,允许并发事务同时进行读取和修改操作,但在提交时检查数据是否被其他事务修改过,以避免丢失更新的问题。
事务隔离级别的作用范围
全局级:对所有的会话有效
会话级:|只对当前的会话有效
1、查看全局事务和会话事务级别
全局事务级别
mysql> show global variables like '%isolation%';
SELECT @@global.tx_isolation;
会话事务等级
show session variables like '%isolation%';
mysql> SELECT @@session.tx_isolation;
2、 设置全局事务隔离级别和会话事务隔离级别
mysql> set global transaction isolation level read committed; #设置全局事务隔离事务mysql> set session transaction isolation level read committed; # 设置会话事务隔离级别
事务的控制语句:
BEGIN 或 START TRANSACTION:显式地开启一个事务。
COMMIT 或 COMMIT WORK:提交事务,并使已对数据库进行的所有修改变为永久性的。
ROLLBACK 或 ROLLBACK WORK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。
SAVEPOINT S1:使用 SAVEPOINT 允许在事务中创建一个回滚点,一个事务中可以有多个 SAVEPOINT;“S1”代表回滚点名称。
ROLLBACK TO [SAVEPOINT] S1:把事务回滚到标记点。
create database SCHOOL; 创建库
use SCHOOL;
create table info(
id int(10) primary key not null,
name varchar(40),
money double
); 创建表insert into info values(1,'A',1000);
insert into info values(2,'B',1000); 写入数据
select * from info;
1、测试提交数据
begin;事务开始固定格式
update info set money= money - 100 where name='A';
select * from info;commit;提交
quitmysql -u root -p
use SCHOOL;
select * from info;查看是否修改成功
2、测试回滚事务.
begin;
update info set money= money + 100 where name='A';
select * from info;rollback;
quit
mysql -u root -p
use SCHOOL;
select * from info;
3、测试多点回滚
begin;
update info set money= money + 100 where name='A';
select * from info;
SAVEPOINT S1;
update info set money= money + 100 where name='B';
select * from info;
SAVEPOINT S2;
insert into info values(3,'C',1000);select * from info;
ROLLBACK TO S1;
select * from info;
4、使用 set 设置控制事务
SET AUTOCOMMIT=0; #禁止自动提交
SET AUTOCOMMIT=1; #开启自动提交,Mysql默认为1
SHOW VARIABLES LIKE 'AUTOCOMMIT'; #查看Mysql中的AUTOCOMMIT值
use SCHOOL;
select * from info;
SET AUTOCOMMIT=0;
SHOW VARIABLES LIKE 'AUTOCOMMIT';
update info set money= money + 100 where name='B';
select * from info;
quitmysql -u root -p
use SCHOOL;
select * from info;
MySQL 存储引擎
概述
1、MvSQL中的数据用各种不同的技术存储在文件中,每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力,这些不同的技术以及配套的功能在MySQL中称为存储引擎
2、存储引擎是MySQL将数据存储在文件系统中的存储方式或者存储格式
3、MySQL数据库中的组件,负责执行实际的数据I/O操作作
4、MySQL系统中,存储引擎处于文件系统之上,在数据保存到数据文件之前会传输到存储引擎,之后按照各个存储引擎的存储格式进行存储
常用的存储引擎
1、MyISAM
MyISAM不支持事务,也不支持外键约束,只支持全文索引,数据文件和索引文件是分开保存的
访问速度快,对事务完整性没有要求 MyISAM 适合查询、插入为主的应用场景,
MyISAM在磁盘上存储成三个文件,文件名和表名都相同,但是扩展名分别为:
.frm 文件存储表结构的定义
数据文件的扩展名为 .MYD (MYData)
索引文件的扩展名是 .MYI (MYIndex)
例如
表级锁定形式,数据在更新时锁定整个表
数据库在读写过程中相互阻塞: ————》串行操作,按照顺序操作,每次在读或写的时候会把全表锁起来,会在数据写入的过程阻塞用户数据的读取,也会在数据读取的过程中阻塞用户的数据写入。
特性:
数据单独写入或读取,速度过程较快且占用资源相对少,MyIsam 是表级锁定,读或写无法同时进行,好处是:分开执行时,速度快、资源占用相对较少(相对)
MyISAM 表支持 3 种不同的存储格式
静态(固定长度)表
静态表是默认的存储格式。静态表中的字段都是非可变字段,这样每个记录都是固定长度的,这种存储方式的优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多。 固定长度10
存储非常迅速,容器缓存,故障之后容易恢复
动态表
动态表包含可变字段(varchar),记录不是固定长度的,这样存储的优点是占用空间较少,但是频繁的更新、删除记录会产生碎片,需要定期执行 OPTIMIZE TABLE 语句或 myisamchk -r 命令来改善性能,并且出现故障的时候恢复相对比较困难。
压缩表
压缩表由 myisamchk 工具创建,占据非常小的空间,因为每条记录都是被单独压缩的,所以只有非常小的访问开支。
3、MyISAM适用的生产场景
公司业务不需要事务的支持 ,单方面读取或写入数据比较多的业务, MyISAM存储引擎数据读写都比较频繁场景不适合 ,使用读写并发访问相对较低的业务,数据修改相对较少的业务 ,对数据业务一致性要求不是非常高的业务,服务器硬件资源相对比较差
MyIsam:适合于单方向的任务场景、同时并发量不高、对于事务要求不高的场景
2、InnoDB
1、InnoDB特点
支持事务,支持4个事务隔离级别(数据不一致问题)
MySQL从5.5.5版本开始,默认的存储引擎为 InnoDB 5.5 之前是myisam (isam) 默认
读写阻塞与事务隔离级别相关
能非常高效的缓存索引和数据
表与主键以簇的方式存储
支持分区、表空间,类似oracle数据库(5.5 ——》5.6 和5.7 第三代数据库8.0后版本) 支持外键约束,5.5前不支持全文索引,5.5后支持全文索引
InnoDB 中不保存表的行数,
如 select count() from table; 时,InnoDB 需要扫描一遍整个表来计算有多少行,
但是 MyISAM 只要简单的读出保存好的行数即可。需要注意的是,当 count()语句包含 where 条件时 MyISAM 也需要扫描整个表 对于自增长的字段,
InnoDB 中必须包含只有该字段的索引,但是在 MyISAM 表中可以和其他字段一起建立组合索引
清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表(truncate)
死锁
MyISAM :表级锁定
innodb :行级锁定
当两个请求分别访问/读取2行记录,同时又需要读取对方的记录数据,因为(行锁的限制)而造成了阻塞的现象
怎么解决死锁
企业选择存储引擎依据
业务场景如果并发量大,什么并发量大,读写的并发量大,那我们建议使用innoDB 如果单独的写入或是插入单独的查询,那我们建议使用没有INNODB
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低; 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
MyISAM不支持事务,也不支持外键约束,只支持全文索引,数据文件和索引文件是分开保存的
需要考虑每个存储引擎提供了哪些不同的核心功能及应用场景
• 支持的字段和数据类型
所有引擎都支持通用的数据类型
但不是所有的引擎都支持其它的字段类型,如二进制对象
• 锁定类型:不同的存储引擎支持不同级别的锁定
表锁定: MyISAM 支持
行锁定: InnoDB 支持
索引的支持
建立索引在搜索和恢复数据库中的数据时能显著提高性能
不同的存储弓|擎提供不同的制作索引的技术
•有些存储弓|擎根本不支持索引
事务处理的支持
提高在向表中更新和插入信息期间的可靠性
可根据企业业务是否要支持事务选择存储引擎
查看系统支持的存储引擎
show engines;
查看表使用的存储引擎
方法一
show table status from 库名 where name='表名'\G;
例:show table status from SCHOOL where name='info'\G;
方法二
use 库名;
show create table 表名;
修改存储引擎
方法一:通过 alter table 修改
use 库名;
alter table 表名 engine=MyISAM;
方法二:通过修改 /etc/my.cnf 配置文件,指定默认存储引擎并重启服务
quit
vim /etc/my.cnf
[mysqld]
default-storage-engine=INNODBsystemctl restart mysqld.service
修改完记得重启mysql服务
#注意:此方法只对修改了配置文件并重启mysql服务后新创建的表有效,已经存在的表不会有变更。
方法三:通过 create table 创建表时指定存储引擎
use 库名;
create table 表名(字段1 数据类型,...) engine=MyISAM;
面试题
1、索引——》mysql 优化
在合适的字段上创建索引
在有索引的情况下,数据库会先进行索引查询,然后定位到具体的数据行没有有索引的情况下扫描全表来定位某行的数据 )一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,
使用索引后,是先通过索引表找到该行数据对应的物理地址然后访问相应的数据,因此能加快数据库的查询速度。
2、事务特性(ACID)
事务ACID
原子性 (一个整体,要么都执行要么都不执行)
一致性 要求事务前后数据的完整和一致
隔离性 要求多个事务之间不相互影响依赖(4个影响,4个隔离级别)
持久性 当事务提交后将永久保存,不可再回滚
3、数据不一致的情况(四种)
(1)read uncommitted(未提交读) : 读取尚未提交的数据 :不解决脏读 允许脏读,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值。也就是可能读取到其他会话中未提交事务修改的数居。
(2)read committed(提交读):读取已经提交的数据 :可以解决脏读 只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别〈不重复读)。
(3)repeatable read(可重复度):重读读取:可以解决脏读 和 不可重复读 —mysql默认的 可重复读。无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响
(4)serializable:串行化:可以解决 脏读 不可重复读 和 虚读—相当于锁表 完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。
mysql默认的事务处理级别是 repeatable read ,而Oracle和SQL Server是 read committed 。
4、MyISAM 和 INNODB区别(差异)
InnoDB支持事物,而MylSAM不支持事物。
lnnoDB支持行级锁,而MylSAM支持表级锁.
InnoDB支持MVCC,而MlSAM不支持。
lnnoDB支持外键。而MyISAM不支持。
lnnoDB全文索引,而MylSAM支持。
INNODB
支持事务读写并发外键5.5版本以后支持全文索引行级锁定(在用like模糊匹配全表扫描时会表级锁定)对硬件资源要求较高,特别是内存高可以提高缓存能力
三个文件存储.frm(表结构) .ibd (表数据文件同时也是索引文件) db.opt (表属性文件)适合场景有事务要求的一致性要求高的读写并发量高的
MyISAM
不支持事务外键表级锁定
读写会相互阻塞支持全文索引资源消耗较低
三个文件存储 .frm(表结构).MYI(索引文件).MYD(数据文件)三种存储格式静态表动态表压缩表 适合场景单独的读取或插入
5、你们公司用哪种存储引擎
这是高级开发者面试时经常被问的问题。实际我们在平时的开发中,经常会遇到的,在用SQLyog等工具创建表时,就有一个引擎项要你去选
Mysql的存储引擎有这么多种,实际我们在平时用的最多的莫过于InnoDB和MyISAM了。
所有如果面试官问道mysql有哪些存储引那他们都有什么特点和区别呢?
那他们都有什么特点和区别呢?
MyISAM和InnoDB的特点:
MyISAM :默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。不是事务安全的,而且不支持外键,如果执行大量的select,insert MyISAM比较适合
InnoDB :支持事务安全的引擎,支持外键、行锁、事务是他的最大特点。如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS较高的情况。注: 在MySQL 5.5之前的版本中,默认的搜索引擎是MyISAM,从MySQL 5.5之后的版本中,默认的搜索引擎变更为InnoDB。
MyISAM和InnoDB的区别:
InnoDB支持事务,MyISAM不支持。对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务; InnoDB支持外键,而MyISAM不支持。
InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快。
Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;5.7以后的InnoDB支持全文索引了。
InnoDB支持表、行级锁(默认),而MyISAM支持表级锁。
InnoDB表必须有主键(用户没有指定的话会自己找或生产一个主键),而Myisam可以没有。
Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI。
Innodb:frm是表定义文件,ibd是数据文件。
Myisam:frm是表定义文件,myd是数据文件,myi是索引文件。