数据库索引、事务与存储引擎
索引的概念
数据库索引
是一个排序的列表,存储着索引值和这个值所对应的物理地址
无须对整个表进行扫描,通过物理地址就可以找到所需数据
是表中一列或者若干列值排序的方法
需要额外的磁盘空间
索引的作用
数据库利用各种快速地位技术,能够大大加快查询速率
当表很大或查询涉及到多个表时,可以成千上万倍的提高查询速率
可以降低数据库的IO成本,并且可以降低数据库的排序成本
通过创建唯一性索引保证数据表数据的唯一性
可以加快表与表之间的连接
在使用分组和排序时,可以大大减少分组和排序时间
索引的分类
普通索引、唯一索引、主键索引、组合索引,全文索引
索引的创建方法
直接创建索引、修改表结构方式添加索引、创建表结构时创建索引
普通索引
最基本的索引类型
create(drop) index index_name ON table_name; #直接创建(删除)
create index name_sy on b(name); #在b表中创建名称为name_sy的索引
show index from b; #查看b表中的索引
show index from b\G
drop index name_sy on b; #删除b表中名称为name_sy的索引
alter table table_name add(drop) index index_name #修改表时添加(删除)
alter table b add index namesy(name); #在b表中创建名称为name_sy的索引
show index from b; #查看b表中的索引
create table table_name ('name'.........,index index_name (title)) //创建表时添加
create table c(id int(2) auto_increment primary key, name varchar(128) not null,index nameys(name)); #在新创建的表c中创建名为nameyn的索引
show index from c; #查看b表中的索引
唯一性索引
与普通索引相同,但是索引列的所有值只能出现一次,及必须唯一
CREATE UNIQUE INDEX index_name ON table_name (column) ; #直接创建
create unique index agesy on b(age); #在表b中创建agsy索引,以age为索引字段
ALTER TABLE table_name ADD UNIQUE index_name (column) ; #修改表时创建
alter table b add unique idsy(id);
创建表时添加唯一索引
create table table_name(id int(10), name varchar(128), unique index_name(column));
create table c(id int(10), name varchar(128), unique idsy(id));
主键索引
是一种特殊的唯一索引,指定为“primary key”,一个表只能由一个主键,不允许有空值,一般在创建表时同时创建主键索引
create table c(id int(2) not null auto_increment, name int(128),primary key(id));
alter table table_name add primary key(id) ; #修改表时创建
create table d(id int(3) not null , name varchar(64)); #先创建一个表
alter table d add primary key(id);
组合索引
可以是单列上创建的索引,也可以是在与多列上创建的索引,最左原则,从左往右依次执行
创建组合索引的方式:创建表时添加索引
create table e(id int(2) aouto_crement, name varchar(64), age int(3), index e(id,name,age));
全文索引
MySQL从3.23.23版开始支持全文索引和全文检索
索引类型为FULLTEXT
可以在CHAR,VARCHAR或者TEXT类型是列上创建
CREATE INDEX index_name ON table_name(column(length)); #直接创建
create fulltext index fd on b(name(128));
ALTER TABLE table_name ADD INDEX index_name(column(length));#修改表时添加
alter table b add fulltext index qw(age);
create table c(id int(3) not null , name varchar(64), score int(3), fulltext (name));#创建表时创建索引
创建索引的原则依据
表的主键,外键(约束表的一致性)必须有索引
记录数超过300行的表应该有索引
经常与其他表进行连接的表,在连接字段上应该建立索引
唯一性太差的字段(如性别,年龄)不适合建立索引
更新太频繁地字段不适合创建索引
经常出现在where子句中的字段,特别是大表的字段,应该建立索引
索引应该建在选择性高的字段上
索引应该建在小字段上,对于大的的文本字段甚至超长字段,不要建索引
事务
事务的概念
是一种机制、一个操作序列,包含了一-组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行, 要么都不执行
是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时,事务是最小的控制单元
适用于多用户同时操作的数据库系统的场景,如银行、保险公司及证券交易系统等等
通过事务的整体性以保证数据的一致性
数据不一致的后果
脏读
读取未提交的数据
A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。就好像原本的数据比较干净、纯粹,此时由于B事务更改了它,这个数据变得不再纯粹。这个时候A事务立即读取了这个脏数据,但事务B良心发现,又用回滚把数据恢复成原来干净、纯粹的样子,而事务A却什么都不知道,最终结果就是事务A读取了此次的脏数据,称为脏读。
不可重复读取
前后读取内容不一致
事务A在执行读取操作,由整个事务A比较大,前后读取同一条数据需要经历很长的时间。而在事务A第一次读取数据,比如此时读取了小明的年龄为20岁,事务B执行更改操作,将小明的年龄更改为30岁,此时事务A第二次读取到小明的年龄时,发现其年龄是30岁,和之前的数据不一样了,也就是数据不重复了,系统不可以读取到重复的数据,称为不可重复读取。
幻读
前后读取总量不一致
事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,称为幻读。
事务的ACID特点
原子性
事务是一个完整的操作,事务的各元素是不可分的
事务中的所有元素必须作为一个整体提交或回滚(回到事务开始前状态)
如果事务中的任何元素失败,则整个事务将失败
一致性
当事务完成时,数据必须处于一致状态
在事务开始前,数据库中存储的数据处于一致状态
在正在进行的事务中,数据可能处于不一致的状态
当事务成功完成时,数据必须再次回到已知的一致状态
隔离性
对数据进行修改的所有并发事务是彼此隔离的,表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务
修改数据的事务可在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数据
持久性
指不管系统是否发生故障,事务处理的结果都是永久的
一旦事务被提交,事务的效果会被永久地保留在数据库中
关于事务的一致性
在开始到提交之间的操作,在提交前的操作仅自己本地可见,不会对数据库产生影响,事务产生的数据变化取决于提交
事务的控制方法
MySQL事务默认是自动提交的,当SQL语句提交时事务便自动提交
set autocommit=0; #禁止自动提交
show variables like 'autocommit';#查看默认自动提交状态
事务控制语句
begin #事务的开始
commit #提交
rollback #回滚
savepoint 存档点名称 #存档点
release savepoint 存档点名称 #删除存档点
rollback to 存档点名称 #回滚到某个存档点
set transaction #设置事务
begin;#开始事务
insert into b value(5,16,'panh',89,134); #插入数据
select * from b; #查看
从另外一台主机上登录数据库,查看表b,插入的数据还没有产生作用
将事务提交后,在另一台主机上查看
保存点设置
begin; #开始事务
select * from b; #查看
delete from a.b name='panh';#删除数据
select * from b;
savepoint a; #创立保存点a
delete from a.b name='lisi';
select * from b;
savepoint b;
delete from a.b name='wangwu';
select * from b;
savepoint c;
回滚到保存点
select * from b; #查看
rollback to c; #回滚到保存点c
select * from b;
rollback to b;
select * from b;
rollback to a;
select * from b;
rollback;#回滚到事务开始
select * from b;
回滚到保存点只能按照创建保存点反向顺序回滚,不能跳跃回滚,并且只能回滚到当前时间点之前的保存点,之后的保存点无法回滚到
存储引擎介绍
存储引擎概念介绍
MySQL中的数据用各种不同的技术存储在文件中,每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力,这些不同的技术以及配套的功能在MySQL中称为存储引擎
存储引擎是MySQL将数据存储在文件系统中的存储方式或者存储格式
MySQL常用的存储引擎:
MyISAM
InnoDB
MySQL数据库中的组件,负责执行实际的数据I/O(输入/输出)操作
MySQL系统中,存储引擎处于文件系统之上,在数据保存到数据文件之前会传输到存储引擎,之后按照各个存储引擎的存储格式进行存储
MyISAM的介绍
MyISAM不支持事务,也不支持外键
访问速度快
对事务完整性没有要求
MyISAM在磁盘上存储成三个文件:
.frm 文件存储表定义
数据文件的扩展名为 .MYD (MYData)
索引文件的扩展名是 .MYI (MYIndex)
表级锁定形式,数据在更新时锁定整个表
数据库在读写过程中相互阻塞(不能同时进行)
会在数据写入的过程阻塞用户数据的读取 也
会在数据读取的过程中阻塞用户的数据写入
数据单独写入或读取,速度过程较快且占用资源相对少
MyIAM支持的存储格式:
静态表
动态表
压缩表
解析MyIAM支持的存储格式
1.静态表是默认的存储格式。静态表中的字段都是非可变字段,这样每个记录都是固定长度的,这种存储方式的优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多。静态表在数据存储时会根据列定义的宽度定义补足空格,但是在访问的时候并不会得到这些空格,这些空榕在返回给应用之前已经去掉。同时需要注意:在某些情况下可能需要返回字段后的空格,而使用这种格式时后面的空格会被自动处理掉。
2.动态表包含可变字段,记录不是固定长度的,这样存储的优点是占用空间较少,但是频繁的更新、删除记录会产生碎片,需要定期执行OPTIMIZE TABLE 语句或myisamchk -r命令来改善性能,并且出现故障的时候恢复相对比较困难。
3.压缩表由myisamchk 工具创建,占据非常小的空间,因为每条记录都是被单独压缩的,所以只有非常小的访问开支。
MyISAM适用的生产场景举例
公司业务不需要事务的支持
单方面读取或写入数据比较多的业务
MyISAM存储引擎数据读写都比较频繁场景不适合
使用读写并发访问相对较低的业务
数据修改相对较少的业务
对数据业务一致性要求不是非常高的业务
服务器硬件资源相对比较差
InnoDB特点介绍
支持4个事务隔离级别
行级锁定,但是全表扫描仍然会是表级锁定
读写阻塞与事务隔离级别相关
能非常高效的缓存索引和数据
表与主键以簇的方式存储
支持分区、表空间,类似oracle数据库
支持外键约束,5.5前不支持全文索引,5.5后支持全文索引
对硬件资源要求还是比较高的场合
解析分区,表空间
分区就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的
分表就是把一张表按一定的规则分解成N个具有独立存储空间的实体表。系统读写时需要根据定义好的规则得到对应的字表明,然后操作它。
分库一旦分表,一个库中的表会越来越多
表空间是数据库的逻辑划分,一个表空间只能属于一个数据库。所有的数据库对象都存放在指定的表空间中。但主要存放的是表,所以称作表空间。
一个数据库可以包含多个表空间,一个表空间只能属于一个数据库
一个表空间包含多个数据文件,一个数据文件只能属于一个表空间
InnoDB适用生产场景分析
业务需要事务的支持
行级锁定对高并发有很好的适应能力,但需确保查询是通过索引来完成
业务数据更新较为频繁的场景,如:论坛,微博等
业务数据一致性要求较高,如:银行业务
硬件设备内存较大,利用Innodb较好的缓存能力来提高内存利用率,减少磁盘IO的压力
企业选择存储引擎依据
需要考虑每个存储引擎提供的核心功能及应用场景
支持的字段和数据类型
所有引擎都支持通用的数据类型
但不是所有的引擎都支持其它的字段类型,如二进制对象
锁定类型:不同的存储引擎支持不同级别的锁定
表锁定
行锁定
索引的支持
建立索引在搜索和恢复数据库中的数据时能显著提高性能
不同的存储弓|擎提供不同的制作索引的技术
有些存储弓|擎根本不支持索引
事务处理的支持
提高在向表中更新和插入信息期间的可靠性
可根据企业业务是否要支持事务选择存储引擎
修改存储引擎方法
1: alter table修改
alter table table_ name engine=引擎;
2:
修改my.cnf,指定默认存储引擎并重启服务
default- storage-engine=InnoDB
3:
create table创建表时指定存储引擎
create table表名(字段) engine=引擎
show engines\G 查看存储引擎
show create table b\G #查看表b的存储引擎
1,直接在数据库里修改表的存储引擎
alter table b engine=MyISAM;
show create table b\G #查看表b的存储引擎
2,在数据库的配置文件中修改
exit;#退出mysql
vi /etc/my.cnf
default-storage-engine=MyISAM #添加
systemctl restart mysqldsystemctl restart mysqld #重启服务
mysql -uroot -p #登录数据库
create table test(name varchar(64));#新建表
show create table test\G #查看
3,创建表时指定存储引擎
create table d(id int(3)) engine=InnoDB; 创建表指定存储引擎