目录
大家好,今天给大家绍一下mysql索引和事务
索引是一种特殊的文件,包含着对数据表中的所有记录的引用指针。可以对表中的一列或者多列创建索引,并指定索引的类型,每一种索引都有各自的数据结构实现。
要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:
满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。 反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。
MySQL支持多种存储引擎,每种引擎都有其自己的特点和适用场景。以下是一些常见的MySQL存储引擎:
InnoDB:InnoDB是MySQL的默认存储引擎,它支持事务、行级锁定、外键约束等特性,适合于需要强大事务支持和并发控制的应用。
MyISAM:MyISAM是MySQL的另一种存储引擎,它不支持事务和行级锁定,但在读密集型应用中性能较好,适合用于数据仓库和日志等应用。
MEMORY:MEMORY存储引擎将数据存储在内存中,适合用于临时表和缓存等场景,具有快速访问速度。
NDB Cluster:NDB Cluster是MySQL的集群存储引擎,适合于高可用性和高性能的分布式数据库系统。
ARCHIVE:ARCHIVE存储引擎适合于需要高压缩比和低写入频率的存档数据。
存储引擎是mysql内部的一个模块,存储引擎模块提供了很多版本的实现,Innodb是当前最常用的存储引擎。
为什么Innodb是默认的存储引擎? 这取决于其内部的数据结构 ==> B+树
?为什么B+树适合用作索引底层的数据结构来使用?
相比大家学过的数据结构也不少,在这么多的数据结构中适合进行查询并且性能相对较好的有
(哈希,红黑,B树) 其他的数据结构要么不适合进行查找或者就是效率上不是那么的好,像是平衡树
虽然查询的速度也是挺快的但是在插入数据的时候需要进行大量的旋转,效率自然而然的就下来了
1.为什么不使用红黑树?
内存占用: 红黑树每个节点包含的信息更多(包括颜色信息、指向父节点的指针等) 如果内存有限,需要存储的数据量又非常的大,这个是否只能将数据存入磁盘中,如果进行查询的话,需要进行大量的磁盘IO非常消耗时间
数据聚集性: 红黑树中数据直接没有关联性,不利于范围查询和顺序遍历
2.为什么不使用哈希表?
哈希表的效率不必多说O(1)的时间复杂度,基本上可以说吊打一切了,但是它有一个致命的缺陷,无法进行范围查询! 这限制了哈希表的应用场景
MEMORY存储引擎一般用于临时表和缓存等场景,这些场景下通常对于快速的数据访问更为重要,而不需要支持复杂的数据操作。因此,选择哈希数据结构可以更好地满足这些场景下的需求。
3.为什么不使用B树?
不稳定性: 对于B树来说,如果要查询的元素在根节点或者层次比较高的节点,可以做到很快的拿到元素, 但是如果要查询的节点在叶子节点,时间相对而言就会更多一些
稳定性对于数据库来说还是很重要的,在生活中也是很重要的,高考的摸底考试和正式高考,相差如果太大就直接g了
如果说没有B+树的话,B树也是算得上比较好的一种索引底层数据结构了,但是B+树是为索引而生的
4.为什么使用B+树?
1) 首先B+树起源于B树,是一颗N叉搜索树.树的高度是有限的,可以有效的降低磁盘IO的次数
2) 非常擅长范围查询,因为所有的值都存储在叶子结点
3) 稳定性好,所有的查询都是要落到叶子结点上的,查询和查询之间的时间开销是稳定的,不会出现B树的不稳定情况(三模600 高考500)
4) 由于叶子结点是全集,非叶子节点上只存储一个用来排序的key,数据库是按行组织数据的,创建索引的时候是针对一列进行创建,这就导致非叶子节点根本占不了多少空间,因为它存储的不过是一个用来排序的key(比如一个id) 这部分内容可以直接缓存到内存中
(硬盘上则是存储叶子结点和非叶子结点,在查询的时候可以把非叶子结点的内容加载到内存中,整个查询过程就是在内存中进行,进一步的减少了磁盘IO的次数)
事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。 在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。
start transaction??rollback/commit 已经过时了,在现在的开发中事务被层层封装,这种最原始的在sql中穿插的命令已经用不到,不知道的也不必再了解.知道的也可以选择性遗忘
开发中经常会遇到一些需要一气呵成的操作,即必须是同时成功或者是同时失败,这种操作业内称之为原子操作 ,为什么叫原子操作? 这是早期的一个错误观点被沿用至今(也没有修改的必要), 在人类的发展认知中曾经存在过 "原子是不可分割的最小单位" 这一说法,这一个错误观点就诞生了事务的四大特征之一 - 原子性中原子两字
举个例子:? 张三给李四转账500元 首先张三的账户减去500 然后李四的账户加上500
这个时候如果张三的账户减少500,但是李四的账户并没有加上500,这个时候问题可就大了
所以事务的原子性是不可或缺的!
原子性: 事务要么同事成功,要么同时失败
再来思考一个问题,有没有一种可能,张三账户上减500元 李四账户上加50000000元,这个时候如果处理不好,那可就是"刑"了,有没有可能出现这么一个情况呢? 早期我不知道,但是有事务的一致性为我保驾护航,我想问题应该不大
一致性: 数据库操作前后,数据要能对得上
持久性(Durability):一旦事务提交,其所做的修改将会永久保存在数据库中,即使系统发生故障,这些修改也不会丢失。
隔离性: 多个事务并发执行时,各个事务的操作互不干扰。
并发执行时非常的常见的,mysql是一个客户端服务器结构的程序,一个服务器可以给多个客户端提供服务,如果多个客户端同时访问数据库,在客户端1提交的事务执行到一半时,客户端2提交的事务也过来了,这个时候数据库服务器需要同时并发处理这两个事务,这个时候我们应该怎么去处理呢?
如果我们希望数据库服务器的执行效率提高,这个时候就需要提高并发率,但是提高并发率可能会出现数据错误的情况,具体情况如下
脏读: 一个事务A正在写数据的的过程中,另一个事务B读取了同一个数据,接下来A又修改了数据,导致B之前读到的数据,是一个无效的数据/中间的数据(脏数据)
如何解决??
注意上面的措词,?写数据的过程中,另一个事务读取了同一个数据
如果在一个事务写的过程中,另一个或者多个事务无法去读取该数据,那么问题不就完美解决了吗?
这个操作称之为 "写加锁"
并发性降低了,隔离性提高了,效率降低了,数据准确性提高了
不可重复读: 并发执行事务的过程中如果事务A在多次读取同一个数据的时候,出现不同的情况,这就是不可重复读,意味着在A两次读取数据之间,有一个数据B修改并提交了数据
如何解决?
注意措词?A两次读取数据之间,有一个数据B修改并提交了数据 如果在A读取数据的过程中,其他的事务无法读取该数据不就完美解决了吗?
这个操作我们称之为 - "读"加锁
并发程度进一步降低,隔离性提高,效率降低,数据的准确性提高
幻读: 一个事务A在执行过程中,两次的读取操作,数据内容虽然没有改变,但是结果集变了,这种称之为 "幻读"
比如我在读A文件,你不能写A文件,但是你可以写其他的文件,这样我在读取的时候,读取的内容虽然没有变,但是结果集发生了改变
如何解决?
引入串行化方式解决幻读,什么是串行化? 完全没有并发 我在读A文件的时候,其他人什么也不能干
数据绝对安全,效率绝对低的离谱!
总结一波
事务的四大特性通常指的是ACID特性,即:
原子性(Atomicity):事务是一个不可分割的工作单位,要么全部执行,要么全部不执行。在事务执行过程中,如果发生错误或者中断,系统会将所有操作回滚到事务开始前的状态,保证数据的一致性。
一致性(Consistency):事务执行前后,数据库的完整性约束没有被破坏。即使在事务执行过程中发生了错误,系统也会保证数据库从一个一致的状态转移到另一个一致的状态。
隔离性(Isolation):多个事务并发执行时,各个事务的操作互不干扰。每个事务的操作对其他事务是隔离的,因此不会出现数据争用、幻读等问题。
持久性(Durability):一旦事务提交,其所做的修改将会永久保存在数据库中,即使系统发生故障,这些修改也不会丢失。
这些特性确保了事务在数据库系统中的可靠性和一致性,是数据库设计和管理中非常重要的概念。
常见的事务隔离级别包括:
读未提交(Read Uncommitted):允许一个事务读取另一个事务未提交的数据。这是最低的隔离级别,可能会导致脏读、不可重复读和幻读的问题。
读提交(Read Committed):保证一个事务不会读取另一个事务未提交的数据。这个级别可以避免脏读,但仍然可能出现不可重复读和幻读的问题。
可重复读(Repeatable Read):保证一个事务不会读取到另一个事务已提交的修改,从而避免了不可重复读的问题。但仍然可能出现幻读的问题。(Innodb默认隔离级别)
串行化(Serializable):最高的隔离级别,通过强制事务串行执行来避免脏读、不可重复读和幻读。这个级别能够确保事务之间的完全隔离,但会导致性能下降。
这篇博客主要介绍了mysql数据库索引和事务的相关内容,下一篇博客见!