索引:是一个排序的列表 列表中存储的是索引的值和包含这个值数据所在行的物理地址
索引的作用
索引创建的原则:
索引的类型:
排序时 索引是失效的
常用类型:
B-树索引 BTREE索引 树行结构索引 也是大部分数据库的默认索引类型
叶子节点:直接指向表里的数据
分支节点:指向索引里其他的分支节点 也可以是叶子节点
根节点:指向分支节点
哈希索引:
把任意长度的输入 通过散列算法变成固定的长度的输出 散列值分别对应数据里的列和行
MySQL的默认引擎是innodb
Memory引擎可以支持哈希 默认索引就是哈希索引
先算散列值 然后对应 速度较慢
哈希索引匹配方式 = in() <= >
查看表的索引:
Show index from 表名;
创建btree索引
Create index name_index on 表名 (name);
创建索引需要考虑因素:
索引的副作用:索引也需要占用额外的磁盘空间innodb表数据文件本身也是索引,myisam:索引和数据文件是分离的。更新一个包含索引的表,要比更新一个没有索引表花费的时间更多。更新值了值,也就是更新索引。
创建索引:
普通索引 唯一索引
Index name_index(name):创建普通索引
唯一索引:
Unique 与普通索引类似 唯一索引的每个值都是唯一 唯一索引允许空值 添加唯一键才会创建唯一索引 最好不要为空 not null
以添加方式创建唯一索引
Alter table 表名 add unique 索引名(表名);
能在建表时创建好的条件 尽量在创建时把条件约束好 不要创完之后再添加
主键索引 创建表的指定的主键就是索引 添加主键自动就是主键索引
主键:值唯一 一个表只能有一个主键 不允许有空值 创建主键自动创建主键索引
全文索引 一般用于长文本列 text 适合在进行模糊查询的时候使用 可以在一边文章中检索文本信息
在建表中写:fulltext 索引名(列名);
通过修改添加:Create fulltext index 索引名 on 表名(列名);
删除索引
Drop index 索引名 on 表名
模糊查询
Select * from 表名 where 列名 like ‘%’
Explanin加select 查询索引是否生效
如何创建联合索引 指定一个索引名 一个索引名对应多个列名
Create index 索引名 on 表名 (列名,列名);
Explain select * from 表名 where 列名 like ‘%’;
联合索引查询时 必须按照创建时的顺序查询 否则索引会失效
MySQL机制默认会找最短的索引列 最优索引选择
范围查询 有可能右侧的索引会失效
如果索引是字符串 但是不加引号也会失效
使用or语句 索引一定失效 MySQL无法同时使用多个索引
Is not null 有时索引会失效 where is null 如果数据绝大多数都是空值 索引失效
Where is not null 如果数据多数不为空 索引也会失效
In 和 not in
全文索引要用
索引总结
类型:普通索引 主键索引 唯一索引 全文索引 联合索引
创建索引时 注意索引失效情况 explain加在查询语句前 可以查看索引使用情况
面试题:一张表的查询速度是7.62s 该如何解决
首先检查缓存 看是不是请求直接到后端数据库
再看索引 请求的列值不是默认的索引 添加一下即可 用explain查看
MySQL事务:
事务是一种机制 一个操作序列 包含了一组数据库的操作命令 所有命令都是一个整体 想系统提交或撤销的操作 要么都执行 要么都不执行
不可分割的单位
事务的特点ACID:
A 原子性 最小单位 事务里的所有条件都是一个整体 不可分割 要么都成功 要么都失败
C 一致性 事务开始前和事务开始后 数据库的完整性约束没有被破坏 事务完成时 数据必须属于一致状态 事务开始时 数据库中的存储数据属于一致状态 进行中的事务 数据可能处于不一致的状态 在事务最终处理完后 必须再次回到已知的一种状态
I 隔离性 指在并发环境中 不同事务同时操作相同的数据时 每个事务都有各自完整的数据空间 对数据修改的所有并发事务是彼此隔离的 表明事务必须是独立的 修改数据的事务可以在另一个使用相同数据的事务开始之前访问这些数据 或者在另一个使用相同数据的事务结束只会访问这些数据
MySQL支持的四种隔离级别:
脏读:另外一个事务可以看到另外一个事务未提交的修改结果
事务隔离级别的作用范围:
SELECT * FROM vip_member;
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';
临时修改会话隔离级别
FLUSH PRIVILEGES;
刷新
不可重复读:一个事务内 多次读同一数据 前一个事务还没有结束 另一个事务也访问该数据 在一个事务
内 两次查询到的结果不一致 读不到相同的数据内容
先把全局和会话改成提交读
FLUSH PRIVILEGES;
幻读:一个事务对一个表中的数据进行了修改 可能会涉及到全部数据
另一个事务也修改了这个表的数据 插入了一行新的数据 前一个事务会发现
表中还有数据没修改 类似幻觉
丢失更新:两个事务同时修改一条记录 a先记录b也修改了记录 b提交会覆盖a的结果
如何避免 :
权限控制
根据情况使用隔离级别
生产环境允许一个人对一个事务进行操作 其他人不允许操作
D:持久性 数据一旦提交 事务效果将会永久保留在数据库中 而且不会被回滚
总结:
在事务管理中 原子性是基础 隔离性是手段 一致性是目的 持久性是最终结果
事务的控制语句:
Begin
Start transaction 都可以作为显示的开启事务
Commit
Commit work 都可以作为提交事务
Rollback
Rollback work 都可以作为回滚事务 撤销正在进行的所有未提交的修改
Cavepoint 自定义名 创建还原 一个事务可以有多个回滚点
Rollback to 自定义名 回滚到哪个还原点
多点还原时 注意顺序
MySQL提交事务默认是自动提交
一旦提交 还原点全部消失
Set设置mysql的提交方式
Show variables like ‘autocommit’
关闭自动提交
Set autocommit = 0 如果不自动提交会怎么样
存储引擎
在MySQL中 数据用各种不同技术存储在文件中 每一种技术都使用一种不同的存储机制 索引技巧 锁定水平以及最终提供的不同的功能和能力
功能:
MySQL存储引擎的分类:
Myisam和INNODB对比:
Myiam:不支持事务 不支持外键 只支持全文索引 数据文件和索引文件分开的 访问速度快 适用场景:查询和插入数据为主的应用
在磁盘上会有三个文件 文件名和表名相同 扩展名不同
.frm 存储表结构 .myd 存储数据文件 .myi 索引文件
Myisam的特点
支持的存储格式
Innodb:
支持事务 支持四个事务的隔离级别 是MySQL的默认存储引擎 读写阻塞和隔离级别相关
支持高效的缓存索引和缓存数据
表与主键以簇方式存储btree
支持外键约束 5.5后可以支持全文索引
对硬件要求比较高 支持行锁定(全表扫描)
特点:
不保存表的行数 统计表的行数 会扫描全表来计算有多少行
自增长字段 innodb中必须包含只有改字段的索引
Delect清空表 一行一行删
适用场景:
三个文件:
表名.frm(表结构文件)
表名.idb(既是数据文件 又是索引文件)
表名.opt(表的属性文件)
Innodb行锁和索引的关系以及表锁 排他锁 死锁
CREATE TABLE IF NOT EXISTS test(
id INT(5) PRIMARY KEY,
name CHAR(8),
age INT(3),
sex CHAR(2)
);
ALTER TABLE test ADD INDEX name_index(name);
SHOW INDEX FROM test;
INSERT INTO test VALUES (1,'张三',90,'男');
INSERT INTO test VALUES (2,'张四',11,'男');
INSERT INTO test VALUES (3,'张五',12,'男');
INSERT INTO test VALUES (4,'张六',19,'男');
INSERT INTO test VALUES (5,'张七',17,'男');
INSERT INTO test VALUES (6,'张八',18,'男');
SELECT * FROM test;
begin;
UPDATE test SET age=90 WHERE id = 1;
UPDATE test SET sex='女' WHERE name='张三';
如果name字段是一个普通索引 会所著索引行 对应的主键一并锁住 实际上就是行锁
SELECT * from test where id = 1 ;
UPDATE test SET sex='女' WHERE name='张四';
commit;
如果使用的id的字段是主键 innodb对主键适用聚簇索引 直接锁定整行记录
锁定表 要对一个非索引键进行操作
begin;
UPDATE test set name='张八十' WHERE age = '18';
当一个事务对非索引列进行操作 因为要全表扫描过滤 整张表都会被锁定 另一个事务只能查
死锁 事务相互等待对方资源 最后形成环路
FOR UPDATE 排他锁 悲观锁
1、当死锁发生时 数据库会自动选择一个事务作为受害者 然后先解除死锁 再回滚事务
2、MySQL默认的死锁机制 一旦发生死锁 会选择一个事务作为死锁的牺牲品 直接终止
其中一个事务 但是不会自动回滚
存储引擎只能是innodb MySQL默认隔离级别即可
如何尽可能避免死锁
业务逻辑要合理以固定的顺序访问表和行
如果事务的类型比较复杂 要进行拆分 在业务允许的情况下 把大事务拆小
在同一事务中 尽可能一次性锁定所有需要的资源 减少死锁的概率
隔离级别 避免死锁可以使用read commit
添加合理的索引可以减少死锁的概率
乐观锁 不会有任何提示 只是数据不能写入 数据提交更新时 进行校验 发生冲突 数据不生效 没用其他的报错或卡停
在表中配置一个version字段 可以自增 通过自增校验查看数据是否冲突 通过时间戳查看是否冲突