表共享的region显示问题

【TiDB 版本】:5.2.1
表共享region:
image
image

t_test_4和t_test_5表的基本信息:

mysql> select TABLE_NAME,tidb_table_id from information_schema.tables where table_name in ('t_test_4','t_test_2','t_test_5');
+------------+---------------+
| TABLE_NAME | tidb_table_id |
+------------+---------------+
| t_test_2   |            81 |
| t_test_4   |            85 |
| t_test_5   |            87 |
+------------+---------------+
3 rows in set (0.02 sec)


mysql> show create table t_test_4 \G
*************************** 1. row ***************************
       Table: t_test_4
Create Table: CREATE TABLE `t_test_4` (
  `id` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,
  `name` varchar(200) DEFAULT '',
  `honor` varchar(200) DEFAULT '',
  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![auto_rand_base] AUTO_RANDOM_BASE=1421743 */
1 row in set (0.00 sec)

mysql> show create table t_test_5 \G
*************************** 1. row ***************************
       Table: t_test_5
Create Table: CREATE TABLE `t_test_5` (
  `id` bigint(20) NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,
  `name` varchar(200) DEFAULT '',
  `honor` varchar(200) DEFAULT '',
  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![auto_rand_base] AUTO_RANDOM_BASE=15130858 */
1 row in set (0.00 sec)

mysql> select min(id),max(id) from t_test_5;
+---------+---------------------+
| min(id) | max(id)             |
+---------+---------------------+
| 8110001 | 8935141660717874064 |
+---------+---------------------+
1 row in set (0.04 sec)

mysql> select min(id),max(id) from t_test_4;
+---------------------+---------------------+
| min(id)             | max(id)             |
+---------------------+---------------------+
| 3170534137668835185 | 7493989779944511344 |
+---------------------+---------------------+
1 row in set (0.01 sec)


查看t_test_4的region信息:

mysql> show table t_test_4 regions;
+-----------+----------------------------+----------------------------+-----------+-----------------+---------------------+------------+---------------+------------+----------------------+------------------+
| REGION_ID | START_KEY                  | END_KEY                    | LEADER_ID | LEADER_STORE_ID | PEERS               | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS |
+-----------+----------------------------+----------------------------+-----------+-----------------+---------------------+------------+---------------+------------+----------------------+------------------+
|     40029 | t_81_5f72fc00000005bf764b  | t_85_r_3170534137669207230 |     40031 |               4 | 40030, 40031, 40032 |          0 |             0 |          0 |                   97 |           547491 |
|     40066 | t_85_r_3170534137669207230 | t_85_r_7407520667098997812 |     40067 |               5 | 40067, 40068, 40069 |          0 |             0 |          0 |                   40 |           224300 |
|      1141 | t_85_r_7407520667098997812 | t_87_5f728400000000272b86  |      1144 |               4 | 1143, 1144, 1687    |          0 |          1453 |          0 |                  100 |           560750 |
+-----------+----------------------------+----------------------------+-----------+-----------------+---------------------+------------+---------------+------------+----------------------+------------------+
3 rows in set (0.00 sec)


验证数据:

mysql> SELECT START_KEY, TIDB_DECODE_KEY(START_KEY),end_key,TIDB_DECODE_KEY(end_key) FROM information_schema.tikv_region_status WHERE table_name='t_test_4' AND REGION_ID=1141 \G
*************************** 1. row ***************************
                 START_KEY: 7480000000000000FF555F72E6CCCCCCCCFFCCE4340000000000FA
TIDB_DECODE_KEY(START_KEY): {"_tidb_rowid":7407520667098997812,"table_id":"85"}
                   end_key: 7480000000000000FF575F728400000000FF272B860000000000FA
  TIDB_DECODE_KEY(end_key): {"_tidb_rowid":288230376154278790,"table_id":"87"}
1 row in set (0.01 sec)

mysql> select * from t_test_5 where id=288230376154278790;
+--------------------+-------------------------------------------------------------+----------------------------------------------------------------------+
| id                 | name                                                        | honor                                                                |
+--------------------+-------------------------------------------------------------+----------------------------------------------------------------------+
| 288230376154278790 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy |
+--------------------+-------------------------------------------------------------+----------------------------------------------------------------------+
1 row in set (0.01 sec)

发现region_id为1141(t_test_4、t_test_5两个表共享)的region是t_87_5f728400000000272b86,而非正常显示的t_{tableid}r{rowid}.

问题:
1)请问为什么表共享的region endkey表示方式不一样,想标识什么或者区分什么呢?
2) endkey:t_87_5f728400000000272b86 中 5f728400000000272b86 这串字符是怎么来的?

