I.执行计划:
**什么是:**在sql语句执行的过程中,保存的一些数据信息,可以通过这些数据分析sql语句
**作用:**分析sql执行情况,索引使用和查询条数
使用:
explain select name from table where name='zhangsan'
II.索引:
什么是索引:
索引是加速对表数据检索的一种数据结构,像目录一样,存储数据的信息。
索引的分类
**聚簇索引:**存储整张表的数据。在建表时,会默认将主键作为聚簇索引,没有指定主键,会默认将不为null的唯一索引作为主键索引,如果没有索引,则会将6字节的ROWID作为聚簇索引。
**主键索引:**保证数据的唯一性,在创建表时指定主键,会默认为唯一索引,主键索引不可以有空值。
**二级索引:**只存了主键值
**辅助索引:**只存储了每个节点的索引值和页签,里面存的是数据的主键地址
**唯一索引:**唯一索引和普通索引一样存主键地址,但可以有一个空值。
**覆盖索引:**SQL语句中的查询列都在索引中,不用回表查询,就是索引覆盖。
**索引下推:**是指当查询条件中包含复合索引时,会先通过索引进行过滤,再通过联合索引进行再次过滤,减少查到无用数据,浪费资源
select * from t_user where name like 王% and age >10;(name,age)联合索引
不使用索引下推:
1.先根据name找到对应数据的聚簇索引,
2.再根据id进行回表查询,并将数据返回给server层
3.server层再进行age过滤
使用索引下推:
1.先根据name找到对应数据信息
2.再根据联合索引种age列进行过滤判断
3.再返回给server层
**覆盖索引:**SQL查询条件需要多个字段判断和等值判断时,需要使用联合索引。遵循最左匹配原则。
**联合索引:**按顺序查询,根据前一个环境在进行查询。使用复合索引可以直接在聚簇索引拿到数据避免回表。
**最左匹配原则:**联合索引的key为{1,2,3},查询只能按照123,12,【13等同于1】,、不能跳级。可以用 like ‘张%’ ,这样可以找到,不能用’%3’
**全文索引:**模糊查询在使用 like = %zhang% 查询时,索引会失效。使用全文索引可以解决问题,原理通过分词器,
**外键:**保持数据完整性,外键的值只能来源于外键表,当外键表数据删除时,外键的值就为null
回表
这就是通常所说的回表或者二次查询:使用聚集索引查询可以直接定位到记录,而普通索引通常需要扫描两遍索引树,即先通过普通索引定位到主键值,在通过聚集索引定位到行记录,这就是所谓的回表查询,它的性能比扫描一遍索引树低。
索引维护
当一条数据插入后,索引页满了,就需要重新申请。尽量使用自增id做为主键索引,这样每次新增只需要获取最大值,并在最后面加上。最后只会影响父节点。不会对之前的索引造成影响。
索引失效:
模型数空运最快
模糊匹配,数据类型错误,函数运算,空值,运算,最左匹配,快速查询
III.锁:
0.锁:Innodb的锁是基于索引实现的,当SQL命中索引之后,就会触发行锁,当未命中索引,就会触发表锁,走全表扫描。
1.全局锁:锁整个数据库,让整库只读 。但客户端出现问题,会自动释放锁。用set global readonly=true客户端出现问题,不会释放锁。
Flush tables with read lock
2.表锁:不走索引时,会触发表锁,锁定整张表,走全表扫描。
3.行锁:走索引时,触发行锁,锁定某一行数据。InnoDB 通过给索引上的索引记录加锁的方式实现行级锁
4.共享锁(S锁):事务A给数据加上共享锁之后,数据不可被修改,其他事务只能加共享锁。不能加排他锁。
Lock in share MODE
5.排他锁(X锁):事务A给数据加上排他锁之后,只能由事务A进行读写,其他事务只能等待。
FOR UPDATE
6.意向锁:意向锁是加在表层的一种锁,用于提高加锁效率,事务A给表的某一行加了行锁,当事务A需要给表加锁时,如果无法获取意向锁,则只能等待。
7.意向共享锁(IS):
IS : lock tables t read;
IX : lock tables t write;
事务添加for update锁,表就会有IX锁,当其他事务想加锁就不用一行一行判断,直接就会阻塞。
事务添加lock in share mode ,当其它事务要给表加非S锁时,就会阻塞。
8.间隙锁:普通查询,唯一索引没有值时,会锁定范围内的空隙,即使索引id不存在,防止幻读。
9.临间锁:只与非唯一索引列有关,锁定左开右闭区间
死锁:互请不环
互斥条件:当前资源独占,其他需要当前资源就得阻塞等待
请求和保持条件:进程每次申请它所需要的一部分资源,在申请新的资源的同时,继续占用已分配到的资源。
不可剥夺条件:进程为执行完,不可被剥夺。
循环等待条件:互相请求的进程形成一个循环等待前者的资源。
.乐观锁:维护一个版本号,每次修改都会对版本号进行更新,其他操作,在获取到的版本号和之前的不一致时,就会回滚。
悲观锁:每次操作都会加锁,其他线程只能读。
IV.存储引擎:
区别
区别 | InnoDB | InnoDB |
---|---|---|
存储结构 | 都是b+树聚簇索引 | 非聚簇索引 |
外键 | 支持外键 | 不支持外键 |
事务 | 支持事务 | 不支持事务 |
读写 | 大量写 | 大量读 |
选择
- 需要外键吗?选择 InnoDB。
- 需要事务支持吗?选择 InnoDB。
- 需要全文索引吗?在5.7及以后版本,都可选,优先考虑 InnoDB + Sphinx。
- 绝大多数都是读操作,可以考虑 MyISAM。
- 数据量大,选择 InnoDB,因为其支持事务处理和故障恢复。MyISAM 可能需要几小时或几天来恢复,InnoDB 只需要几分钟。
V.数据结构:
使用的数据结构:b+树
- B树每个节点中不仅包含数据的key值,还有data值。而每一个页的存储空间是有限的,如果data数据较大时将会导致每个节点能存储的key的数量很小,要保存同样多的key,就需要增加树的高度。树的高度每增加一层,查询时的磁盘I/O次数就增加一次,进而影响查询效率。而在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+树的高度。
- B+树的叶子节点上有指针进行相连,因此在做数据遍历的时候,只需要对叶子节点进行遍历即可,这个特性使得B+树非常适合做范围查询。
执行
原因:
(49条消息) 从一条查询sql执行过程了解mysql索引_查询sql索引执行过程 ex_java排坑日记的博客-CSDN博客
全文索引:模糊查询在使用 like = %zhang% 查询时,索引会失效。使用全文索引可以解决问题,原理通过分词器,
索引覆盖
外键:
外键会导致表之间强耦合,update/delete操作也会影响性能,在高并发情况下容易产生数据库的死锁
VI.建表优化
1.字段设计
1.除了VARVHAR类型限制大小是有用的,其他都是固定的。
2.int类型可以用bigint和tinyint来表示
3.时间类型的数据中,datetime和timestamp都可以显示时分秒,timestamp占用内用更小
4.数据库的数据存储时是在一行的,行数据分为信息和真实数据,信息中有可变长字段读取长度2字节和空值列表1字节
2.分库分表
分表:
垂直分表:将不常用的大字段数据(如text/blob/longtext)拆分出去,并与zhubiaoid关联,当需要的时候再调用。
水平分表:将200万的数据拆分,使用表ID(取模+1)需要拆的表数量拆分存到t1,t2,t3,t4表中,并额外建一张自增ID表,来提供自增ID,增删改查都是通过对id进行取模操作。
insert into uid_temp values(null); //返回ID值,再进行插入
分库:
垂直分库:将不同业务类型的数据库表,分在不同的数据库中,可以缓解数据库磁盘压力
水平分库:每个可都有相同的表,将表数据通过(range 或 取模 Hash)到不同的库中的表里。大大缓解了IO,连接数,性能瓶颈。
数据迁移:
**问题:**分表之后,由于数据量大,直接迁移耗时太久,会对业务造成很大的影响。
**解决:**在业务上加一层逻辑判断路由:
当用户操作为新增时,将新数据计算后存入分表。
当用户操作为查询时,如果数据在原表,就从原表查询返回。直到所有的操作都是对于分表时,在进行数据迁移。
归档:
数据库归档的概念本身十分简单,把一条记录从生产数据库插入到历史数据库中,然后把该条记录在生产数据库中删除就实现了数据库归档的功能。这条数据应该满足长时间不活跃。
什么时候不要用索引
- 索引是怎么提高查询效率的?可以为了提高查询效率增加索引么?
- mysql索引系统采用的数据结构是什么?
- 为什么要使用B+树?
- 聚集索引相对于非聚集索引的区别?
- 什么是回表?
- 什么是索引覆盖?
- 什么是最左匹配原则?
- 索引失效场景有哪些,如何避免?
VII.数据类型
VIII.优化流程
1.优化思路
1.使用show status 查看sql的执行频率
2.查看慢查询日志定位慢查询日志
3.使用explain分析sql语句的执行情况
2.SQL优化方案
1.避免是以哦那个select * ,避免mysql需要进行将 *转为所有的字段的过程。
2.尽量使用索引进行查询
3.查询尽量小表驱动大表,这样小表一次就可以加载完,避免join buffer 的多次加载。
Limit优化
Limit很大的数据,但是需要返回的数据很少时。可以在where后面加上一页的索引id,然后再limit
//前提id是有序的
select * from table where id >100000 limit 10
select * from table order by id between 100000 and 100010
select * from table order by id limit 100000,10
In和Exists区别
In是通过子查询的数据和主查询做笛卡尔积,再通过条件进行筛选。
exists是通过先做主查询,得到主查询结果集,再使用子查询语句去一一比对。
Count
**count(字段):**不会统计null值
Count(*): 查询数据再做函数
**count(1):**查询表里第一个
总结:
主多子少IN,主少子多Exists
1.回滚:就是在日志中反向update
2.两类丢失:解决办法是加锁,加乐观锁
第一类更新丢失:回滚丢失,事务B对同一条数据进行更新,事务A已提交数据,事务B回滚后,事务A提交丢失。
A | B | Time |
---|---|---|
开启事务 | ||
开启事务 | ||
查询余额1000 | 1 | |
查询余额 1000 | 2 | |
转入100 | 转出500 | 3 |
提交事务:余额1100 | 回滚事务 | 4 |
余额:1000 | 5 |
第二类更新丢失:更新丢失。 事务A更新,事务B更新把事务A数据覆盖。
A | B | Time |
---|---|---|
开启事务 | T1 | |
开启事务 | T2 | |
查询1000 | 查询1000 | T3 |
转入100 | T4 | |
提交事务:1100 | T5 | |
转出100 | T6 | |
提交事务:900 |
IX.日志
区别:
redolog是循环写的,binlog是追加写的。redolog有crush-safe能力,binlog只能用于归档,但是还有会有一个问题,就是写顺序的问题,这个是两阶段提交
两阶段提交:
binlog写完后,事务提交之前crush,重启之后,继续提交。
binlog未写完crush,重启之后,回滚。
redo log | bin log | undo log | |
---|---|---|---|
日志归属 | 存储引擎层,innodb专有的 | service层,所有引擎都有 | 回滚日志 |
写入方式 | 循环写入,写满就从头开始 | 追加写入,写满就新建文件 | |
适用场景 | 崩溃恢复 | 主从复制,误删恢复 | |
日志类型 | 物理 | sql |
mysql为了提高更新效率,使用了一种STEAL策略,就是允许在事务提交之前写入数据到磁盘,这时候如果事务回滚就会产生脏数据,进而引发事务隔离级别问题。这个时候就需要引入undo log。
redo log :Innodb专属,保存的是物理日志,记录了数据页的数据变更。讲更新操作,会先写入redo log 中,随后会在空闲时刻讲数据刷入磁盘
binlog :是servicr层的,保存的是逻辑日志,即sql语句。binlog只能用于归档,可以使用binlog恢复到任意备份时刻的状态。
undo log :负责记录未提交事务被写入磁盘的数据,当事务回滚或者崩溃重启时,就需要从undo中找到上条数据的回滚指针并进行回滚。Undo Log还有一个作用,就是实现多个行版本控制(MVCC),当读取的某一行被其他事务锁定时,它可以从 Undo Log 中获取该行记录以前的数据是什么,从而提供该行版本信息,让用户读取。
快照读(snapshot read):普通的 select 语句(不包括 select … lock in share mode, select … for update)
当前读(current read) :select … lock in share mode,select … for update,insert,update,delete 语句
X.隔离级别
问题:
脏读:读到STEAL机制其他事务刷入磁盘但未提交的数据,有可能回滚。
可重复读:每次读到的数据都一样
不可重复读:可能会被其他事务更新受影响。
幻读:读到其他数据插入的数据
隔离级别:
读未提交:性能最好,不加锁,连脏读都无法解决
读已提交:可以解决脏读,使用MVCC,每次读之前都会创建一份ReadView,但是每次数据都有可能不一样,可能造成幻读。
可重复读:可以解决幻读,使用MVCC,事务开启只会创建一份ReadView,保证每次数据一致。
串行化:完全解决事务影响,事务阻塞进行。
ReadView:
包含当前活跃的事务id,当前系统中最大的和最小的事务id,当前事务id。
每次先进行判断:拿当前的事务id,在当前行进行判断:先和最大事务id比较,再看最大事务id是否活跃,再判断是否要去undo中取数据。
MVCC
又叫多版本并发控制,使用这个技术可以实现数据库并发访问,解决事务隔离的读已提交,和可重复读问题。实现了数据库的读写和写读并发进行问题。
3、索引失效的几种情况?
1)like 以%开头,索引无效;当like前缀没有%,后缀有%时,索引有效;
2)or 语句前后没有同时使用索引。当 or 左右查询字段只有一个是索引,该索引失效,只有左右查询字段均为索引时,才会生效;
3)联合索引不使用第一列,索引失效;
4)数据类型出现隐式转化。如 varchar 不加单引号的话可能会自动转换为 int 型,使索引无效,产生全表扫描;
5)在索引列上使用 IS NULL 或 IS NOT NULL操作。最好给列设置默认值。
6)在索引字段上使用not,<>,!=。不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 优化方法: key<>0 改为 key>0 or key<0。
7)对索引字段进行计算操作、字段上使用函数。
8)当 MySQL 觉得全表扫描更快时(数据少);
XI.数据库语句
1.类型
DDL:数据库定义语句,
DML:数据库操作语言
DCl:数据库控制语言
DQL:数据库查询语言
2.句子
//创建表
CREATE TABLE t_user (name VARCHAR(20));
//添加字段
ALTER TABLE t_user add age int
//删除字段
ALTER TABLE T_user drop age
//修改字段
ALTER TABLE t_user modify colum age varchar(20)
//字段改名
ALTER TABLE t_user rename column name to user_Name
I.执行计划:
**什么是:**在sql语句执行的过程中,保存的一些数据信息,可以通过这些数据分析sql语句
**作用:**分析sql执行情况,索引使用和查询条数
使用:
explain select name from table where name='zhangsan'
II.索引:
什么是索引:
索引是加速对表数据检索的一种数据结构,像目录一样,存储数据的信息。
索引的分类
**聚簇索引:**存储整张表的数据。在建表时,会默认将主键作为聚簇索引,没有指定主键,会默认将不为null的唯一索引作为主键索引,如果没有索引,则会将6字节的ROWID作为聚簇索引。
**主键索引:**保证数据的唯一性,在创建表时指定主键,会默认为唯一索引,主键索引不可以有空值。
**二级索引:**只存了主键值
**辅助索引:**只存储了每个节点的索引值和页签,里面存的是数据的主键地址
**唯一索引:**唯一索引和普通索引一样存主键地址,但可以有一个空值。
**覆盖索引:**SQL语句中的查询列都在索引中,不用回表查询,就是索引覆盖。
**索引下推:**是指当查询条件中包含复合索引时,会先通过索引进行过滤,再通过联合索引进行再次过滤,减少查到无用数据,浪费资源
select * from t_user where name like 王% and age >10;(name,age)联合索引
不使用索引下推:
1.先根据name找到对应数据的聚簇索引,
2.再根据id进行回表查询,并将数据返回给server层
3.server层再进行age过滤
使用索引下推:
1.先根据name找到对应数据信息
2.再根据联合索引种age列进行过滤判断
3.再返回给server层
**覆盖索引:**SQL查询条件需要多个字段判断和等值判断时,需要使用联合索引。遵循最左匹配原则。
**联合索引:**按顺序查询,根据前一个环境在进行查询。使用复合索引可以直接在聚簇索引拿到数据避免回表。
**最左匹配原则:**联合索引的key为{1,2,3},查询只能按照123,12,【13等同于1】,、不能跳级。可以用 like ‘张%’ ,这样可以找到,不能用’%3’
**全文索引:**模糊查询在使用 like = %zhang% 查询时,索引会失效。使用全文索引可以解决问题,原理通过分词器,
**外键:**保持数据完整性,外键的值只能来源于外键表,当外键表数据删除时,外键的值就为null
回表
这就是通常所说的回表或者二次查询:使用聚集索引查询可以直接定位到记录,而普通索引通常需要扫描两遍索引树,即先通过普通索引定位到主键值,在通过聚集索引定位到行记录,这就是所谓的回表查询,它的性能比扫描一遍索引树低。
索引维护
当一条数据插入后,索引页满了,就需要重新申请。尽量使用自增id做为主键索引,这样每次新增只需要获取最大值,并在最后面加上。最后只会影响父节点。不会对之前的索引造成影响。
索引失效:
模型数空运最快
模糊匹配,数据类型错误,函数运算,空值,运算,最左匹配,快速查询
III.锁:
0.锁:Innodb的锁是基于索引实现的,当SQL命中索引之后,就会触发行锁,当未命中索引,就会触发表锁,走全表扫描。
1.全局锁:锁整个数据库,让整库只读 。但客户端出现问题,会自动释放锁。用set global readonly=true客户端出现问题,不会释放锁。
Flush tables with read lock
2.表锁:不走索引时,会触发表锁,锁定整张表,走全表扫描。
3.行锁:走索引时,触发行锁,锁定某一行数据。InnoDB 通过给索引上的索引记录加锁的方式实现行级锁
4.共享锁(S锁):事务A给数据加上共享锁之后,数据不可被修改,其他事务只能加共享锁。不能加排他锁。
Lock in share MODE
5.排他锁(X锁):事务A给数据加上排他锁之后,只能由事务A进行读写,其他事务只能等待。
FOR UPDATE
6.意向锁:意向锁是加在表层的一种锁,用于提高加锁效率,事务A给表的某一行加了行锁,当事务A需要给表加锁时,如果无法获取意向锁,则只能等待。
7.意向共享锁(IS):
IS : lock tables t read;
IX : lock tables t write;
事务添加for update锁,表就会有IX锁,当其他事务想加锁就不用一行一行判断,直接就会阻塞。
事务添加lock in share mode ,当其它事务要给表加非S锁时,就会阻塞。
8.间隙锁:普通查询,唯一索引没有值时,会锁定范围内的空隙,即使索引id不存在,防止幻读。
9.临间锁:只与非唯一索引列有关,锁定左开右闭区间
死锁:互请不环
互斥条件:当前资源独占,其他需要当前资源就得阻塞等待
请求和保持条件:进程每次申请它所需要的一部分资源,在申请新的资源的同时,继续占用已分配到的资源。
不可剥夺条件:进程为执行完,不可被剥夺。
循环等待条件:互相请求的进程形成一个循环等待前者的资源。
.乐观锁:维护一个版本号,每次修改都会对版本号进行更新,其他操作,在获取到的版本号和之前的不一致时,就会回滚。
悲观锁:每次操作都会加锁,其他线程只能读。
IV.存储引擎:
区别
区别 | InnoDB | InnoDB |
---|---|---|
存储结构 | 都是b+树聚簇索引 | 非聚簇索引 |
外键 | 支持外键 | 不支持外键 |
事务 | 支持事务 | 不支持事务 |
读写 | 大量写 | 大量读 |
选择
- 需要外键吗?选择 InnoDB。
- 需要事务支持吗?选择 InnoDB。
- 需要全文索引吗?在5.7及以后版本,都可选,优先考虑 InnoDB + Sphinx。
- 绝大多数都是读操作,可以考虑 MyISAM。
- 数据量大,选择 InnoDB,因为其支持事务处理和故障恢复。MyISAM 可能需要几小时或几天来恢复,InnoDB 只需要几分钟。
V.数据结构:
使用的数据结构:b+树
- B树每个节点中不仅包含数据的key值,还有data值。而每一个页的存储空间是有限的,如果data数据较大时将会导致每个节点能存储的key的数量很小,要保存同样多的key,就需要增加树的高度。树的高度每增加一层,查询时的磁盘I/O次数就增加一次,进而影响查询效率。而在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+树的高度。
- B+树的叶子节点上有指针进行相连,因此在做数据遍历的时候,只需要对叶子节点进行遍历即可,这个特性使得B+树非常适合做范围查询。
执行
原因:
(49条消息) 从一条查询sql执行过程了解mysql索引_查询sql索引执行过程 ex_java排坑日记的博客-CSDN博客
全文索引:模糊查询在使用 like = %zhang% 查询时,索引会失效。使用全文索引可以解决问题,原理通过分词器,
索引覆盖
外键:
外键会导致表之间强耦合,update/delete操作也会影响性能,在高并发情况下容易产生数据库的死锁
VI.建表优化
1.字段设计
1.除了VARVHAR类型限制大小是有用的,其他都是固定的。
2.int类型可以用bigint和tinyint来表示
3.时间类型的数据中,datetime和timestamp都可以显示时分秒,timestamp占用内用更小
4.数据库的数据存储时是在一行的,行数据分为信息和真实数据,信息中有可变长字段读取长度2字节和空值列表1字节
2.分库分表
分表:
垂直分表:将不常用的大字段数据(如text/blob/longtext)拆分出去,并与zhubiaoid关联,当需要的时候再调用。
水平分表:将200万的数据拆分,使用表ID(取模+1)需要拆的表数量拆分存到t1,t2,t3,t4表中,并额外建一张自增ID表,来提供自增ID,增删改查都是通过对id进行取模操作。
insert into uid_temp values(null); //返回ID值,再进行插入
分库:
垂直分库:将不同业务类型的数据库表,分在不同的数据库中,可以缓解数据库磁盘压力
水平分库:每个可都有相同的表,将表数据通过(range 或 取模 Hash)到不同的库中的表里。大大缓解了IO,连接数,性能瓶颈。
数据迁移:
**问题:**分表之后,由于数据量大,直接迁移耗时太久,会对业务造成很大的影响。
**解决:**在业务上加一层逻辑判断路由:
当用户操作为新增时,将新数据计算后存入分表。
当用户操作为查询时,如果数据在原表,就从原表查询返回。直到所有的操作都是对于分表时,在进行数据迁移。
归档:
数据库归档的概念本身十分简单,把一条记录从生产数据库插入到历史数据库中,然后把该条记录在生产数据库中删除就实现了数据库归档的功能。这条数据应该满足长时间不活跃。
什么时候不要用索引
- 索引是怎么提高查询效率的?可以为了提高查询效率增加索引么?
- mysql索引系统采用的数据结构是什么?
- 为什么要使用B+树?
- 聚集索引相对于非聚集索引的区别?
- 什么是回表?
- 什么是索引覆盖?
- 什么是最左匹配原则?
- 索引失效场景有哪些,如何避免?
VII.数据类型
VIII.优化流程
1.优化思路
1.使用show status 查看sql的执行频率
2.查看慢查询日志定位慢查询日志
3.使用explain分析sql语句的执行情况
2.SQL优化方案
1.避免是以哦那个select * ,避免mysql需要进行将 *转为所有的字段的过程。
2.尽量使用索引进行查询
3.查询尽量小表驱动大表,这样小表一次就可以加载完,避免join buffer 的多次加载。
Limit优化
Limit很大的数据,但是需要返回的数据很少时。可以在where后面加上一页的索引id,然后再limit
//前提id是有序的
select * from table where id >100000 limit 10
select * from table order by id between 100000 and 100010
select * from table order by id limit 100000,10
In和Exists区别
In是通过子查询的数据和主查询做笛卡尔积,再通过条件进行筛选。
exists是通过先做主查询,得到主查询结果集,再使用子查询语句去一一比对。
Count
**count(字段):**不会统计null值
Count(*): 查询数据再做函数
**count(1):**查询表里第一个
总结:
主多子少IN,主少子多Exists
1.回滚:就是在日志中反向update
2.两类丢失:解决办法是加锁,加乐观锁
第一类更新丢失:回滚丢失,事务B对同一条数据进行更新,事务A已提交数据,事务B回滚后,事务A提交丢失。
A | B | Time |
---|---|---|
开启事务 | ||
开启事务 | ||
查询余额1000 | 1 | |
查询余额 1000 | 2 | |
转入100 | 转出500 | 3 |
提交事务:余额1100 | 回滚事务 | 4 |
余额:1000 | 5 |
第二类更新丢失:更新丢失。 事务A更新,事务B更新把事务A数据覆盖。
A | B | Time |
---|---|---|
开启事务 | T1 | |
开启事务 | T2 | |
查询1000 | 查询1000 | T3 |
转入100 | T4 | |
提交事务:1100 | T5 | |
转出100 | T6 | |
提交事务:900 |
IX.日志
区别:
redolog是循环写的,binlog是追加写的。redolog有crush-safe能力,binlog只能用于归档,但是还有会有一个问题,就是写顺序的问题,这个是两阶段提交
两阶段提交:
binlog写完后,事务提交之前crush,重启之后,继续提交。
binlog未写完crush,重启之后,回滚。
redo log | bin log | undo log | |
---|---|---|---|
日志归属 | 存储引擎层,innodb专有的 | service层,所有引擎都有 | 回滚日志 |
写入方式 | 循环写入,写满就从头开始 | 追加写入,写满就新建文件 | |
适用场景 | 崩溃恢复 | 主从复制,误删恢复 | |
日志类型 | 物理 | sql |
mysql为了提高更新效率,使用了一种STEAL策略,就是允许在事务提交之前写入数据到磁盘,这时候如果事务回滚就会产生脏数据,进而引发事务隔离级别问题。这个时候就需要引入undo log。
redo log :Innodb专属,保存的是物理日志,记录了数据页的数据变更。讲更新操作,会先写入redo log 中,随后会在空闲时刻讲数据刷入磁盘
binlog :是servicr层的,保存的是逻辑日志,即sql语句。binlog只能用于归档,可以使用binlog恢复到任意备份时刻的状态。
undo log :负责记录未提交事务被写入磁盘的数据,当事务回滚或者崩溃重启时,就需要从undo中找到上条数据的回滚指针并进行回滚。Undo Log还有一个作用,就是实现多个行版本控制(MVCC),当读取的某一行被其他事务锁定时,它可以从 Undo Log 中获取该行记录以前的数据是什么,从而提供该行版本信息,让用户读取。
快照读(snapshot read):普通的 select 语句(不包括 select … lock in share mode, select … for update)
当前读(current read) :select … lock in share mode,select … for update,insert,update,delete 语句
X.隔离级别
问题:
脏读:读到STEAL机制其他事务刷入磁盘但未提交的数据,有可能回滚。
可重复读:每次读到的数据都一样
不可重复读:可能会被其他事务更新受影响。
幻读:读到其他数据插入的数据
隔离级别:
读未提交:性能最好,不加锁,连脏读都无法解决
读已提交:可以解决脏读,使用MVCC,每次读之前都会创建一份ReadView,但是每次数据都有可能不一样,可能造成幻读。
可重复读:可以解决幻读,使用MVCC,事务开启只会创建一份ReadView,保证每次数据一致。
串行化:完全解决事务影响,事务阻塞进行。
ReadView:
包含当前活跃的事务id,当前系统中最大的和最小的事务id,当前事务id。
每次先进行判断:拿当前的事务id,在当前行进行判断:先和最大事务id比较,再看最大事务id是否活跃,再判断是否要去undo中取数据。
MVCC
又叫多版本并发控制,使用这个技术可以实现数据库并发访问,解决事务隔离的读已提交,和可重复读问题。实现了数据库的读写和写读并发进行问题。
3、索引失效的几种情况?
1)like 以%开头,索引无效;当like前缀没有%,后缀有%时,索引有效;
2)or 语句前后没有同时使用索引。当 or 左右查询字段只有一个是索引,该索引失效,只有左右查询字段均为索引时,才会生效;
3)联合索引不使用第一列,索引失效;
4)数据类型出现隐式转化。如 varchar 不加单引号的话可能会自动转换为 int 型,使索引无效,产生全表扫描;
5)在索引列上使用 IS NULL 或 IS NOT NULL操作。最好给列设置默认值。
6)在索引字段上使用not,<>,!=。不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 优化方法: key<>0 改为 key>0 or key<0。
7)对索引字段进行计算操作、字段上使用函数。
8)当 MySQL 觉得全表扫描更快时(数据少);
XI.数据库语句
1.类型
DDL:数据库定义语句,
DML:数据库操作语言
DCl:数据库控制语言
DQL:数据库查询语言
2.句子
//创建表
CREATE TABLE t_user (name VARCHAR(20));
//添加字段
ALTER TABLE t_user add age int
//删除字段
ALTER TABLE T_user drop age
//修改字段
ALTER TABLE t_user modify colum age varchar(20)
//字段改名
ALTER TABLE t_user rename column name to user_Name