数据库概念学习

本文探讨了MySQL的默认隔离级别、事务特性(原子性、一致性、隔离性、持久性),以及索引结构(B+树、哈希索引和全文索引)。还介绍了分库分表带来的挑战和解决方案,如分布式事务和数据处理问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. mysql默认的事物级别
MySQL 默认的隔离级别是可重复读(REPEATABLE READ)。
PostgreSQL 中,默认的隔离级别是读已提交(READ COMMITTED)

可重复读隔离级别是 MySQL 的默认隔离级别,它具有以下特点:

事务读取的数据集是一个一致性视图(consistent snapshot),即事务开始时刻的数据状态。在同一事务中,无论其他事务对数据的修改如何,事务始终看到一致的数据快照。

事务期间读取的数据不会受到其他并发事务的修改影响。即使其他事务对数据进行了修改,事务内部仍然能够读取到最初一致性视图中的数据。

事务在提交之前对数据的修改对其他事务是不可见的。只有当事务提交后,其他事务才能看到该事务所做的修改。

可重复读隔离级别提供了较高的隔离性和数据一致性,适用于大多数应用场景。然而,由于事务期间持有锁的时间较长,可能导致锁竞争和并发性能下降。如果应用需要更高的并发性能,可以考虑将隔离级别调整为读已提交(READ COMMITTED)。

2. mysql的索引结构
MySQL 使用多种索引结构来支持高效的数据检索,其中最常用的索引结构是B+树索引。下面是 MySQL 中常见的索引结构:

B+树索引:B+树索引是 MySQL 最常用的索引结构。B+树是一种平衡树结构,它具有以下特点:

支持快速的索引扫描:B+ 树索引结构具有良好的平衡性和高度的平均查询性能。在 B+ 树中,从根节点到叶子节点的路径长度相等或相差不大,这使得索引扫描的平均时间复杂度为 O(log n),其中 n 是索引中的键值对数量。
所有数据都存储在叶子节点上,非叶子节点仅用于索引和导航。
范围查询和排序性能优化 叶子节点按照键值的顺序形成一个有序链表,可以支持范围查询。
B+树索引适用于等值查询和范围查询,并且对于大部分数据库工作负载都能提供高效的性能。
哈希索引:哈希索引是基于哈希表实现的索引结构。哈希索引具有以下特点:

使用哈希算法将键值映射到哈希表中的桶(bucket)。
哈希索引适用于等值查询,但不支持范围查询。
哈希索引在内存中进行查找,查询速度非常快,但在磁盘上的存储和更新操作相对较慢。
全文索引:全文索引是用于全文搜索的索引结构,用于在文本数据中进行关键字搜索。全文索引具有以下特点:

使用特殊的算法和数据结构来构建索引,以支持文本匹配和搜索。
全文索引适用于模糊搜索和自然语言查询。
MySQL 提供了全文索引的支持,例如使用 InnoDB 引擎的全文索引和使用 MyISAM 引擎的全文索引。

