MySQL---索引、事务
目录
索引
1.1 概念
1.2 作用
1.3 使用场景
1.4 使用
事务
定义:
事务的关键特性 (ACID ):
脏读
不可重复读
幻读
标准隔离级别
索引
1.1 概念
索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。
1.2 作用
数据库中的表、数据、索引之间的关系,类似于书架上的图书、书籍内容和书籍目录的关系。 索引所起的作用类似书籍目录,可用于快速定位、检索数据。索引对于提高数据库的性能有很大的帮助。
1.3 使用场景
要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:
- 数据量较大,且经常对这些列进行条件查询。
- 该数据库表的插入操作,及对这些列的修改操作频率较低。
- 索引会占用额外的磁盘空间。
满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。反之:如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。
1.4 使用
- 查看索引
show index from 表名;
当表中存在主键的时候,内部就会自带给这个列来创建索引
- 创建索引
create index 索引名 on 表名(字段名);

- 删除索引
drop index 索引名 on 表名;
- 创建索引也可能是危险的操作!
- 如果表是空的,或者表中的数据不多,创建索引就没有问题~
- 如果表非空的,并且包含非常多的数据,创建索引,会引起非常大规模的硬盘IO操作!
- 删除索引,只是针对手动创建的索引,自带生成的索引是不能被删除的.
事务
定义:
MySQL 中的事务是指一组数据库操作(例如插入、更新、删除)被当作一个不可分割的原子单元来执行。事务的核心目的是确保数据库从一个一致的状态转换到另一个一致的状态,即使在执行过程中发生错误或中断。
本质:就是为了把多个操作打包成一个操作来完成的(让这多个操作要么全部能执行成功,要么就一个都不执行!!!)
“一个都不执行” 不是真的没有执行.
执行成不成功,得执行后才知道
假设事务有3给操作~~
先执行1
再执行2
最后执行3
真正执行之前,是不知道1 2 3 哪一步会失败~~~
如果是执行到中间出了差错,就需要自动的把前面已经执行的操作,进行还原操作~~还原回最初没有执行的模样~
本质上,这里的“一个都不执行”不是真的没有执行~看起来就和没有执行一样~~ (回滚[rollback])
回滚是怎么实现的?只要把事务中执行的每一个操作,都记录下来(通过特点的日志),如果需要回滚,就直接按照之前操作的“逆操作”来执行就可以了~~
上一个操作如果是插入,逆操作就是删除~
上一个操作如果是删除,逆操作就是插入~
举例子:银行转账
1)给A的账户-500
2)给B的账户+500
在执行第二步的过程中,如果程序崩溃了,此时就需要对第一步进行回滚~
数据库就会自动的把第一步操作的修改给还原回去~~如果数据库挂了?数据库服务器重启了?
因为是通过日志,来记录事务执行的中间过程的,日志中的数据是始终在硬盘上存在的
即使是数据量服务器重启~就会在重新启动之后,针对之前没有回滚完的情况继续进行处理~
-- 1. 显式开始一个事务 start transaction;-- 2. 执行扣款操作 (从A扣200) update accounts set balance = balance - 500 where account_id = 'A';-- 3. 执行加款操作 (给B加200) update accounts set balance = balance + 500 where account_id = 'B';-- 4. 如果上面两个UPDATE都执行成功,没有任何错误,则提交事务,使更改永久生效 commit;-- 如果在start transaction 和 commit之间发生了任何错误(比如第二步失败,或者系统崩溃): -- 可以显式执行 rollback; 或者系统会自动回滚整个事务 -- rollback会撤销这个事务内所有尚未提交的更改,就像这个事务从来没执行过一样。
一个事务务必要以这俩个操作(commit、rollback)结尾~
如果没有这俩操作,接下来的各种sql操作都会被认为是事务的一部分.
事务的关键特性 (ACID ):
-
原子性 (Atomicity):事务中的所有操作要么全部成功,要么全部失败回滚。不存在部分执行的情况。
-
一致性 (Consistency):事务执行前,和事务执行之后,数据能够对上,数据不能够太离谱。
-
持久性 (Durability):一旦事务成功提交,它对数据库的修改就是永久性的(最终写在硬盘上),一旦事务执行成功了,这里的索引操作产生的修改,都是写到硬盘里的。
-
隔离性 (Isolation):并发执行的事务之间是相互隔离的。会在 执行效率 和 数据可靠 直接做出权衡的~~ “隔离” 描述的是同时执行的事务之间,互相的影响~~ 隔离性越高,并发性就越低,数据就越可靠,性能就越低~~
脏读
在大学期间上课,老师会写一些代码(都是老师提前写好的)
比如说,专业课老师今天要讲类和对象,写了一个class Student,这里包含一个String name,String gender......
在老师写代码的过程中,我抬头看了投影仪,发现代码里写的内容和课本上的例题内容一样,我就打开手机,带上耳机听着音乐,玩上一把金铲铲,可当老师将例题讲一半的时候将数据改了,改成其他样子,这个时候,我之前读到的数据就是一个临时的数据~不是最终的结果~~ ,这个临时的数据也就被成为“脏”数据。
然后解决脏读问题?
给 “写” 操作加锁,一个事务A写的时候,其他事务B就不能读了,直到A事务写完数据,提交事务,其他的事务B才能读取数据~~
对于上述例子,老师把课程录制下来,发到学习通里面,我下课再去看视频,这个数据就是最终数据,不是脏数据了。
引入了写加锁,降低了两个事务之间的并发性,提高了隔离性,降低了效率,使数据更加准确。
不可重复读
老师把写的代码上传到学习通后,我们再去读~~
老师写完代码后,提交~~我们去读,在读取的规程中,老师发现其中有个代码出现错误进行修改(相当于另一个事务),修改完成后,再一个提交~~导致我们在学习通上读的时候,代码突然变样了~~
就是在一个读取数据的事务中,可能涉及到多次读操作~~多个读操作读到的数据不一样
如何解决不可重复读?
给 读操作 加锁呗~~
给写操作加锁的意思,是在我写的时候,别人不能读~~(除非我写完提交,别人才能读),此时别人读的过程中,我还可以在开启一个事务来写,第二个事务提交前,其他读事务读到的都是旧版数据,第二个事务提交后,别人在读读到的就是新版数据,给读操作加锁,就是别人读的时候,我就不能写了~
并发程度有进一步降低了~~执行效率降低了,隔离性进一步提高了,数据可靠性更高了~~
幻读
老师在写代码的时候,给我们说:
- 写加锁,我写的时候,提交之前,同学不能看
- 读加锁,同学读的时候,我不能修改代码
老师不修改我们正在读的代码,创建了一个新的类,进行编写~~
这样导致的结果,我们正在读的时候,读着,读着,虽然class Student 代码没变,突然又冒出一个class Teacher
一个事务在多次读的过程中,虽然读到的数据是一样的,但是结果集不同~
比如说,第一次读的是10条记录,第二次读的是11条记录,11条记录的前10条和之前的10条记录一模一样,就是多出一条记录~~(可以看作是不可重复读的特殊情况)
解决幻读的办法只有一个,串行化~彻底放弃并发执行事务,所有的事务都是一个挨一个的串行执行(执行完一个事务,在执行下一个事务) 这个时候:并发性最低的,隔离性最高的,效率最低的,数据最可靠性的。
标准隔离级别
MySQL 支持四种标准隔离级别,按隔离强度从低到高排列如下:
隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
---|---|---|---|---|
RU--READ UNCOMMITTED(允许读已提交的数据) | 可能发生 | 可能发生 | 可能发生 | 最高 |
RC---READ COMMITTED(允许读取已经提交的数据(给写加锁了)) | 避免 | 可能发生 | 可能发生 | 较高 |
RR---REPEATABLE READ(可以重复读数据,读写操作都加锁---默认的) | 避免 | 避免 | 可能发生 | 中等 |
SERIALIZABLE(事务彻底串行执行) | 避免 | 避免 | 避免 | 最低 |
MySQL 在 REPEATABLE READ
下通过 MVCC(多版本并发控制) 和 间隙锁 有效减少了幻读发生概率,因此大多数场景使用默认级别即可满足需求。
-------------------------------到此结束------------------------------------------------------------------