黄东旭解析 TiDB 的核心优势
502
2019-10-17
内容来源:http://mp.weixin.qq.com/s?__biz=MzI3NDIxNTQyOQ==&mid=2247489877&idx=1&sn=fe6fafe3e4845f091366d9bd7b757bd2&chksm=eb163e3fdc61b729f1d2ded48802eeff65e2891cbdfaf2bfbe387dcabb365a9458f776840ee0#rd
TiDB,你已经是一个成熟的数据库了,该学会用自己的 SQL 查自己的状态了。
INFOMATION_SCHEMA
和 PERFORMANCE_SCHEMA
里面有大量的信息,基本上通过查询些信息,DBA 就能对整个系统的运行状态一目了然。最棒的是,查询的接口正是 SQL,不需要依赖其他的第三方工具,运用表达力强大的 SQL 甚至可以对这些信息进行二次加工或者过滤,另外接入第三方的运维监控工具也很自然,不需要引入新的依赖。SHOW TABLES
和几条 SELECT
就能够了。当然选择 RESTFul API 还有其他的原因,例如有些操作并不是只读的,是类似命令的形式,例如:手动 split region 这类操作,使用 RESTFul API 会更好,这两者其实并不矛盾,系统表当然是一个很好的补充,这是提升整体软件易用性的一个好例子。INFORMATION_SCHEMA
添加了一张名为 TIDB_SERVERS_INFO
的表,用来显示集群中所有活着的 tidb-server 的状态信息(基本和 /info/all
做的事情差不多),意在抛砖引玉,社区的小伙伴可以参照这篇博客添加新的有用的信息。information_schema
的代码看看别的系统表是怎么实现的,照猫画虎就 OK 了(没毛病)。TiDB 的代码组织还算比较直观,在 tidb repo 的根目录下直接看到了一个包叫 infoschema
,感觉就是它,打开 inforschema/table.go
后确实应证了我的猜想,文件开头集中定义了很多字符串常量:...
tableTiKVStoreStatus = "TIKV_STORE_STATUS"
tableAnalyzeStatus = "ANALYZE_STATUS"
tableTiKVRegionStatus = "TIKV_REGION_STATUS"
tableTiKVRegionPeers = "TIKV_REGION_PEERS"
...
INFOMATION_SCHEMA
中的表名,根据这些变量顺藤摸瓜可以找到同文件里面的 tableNameToColumns
这个 map,顾名思义应该是这个 map 通过表名映射到表结构定义,随便打开一个,果然如此:var columnStatisticsCols = []columnInfo{
{"SCHEMA_NAME", mysql.TypeVarchar, 64, mysql.NotNullFlag, nil, nil},
{"TABLE_NAME", mysql.TypeVarchar, 64, mysql.NotNullFlag, nil, nil},
{"COLUMN_NAME", mysql.TypeVarchar, 64, mysql.NotNullFlag, nil, nil},
{"HISTOGRAM", mysql.TypeJSON, 51, 0, nil, nil},
}
infoschemaTable
这个类实现了 table.Table interface
,很显然这个 interface 就是 TiDB 中对于 Table 获取数据/修改数据的接口,有关获取数据的方法是 IterRecords
,我们只需要看到 IterRecords
中的实现就能知道这些系统表的数据是如何返回给 SQL Engine 的,果然在 IterRecords
里面有一个方法,inforschemaTable.getRows()
,这个方法的定义中有一个巨大的 switch 语句,用于判断是在哪个系统表上,根据这个信息然后返回不同的数据:...
switch it.meta.Name.O {
case tableSchemata:
fullRows = dataForSchemata(dbs)
case tableTables:
fullRows, err = dataForTables(ctx, dbs)
case tableTiDBIndexes:
fullRows, err = dataForIndexes(ctx, dbs)
...
}
infoschema/tables.go
中添加一个新的字符串常量 tableTiDBServersInfo
用于定义表名;[]columnInfo:tableTiDBServersInfoCols
,用于定义这张系统表的结构;tableNameToColumns
这个 map 中添加一个新的映射关系 tableTiDBServersInfo => tableTiDBServersInfoCols
;infoschemaTable.getRows()
方法中加入一个新的 dataForTableTiDBServersInfo
的 swtich case;dataForTableTiDBServersInfo
,很显然,大致的思路是:tableTiDBServersInfoCols
中定义的形式,返回给 getRows
方法。sessionctx.Context
是 TiDB 中一个很重要的对象,也是 TiDB 贯穿整个 SQL 引擎的一个设计模式,这个 Context 中间存储在这个 session 生命周期中的一些重要信息,例如我们可以通过 sessionctx.Context
获取底层的 Storage 对象,拿到 Storage 对象后,能干的事情就很多了。dataForTiDBHotRegions
的实现:tikvStore, ok := ctx.GetStore().(tikv.Storage)
domain/info.go
中的这个方法正是我们想要的:// GetAllServerInfo gets all servers static information from etcd. func (is *InfoSyncer)
GetAllServerInfo(ctx context.Context) (map[string]*ServerInfo, error)
/info/all
这个 REST API 正是通过调用这个函数实现,我们只需要调用这个方法,将返回值封装好就完成了。版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。