3. 事务特性
原子性(Atomicity):一个事务中的所有操作,要么全部成功,要么失败全部回滚,不会结束在某个中间环节。原子性由undo log日志来实现
一致性(Consistency):事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。由其他三个特性及业务代码正确逻辑来实现
隔离性((Isolation):一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。隔离性由MySQL各种锁以及MVCC机制来实现
持久性(Durable):一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的,即使系统故障也不会丢失。持久性由redo log日志来实现

4. 事务的特性如何保证
原子性
原子性是由undo log日志保证的,它记录了需要回滚的日志信息,也就是说我们的事务还没提交需要回滚,那么事务回滚就是根据undo log日志来撤销已经执行成功的SQL。
undo log其实就是SQL的反向执行,它记录了反向执行的SQL语句,把正向语句回滚回去。

一致性
一致性是ACID的目的,也就是说,只需要保证原子性、隔离性、持久性,自然也就保证了数据的一致性。比如说,我们的ID在数据库中是唯一的,此时插入了一个唯一ID,数据库会给我们做一个检查,告诉咱们是否发生了主键冲突,如果主键冲突数据就无法插入。
另一部分是业务数据的一致性,这需要程序代码来保证。比如说转账这个场景,假设我要转账100元出去,实际上数据库中只有90元,那这时候就不应该转账成功,这种情况通过数据库是无法保证的,只能由程序来保证。
因此一致性是由其它三大特性来保证,而业务一致性由程序代码保证

隔离性
在MySQL中隔离性是通过MVCC多版本并发控制机制来保证的。
多版本并发控制:读取数据时通过一种类似快照的方式将数据保存下来,这样读锁和写锁就不冲突了,不同事务的session会看到自己特定版本的数据,也就是版本链,通过版本链的概念来达到读和写能够并发进行。
MVCC只在READ COMMITTED(已提交读)和REPEATABLE READ(可重复读)两个隔离级别下工作,其他两个隔离级别和MVCC不兼容,这是因为READ UNCOMMITTED(读未提交)总是读取最新的数据行,而不是符合当前事务版本的数据行,而ZERIALIZABLE(串行化)则会对所有读取的行都加锁,MVCC就没有意义了。
在MySQL的InnoDB下,聚簇索引记录中有两个必要的隐藏列:
trx_id:它用来存储每次对某条聚簇索引记录进行修改时的事务ID,这个事务ID由MySQL分配。
roll_pointer:每次对哪条聚簇索引记录有修改的时候,都会把老版本写入undo日志中,这个roll_pointer就是存了一个指针,它指向这条聚簇索引记录的上一个版本的位置,通过它来获得上一个版本的记录信息(注意插入操作的undo日志没有这个属性,因为它没有老版本)。
已提交读和可重复读的区别就在于它们生成ReadView的策略不同。
已提交读隔离级别下的事务在每次查询的开始都会生成一个独立的ReadView,也就是说我每次select查出来的ReadView都会重新生成,所以ReadView可能会不一样,就是说读到的数据就会不一样;
而可重复读隔离级别则在第一次读的时候生成一个ReadView,之后的读都复用之前的ReadView,每次select查询都是一样的。

持久性
持久性意味着事务操作最终要持久化到数据库中,持久性是由 内存+redo log来保证的,InnoDB在修改数据的时候,同时在内存和redo log记录这次操作,宕机的时候可以从redo log中恢复数据。

4. 隔离级别
InnoDB引擎定义了四种隔离级别,级别越高事务隔离性越好,但性能就越低
read uncommit(读未提交),事务A读取到了事务B已经修改但尚未提交的数据
read commit(读已提交):Oracle和SQL Server的默认隔离级别,一个事务只能看见已经提交事务所做的改变
repeatable read(可重复读):MySQL的默认隔离级别,无论事务B如何修改数据,事务A内部相同查询语句在不同时刻查询出来的结果都是一致的,即在第一次查询之后就不会发生变化(除非事务A更新了这行数据,由快照读变为当前读)
serializable(串行化) :所有事务对同一条数据的读和写只允许串行执行,解决了脏读、不可重复读、幻读的问题

5 事务并发遇到的问题
脏写(Dirty Write):Session A修改了Session B修改过但尚未提交的数据
脏读(Dirty Read):Session A读取到了Session B已经修改但尚未提交的数据
不可重复读(Non-Repeatable Read):Session A内部的相同查询语句在不同时刻读出的结果不一致,不符合隔离性
幻读(Phantom):Session A读取到了Session B提交的新增数据,不符合隔离性

6. drop,truncate,delete区别
在这里插入图片描述
7. DDL DML区别
数据定义语言用于对数据库和表进行创建、修改和删除,即DDL包括CREATE、ALTER、DROP等语句。
数据操纵语句是用于向表中插入记录、修改记录以及删除记录的语句,即数据操作语句DML包括INSERT、UPDATE、DELETE等语句

8. char定长的, varchar不定长
1、最大长度:
char最大长度是255字符,varchar最大长度是65535个字节。
2、定长:
char是定长的,不足的部分用隐藏空格填充,varchar是不定长的。
3、空间使用:
char会浪费空间,varchar会更加节省空间。
4、查找效率:
char查找效率会很高,varchar查找效率会更低。
5、尾部空格:
char插入时可省略,vaechar插入时不会省略,查找时省略。

9.什么是分库分表
分库:就是一个数据库分成多个数据库,部署到不同机器。
分表:就是一个数据库表分成多个表。

10 为什么需要分库呢?

如果业务量剧增,数据库可能会出现性能瓶颈,这时候我们就需要考虑拆分数据库。从这几方面来看:
磁盘存储
业务量剧增,MySQL单机磁盘容量会撑爆,拆成多个数据库,磁盘使用率大大降低。
并发连接支撑
我们知道数据库连接是有限的。在高并发的场景下,大量请求访问数据库,MySQL单机是扛不住的!当前非常火的微服务架构出现,就是为了应对高并发。它把订单、用户、商品等不同模块,拆分成多个应用,并且把单个数据库也拆分成多个不同功能模块的数据库(订单库、用户库、商品库),以分担读写压力。

11. 分库分表会导致哪些问题
事务问题
跨库关联
排序问题
分页问题
分布式ID
5.1 事务问题
分库分表后,假设两个表在不同的数据库,那么本地事务已经无效啦,需要使用分布式事务了。
5.2 跨库关联
跨节点Join的问题:解决这一问题可以分两次查询实现
5.3 排序问题
跨节点的count,order by,group by以及聚合函数等问题:可以分别在各个节点上得到结果后在应用程序端进行合并。
5.4 分页问题
方案1:在个节点查到对应结果后,在代码端汇聚再分页。
方案2:把分页交给前端,前端传来pageSize和pageNo,在各个数据库节点都执行分页,然后汇聚总数量前端。这样缺点就是会造成空查,如果分页需要排序,也不好搞。
5.5 分布式ID
据库被切分后,不能再依赖数据库自身的主键生成机制啦,最简单可以考虑UUID,或者使用雪花算法生成分布式ID。

参考文章:
MySQL事务隔离级别与锁机制(一) https://zhuanlan.zhihu.com/p/591676550?utm_id=0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值