对字符串 5f728400000000272b86 进行解码:

$ ./tikv-ctl --to-escaped 5f728400000000272b86
_r\204\000\000\000\000'+\206

对字符串 end_key 7480000000000000FF575F728400000000FF272B860000000000FA 进行解码:

$ ./tikv-ctl --to-escaped 7480000000000000FF575F728400000000FF272B860000000000FA
t\200\000\000\000\000\000\000\377W_r\204\000\000\000\000\377'+\206\000\000\000\000\000\372

$ ./tikv-ctl --to-hex "\200\000\000\000\000\000\000W"
8000000000000057

$ ./tikv-ctl --to-hex "\204\000\000\000\000'+\206"
8400000000272B86

$ ./tikv-ctl --to-hex "\000\000\000\000\000\372"
0000000000FA

$ ./tidb-ctl decoder "t\x80\x00\x00\x00\x00\x00\x00\x57_r\x84\x00\x00\x00\x00\x27\x2B\x86\x00\x00\x00\x00\x00\xFA"
format: table_row
table_id: 87
row_id: 288230376154278790


疑问:
在对end_key进行escaped解码后,生成数字是三位八进制编码

escaped编码:
不会对 ASCII 字母和数字进行编码,也不会对下面这些ASCII标点符号进行编码: * @ - _ + . / 。其他所有的字符都会被转义序列替换。

然后escaped的编码 再转成 Memory Comparable Encoding 编码,就是这串字符,如下:

"t\x80\x00\x00\x00\x00\x00\x00\x57_r\x84\x00\x00\x00\x00\x27\x2B\x86\x00\x00\x00\x00\x00\xFA"

引申出另外一个话题,Memory Comparable Encoding 编码是如何实现的呢?

Memory Comparable Encoding 是 TiDB 中使用的一种便于在对 key 进行"修饰"(加后缀)之后仍然能保持字典顺序(上升序)的编码方式。

简单来说,就是将 key 按照 8 bytes 一组进行 padding,然后再加入一个 byte,值为 0xFF - 这个组中 padding 占的字节数。

原理: 对 key 加后缀之后,顺序不同只可能出现在一个 key 比另一个短的情况下,通过加 padding 的方式:

  • 将原本的由 key 本身的长度进行比较的点强行拉到了一个组的结尾额外添加的 byte 的比较
  • 加入的额外 byte “0xFF - 这个组中 padding 占的字节数”,其比较结果始终是原本更短的组更小,所以在这一步就能比较出原本 key 的大小关系,屏蔽了后面添加的后缀的影响

User Key 会被按照 Memory Comparable Encoding 方式进行编码,编码算法是以8字节为单位进行Padding。这个操作确保了我们在UserKey 后面追加 start_ts或 commit_ts之后实际写入的 Key 能保持与 User Key 具有相同的顺序。

UserKey	         Start_Ts	writeKey(not padding)              Encodedkey(padding)
abc	             0x05	    abc\x00\x00..\x05                  abc\x00\x00\x00\x00\x00\xFA
abc\x00..\x00	 0x10       abc\x00\x00..\x00\x00\x00..\x10    abc\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFA

UserKey 原始大小顺序是:

abc < abc\x00…\x00

writeKey顺序(加上start_ts后)是:

abc\x00\x00…\x05 > abc\x00\x00…\x00\x00\x00…\x10

Encodedkeykey写入顺序:

abc\x00\x00\x00\x00\x00\xFA\x05 < abc\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFA\x01

可见,padding后,实现了Encodedkey key 顺序和UserKey大小顺序保持一致

疑问:
image

原始key和writekey(not padding)相比,红框多出的 怎么补上去的呢?

点个赞,不过类似这种问题,我们好像有个专门研发的一个渠道 internals.tidb.io

此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。