首页后端开发PythonMYSQL INNODB ibd文件详解 (3) FIL_PAGE_SDI

MYSQL INNODB ibd文件详解 (3) FIL_PAGE_SDI

时间2023-07-05 14:04:01发布访客分类Python浏览524
导读:虽然上一章已经提取了DDL, 但是存储DDL的sdi页还没有讲.... 现在补上呗..FIL_PAGE_SDI是存储数据字典的, 8.0把它和表放一起了. 位于ibd文件的第4页 (在inode里面有记录, 也是属于segment 结构如...

虽然上一章已经提取了DDL, 但是存储DDL的sdi页还没有讲.... 现在补上呗..

FIL_PAGE_SDI

是存储数据字典的, 8.0把它和表放一起了. 位于ibd文件的第4页 (在inode里面有记录, 也是属于segment)

结构如下

名字

大小(字节)

描述

FIL_HEADER

38

PAGE_HEADER

56

页头部信息

INFIMUM

13

rec_header(5)+infimum(8) 指向下一条记录

SUPREMUM

13

rec_header(5)+supremum(8) 最后一条记录

other

SDI_DATA

SDI数据, 使用zlib压缩存储的.

other(比如page_directory)

FIL_TRAILER

8

INFIMUM记录的地址不包含RECORD_HEADER

PYTHON解析SDI

sdi信息里面并没有唯一索引的区别, 只有主键索引和普通索引, 推测唯一约束由server层实现.

import innodb_sdi
aa = innodb_sdi.sdi('/data/mysql_3314/mysqldata/db1/ddcw_benchmark__12.ibd')
print(aa.get_ddl())
#aa.get_dic() #返回字典

总结

sdi_page比较简单, 就是个zlib压缩的json格式数据.

ordinal_position 表示的是字段顺序. cloumns和indexes中ordinal_position是完全对应的.

indexes中elements的length如果是4294967295(4G)就表示这个值不属于KEY(就是不是索引值, 是其它值/主键值)

附PYTHON源码

innodb_sdi.py

注: 无法区别是否为唯一索引.

#解析sdi page
#storage/innobase/dict/dict0crea.cc

#STRUCT:
#FIL_HEADER 38
#PAGE_HEADER 56
#INFIMUM 13 (5+8) rec_header的最后两字节指向 sdi数据位置

import struct,json,zlib

PAGE_NEW_INFIMUM = 99

PAGE_SIZE = 16384
class sdi(object):
	def __init__(self,tdata):
		bdata = tdata
		if len(tdata) != PAGE_SIZE:
			with open(tdata,'rb') as f:
				f.seek(PAGE_SIZE*3,0)
				bdata = f.read(PAGE_SIZE)
		self.bdata = bdata
		self.dic_info = None
		self.HAS_NULL = True #设置空值 for ddl
		self.HAS_DEFAULT = True #设置默认值 for ddl
		self.HAS_COMMENT = True #设置注释
		self.HAS_IF_NOT_EXISTS = False #不要create table if not exists

	def get_index(self,):
		return self.get_dic()['dd_object']['indexes']

	def get_columns(self,):
		return self.get_dic()['dd_object']['columns']

	def get_version(self,):
		return self.get_dic()['mysqld_version_id']

	def get_name(self,):
		dic_info = self.get_dic()
		return f"{
dic_info['dd_object']['schema_ref']}
.{
dic_info['dd_object']['name']}
"

	def get_ddl(self):
		dic_info = self.get_dic()
		columns = dic_info['dd_object']['columns']
		indexes = dic_info['dd_object']['indexes']
		dd_object_type = dic_info['dd_object_type']
		schema = dic_info['dd_object']['schema_ref']
		engine = dic_info['dd_object']['engine']
		comment = dic_info['dd_object']['comment']
		foreign_keys = None #不支持外键
		name = dic_info['dd_object']['name']

		ddl = f"CREATE {
dd_object_type}
 {
'IF NOT EXISTS' if self.HAS_IF_NOT_EXISTS else '' }
 {
schema}
.{
name}
"
		cols = ''
		coll = {
}

		for col in columns:
			if col['name'] in ['DB_TRX_ID','DB_ROLL_PTR','DB_ROW_ID']:
				continue
			coll[col['ordinal_position']] = col['name']
			cols += f"\n{
col['name']}
 {
col['column_type_utf8']}
 {
'NULL' if col['is_nullable'] else 'NOT NULL' if self.HAS_NULL else ''}
 {
 col['default_value_utf8'] if self.HAS_DEFAULT else '' }
 {
 col['comment'] if self.HAS_COMMENT else ''}
,"
		indexl = []
		for i in indexes:
			index_name = "PRIMARY KEY" if i['name'] == 'PRIMARY' else i['name']
			idxl = []
			for x in i['elements']:
				if x['length']  4294967295:
					idxl.append(x['ordinal_position'])
			if len(idxl) == 0:
				continue
			indexl.append(f'{
index_name}
({
",".join([ coll[x] for x in idxl ])}
)')
		index = ",".join([ x for x in indexl ])
		col_index = f"{
cols}
\n{
index}
    " if len(index) >
 0 else f"{
cols[:-1]}
"
		ddl = f"{
ddl}
({
col_index}
) ENGINE={
engine}
 {
comment if self.HAS_COMMENT else ''}
    ;
    "

		return ddl

	def get_dic(self):
		offset = struct.unpack('>
    H',self.bdata[PAGE_NEW_INFIMUM-2:PAGE_NEW_INFIMUM])[0] + PAGE_NEW_INFIMUM
		dtype,did = struct.unpack('>
    LQ',self.bdata[offset:offset+12])
		dtrx = int.from_bytes(self.bdata[offset+12:offset+12+6],'big')
		dundo = int.from_bytes(self.bdata[offset+12+6:offset+12+6+7],'big')
		dunzip_len,dzip_len = struct.unpack('>
LL',self.bdata[offset+33-8:offset+33]) 

		unzbdata = zlib.decompress(self.bdata[offset+33:offset+33+dzip_len])
		dic_info = json.loads(unzbdata.decode())
		return dic_info if len(unzbdata) == dunzip_len else {
}
    

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

mysqlpythoninnodbsdifil_page_sdiibd文件解析

若转载请注明出处: MYSQL INNODB ibd文件详解 (3) FIL_PAGE_SDI
本文地址: https://pptw.com/jishu/290345.html
网络工程师学Python-35-开源自动化部署工具Fabric 网络工程师学Python-36-多厂商网络设备自动化管理库Netmiko

游客 回复需填写必要信息