在学习到Oracle redo和undo时,涉及到很多存储结构的知识,但是网上的教程都不是很详细,就去复习了一下mysql,感觉是不是开源的问题,Mysql的社区和知识沉淀远高于Oracle, 对于初学者很友好,我想请问深入学习这些知识学要怎么去了解,不会和win一样要打入内部吧!!!(本篇文章都是主观理解,作者自己知识的梳理,错误可能有点多)
数据库数据存储是一种逻辑结构,就像链表、树、堆一样,链表使用数组开辟一块内存放指向下一个数组的指针,堆是一种完全二叉树在底层其实维护的是一个数组,数据库索引的B-树、B+树,是一种多路平衡树,降低树的高度减少OS的IO操作,加入平衡算法防止线性化,3-4的高度就能满足大部分场景。其实学的数据结构数组、链表、堆、树、图都是逻辑上的,包括做开发用到的数据结构,做一些格式处理、格式转换,现在越来越方便,除了刷算法需要自己处理,平常都是用hutool等工具包,掉包,Python更甚,没有了解过底层是怎么存放的。Linux系统万物皆文件,在文件和文件管理这方面,是如何从内存写到寄存器、磁盘上的,存储格式是怎样的,一点都不懂。todo
为什么OS块4K、Oracle块8K、Mysql页16K,兼容有什么问题吗?
OS多开辟两个内存块存呗?
这种逻辑存储结构是如何存储到操作系统的?
我们看Mysql的
Mysql存储到操作系统上面,不同的引擎略有些差异,常用的InnoDB会有三个文件存放到操作系统,分别是.frm文件、.ibd文件、ibdata 文件
.frm文件存储表的定义,即表结构,包含表名、列定义、索引定义等元数据,每个InnoDB表都有一个对应的.frm文件
.ibd文件存储表的数据和索引(如果启用了innodb_file_per_table
配置选项)包括表的数据行、主键索引、辅助索引以及MVCC(多版本并发控制)数据等
ibdata 文件存储InnoDB的系统表空间数据,包括数据字典、更改缓冲、撤销日志、锁信息等是一个共享的系统表空间文件,可能包含多个InnoDB表的数据(如果innodb_file_per_table
未启用),以及其他InnoDB内部使用的信息。通常至少有一个ibdata文件(ibdata1),但可以通过配置增加更多的ibdata文件,并设置它们的自动扩展属性。
.ibd 文件的其他辅助文件: 除了 .ibd 文件本身外,InnoDB 存储引擎还会生成一些其他辅助文件,用于支持事务、恢复和性能优化等功能。这些辅助文件包括重做日志文件(redo log)、undo 日志文件、共享表空间文件等。这些文件通常不是直接用户可见的,而是由 MySQL 引擎管理的。
参考:Chat GPT:当使用 InnoDB 存储引擎存储数据时,每个表会对应一个 .frm 文件和一个 .ibd 文件(如果启用了单独表空间模式)。除此之外,InnoDB 还会生成一些其他辅助文件,用于支持数据库的事务和恢复功能。
MySql数据在磁盘上到底是怎么存储的?被存储的数据怎么查找? - 知乎 (zhihu.com)
MySQL数据文件介绍及存放位置 - jianhong - 博客园 (cnblogs.com)
B树这种逻辑结构存储到OS上是怎么存放的?
了解一下Mysql数据页的格式从 MySQL 数据页的角度看 B+ 树_b+数 调取某页数据到内存中,是什么形式-CSDN博客,大概有7个部分:
Mysql数据行格式:
Oracle的数据行格式,在往底层了解一下就找不到资料了
MySQL创建的表查看表结构信息中,有一栏 columns,在其中我们会看到处理我们建表时指定的字段以外,还有额外的三个字段 分别是:DB_TRX_ID 、 DB_ROLL_PTR 、DB_ROW_ID
DB_ROW_ID: 隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。
DB_TRX_ID :最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。
DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。’
有了这些知识再去学Mysql的备份恢复就会清晰很多,而且Mysql在做数据迁移时关注SQLthread两个IOthread线程和binlog日志就行,Mysql的存储结构和InnoDB结构很好理解,七个日志不需要全部了解。在学备份恢复就很简单,但是Oracle就学不明白他的某些方面的原理,学习曲线上比mysql高太多了。
其实怎么把数据存储到操作系统上,目前阶段还不需要太关心,可以把这个任务放到后面甚至时几年之后,但是今天在学习Oracle redo undo原理时,涉及到了存储结构,主要表达还是mysql和Oracle学习同样的内容,Oracle学习曲线上比mysql高太多了。排除Oracle和Mysql两者的复杂程度,客观上来讲Oracle对国内的学习支者持不是很友好,包括学习资料、知识沉淀、社区等,比如想搞懂一下页分裂、页合并阈值参数、数据行的存储格式、redo、undo的底层原理等,Oracle学起来都难太多了
索引相关
后面我又想到索引,主要是增加查询效率吗,对于OLTP系统来说是必要的,Oracle、MySQL都是在页目录里存放了索引信息,接着疑惑又来了,int自增主键的索引还比较好理解,那如果是非int型,我的理解是索引标识其实是一种类似二分查找的算法,需要自增,
如果不是自增的,会有什么影响?
首先我们知道,两者在建表时都会建立该系统默认的索引(B-树、B+树),默认是主键,没有主键会有一个隐藏字段Row_id,当作索引,这样一个B树的逻辑结构就有了,主键字段是数字类型 自增的,这里涉及到了主键优化的问题,如果主键不是自增的比如分布式系统中生成的UUID,64位的雪花算法虽然保证了大数据下的唯一性,但是在插入过程中或产生空间碎片,数据分布不均匀。主要是因为在看出过程中数据页会产生大量的页合并和页分裂。
为什么不用字符类型char、varchar、string当作索引?有没有一种算法是字符串生成自增唯一,那用什么算法实现呢?hash生成唯一标识符+时间戳?todo参考文献
还有就是在Mysql索引是由页目录维护的,页目录就是由多个槽组成的,槽相当于分组记录的索引。然后,因为记录是按照「主键值」从小到大排序的,所以通过槽查找记录时,可以使用二分法快速定位要查询的记录在哪个槽(哪个记录分组),定位到槽后,再遍历槽内的所有记录,找到对应的记录,
如果我们增加一个索引,这个过程是什么样的?
主观猜想:首先把该字段通过算法(hash)生成一组多少位的二进制转成十进制进行排序,逻辑上建立B树,存储上在操作系统里告诉页目录,该索引字段的子节点内存地址只是多少,由页目录维护起来。那如果是联合索引呢?把三个字段放进算法(hash)生生唯一标识?为什么where后面不规范会造成索引失效?
太多问题了,午休时间到了,作为历史遗留问题,虽然可能工作中用不到这些,但是有精力和资料的话,还是学通透一些,可能在后面1年?3年?10年?搞明白了,去开国产发数据库😎
参考:
ChatGPT
在 Linux 操作系统上,当进行数据库数据的增删改查操作时,具体的数据存储方式取决于所使用的数据库管理系统(DBMS)和存储引擎。以下是常见的数据库系统在 Linux 上的数据存储方式:
-
MySQL/Oracle 数据库:
-
MySQL 和 Oracle 数据库通常使用类似的数据存储方式。数据存储在数据库文件中,这些文件通常以特定的扩展名(例如 .ibd 或 .dbf)存储在操作系统的文件系统中。
-
对于 InnoDB 存储引擎,数据和索引分别存储在 .ibd 文件中。当执行增删改查操作时,数据会被写入到对应的数据文件中,然后由数据库引擎负责管理和维护。
-
对于 Oracle 数据库,数据存储在表空间中的数据文件(.dbf 文件)中,而表空间由数据文件组成。当执行增删改查操作时,数据会被写入到对应的数据文件中,然后由 Oracle 数据库引擎管理。
-
-
PostgreSQL 数据库:
-
PostgreSQL 数据库使用 WAL(Write-Ahead Logging)机制,将数据和日志分开存储。数据存储在表空间中的数据文件中,而 WAL 日志存储在专门的日志文件中。
-
当执行增删改查操作时,数据会被写入到对应的数据文件中,同时相应的 WAL 日志也会被写入到日志文件中,以确保数据的一致性和持久性。
-
-
MongoDB 数据库:
-
MongoDB 数据库使用 BSON(Binary JSON)格式存储数据。数据存储在数据文件中,每个数据文件包含了一个或多个数据集(Collection)的数据。
-
当执行增删改查操作时,数据会被写入到对应的数据文件中,然后由 MongoDB 数据库引擎管理和维护。
-
总的来说,无论使用哪种数据库管理系统,数据存储在操作系统的文件系统中,具体的存储方式和文件结构取决于数据库管理系统和存储引擎的设计和实现。在执行增删改查操作时,数据会被写入到对应的数据文件中,并由数据库引擎负责管理和维护。