Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2127865
v8.5.5 br: add variable `tidb_advancer_check_point_lag_limit` to cont…
ti-chi-bot Dec 29, 2025
4e18b7a
v8.5.5: Add circuit breaker variable (#19678) (#21176)
ti-chi-bot Dec 29, 2025
bf5b7ac
v8.5.5 br: add compact log backup (#19832) (#21205)
ti-chi-bot Dec 29, 2025
a01bce8
v8.5.5 br: add compatibility between log backup and PITR (#20002) (#2…
ti-chi-bot Dec 29, 2025
51659a0
v8.5.5 br: pitr filter feature release doc (#20450) (#21198)
ti-chi-bot Dec 31, 2025
5a364fc
v8.5.5 br: support pitr filter and concurrent restore (#20919) (#21200)
ti-chi-bot Dec 31, 2025
0b63124
Merge branch 'release-8.5' into feature/preview-v8.5.5
qiancai Jan 6, 2026
5ce1bb8
v8.5.5 br: remove outdated PITR limitation (#21238) (#21239)
ti-chi-bot Jan 6, 2026
9031d29
v8.5.5 restore: update the definition of the parameter `--load-stats`…
ti-chi-bot Jan 6, 2026
8f3a521
v8.5.5 br: pitr restore mode (#20559) (#21216)
ti-chi-bot Jan 6, 2026
7edfc0a
v8.5.5 br: provide a storage target option for BR restore checkpoint …
ti-chi-bot Jan 7, 2026
6bd3654
v8.5.5 br: improve visualization of BR (#20025) (#21217)
ti-chi-bot Jan 8, 2026
8865309
Merge branch 'release-8.5' into feature/preview-v8.5.5
qiancai Jan 13, 2026
437a5df
v8.5.5 br: add ddl job none error report (#21260) (#21266)
ti-chi-bot Jan 13, 2026
1ee718e
v8.5.5: add config for graceful shutdown (#21173)
hujiatao0 Jan 13, 2026
6eea4d4
v8.5.5: include storage engines in slow query logs and statements sum…
ti-chi-bot Jan 13, 2026
ed582d6
v8.5.5: Add index lookup push down content (#20950) (#21229)
ti-chi-bot Jan 13, 2026
0e0ef0d
v8.5.5: add doc for async-batch-get (#21164) (#21271)
ti-chi-bot Jan 13, 2026
d0e187c
Merge branch 'release-8.5' into feature/preview-v8.5.5
qiancai Jan 13, 2026
7304166
v8.5.5 pd,tidb: support affinity schedule (#21207) (#21273)
ti-chi-bot Jan 13, 2026
689ef3a
v8.5.5 scheduler: network slow store scheduler enhancement (#21196) (…
ti-chi-bot Jan 14, 2026
3c53b02
v8.5.5: add store limit support (#21257) (#21272)
ti-chi-bot Jan 14, 2026
a608757
v8.5.5: Add unified.cpu-threshold config (#21174) (#21267)
ti-chi-bot Jan 14, 2026
fdadcfd
v8.5: bump up the latest version to v8.5.5 (#21277)
qiancai Jan 14, 2026
106fd41
v8.5.5 br: add a new authentication method for Azure (#21206) (#21279)
ti-chi-bot Jan 14, 2026
de52c0f
Update upgrade-tidb-using-tiup.md
qiancai Jan 15, 2026
5d0825a
Update upgrade-tidb-using-tiup.md
qiancai Jan 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
- [使用概述](/br/br-use-overview.md)
- [快照备份与恢复](/br/br-snapshot-guide.md)
- [日志备份与 PITR](/br/br-pitr-guide.md)
- [压缩日志备份](/br/br-compact-log-backup.md)
- [实践示例](/br/backup-and-restore-use-cases.md)
- [备份存储](/br/backup-and-restore-storages.md)
- br cli 命令手册
Expand Down Expand Up @@ -882,6 +883,7 @@
- [`SET ROLE`](/sql-statements/sql-statement-set-role.md)
- [`SET TRANSACTION`](/sql-statements/sql-statement-set-transaction.md)
- [`SET <variable>`](/sql-statements/sql-statement-set-variable.md)
- [`SHOW AFFINITY`](/sql-statements/sql-statement-show-affinity.md)
- [`SHOW [BACKUPS|RESTORES]`](/sql-statements/sql-statement-show-backups.md)
- [`SHOW ANALYZE STATUS`](/sql-statements/sql-statement-show-analyze-status.md)
- [`SHOW BINDINGS`](/sql-statements/sql-statement-show-bindings.md)
Expand Down Expand Up @@ -999,6 +1001,7 @@
- [临时表](/temporary-tables.md)
- [缓存表](/cached-tables.md)
- [外键约束](/foreign-key.md)
- [表级数据亲和性](/table-affinity.md)
- 字符集和排序规则
- [概述](/character-set-and-collation.md)
- [GBK](/character-set-gbk.md)
Expand Down
4 changes: 3 additions & 1 deletion best-practices/pd-scheduling-best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,9 @@ Region Merge 速度慢也很有可能是受到 limit 配置的限制(`merge-sc

实践中,如果能确定这个节点的故障是不可恢复的,可以立即做下线处理,这样 PD 能尽快补齐副本,降低数据丢失的风险。与之相对,如果确定这个节点是能恢复的,但可能半小时之内来不及,则可以把 `max-store-down-time` 临时调整为比较大的值,这样能避免超时之后产生不必要的副本补充,造成资源浪费。

自 v5.2.0 起,TiKV 引入了慢节点检测机制。通过对 TiKV 中的请求进行采样,计算出一个范围在 1~100 的分数。当分数大于等于 80 时,该 TiKV 节点会被设置为 slow 状态。可以通过添加 [`evict-slow-store-scheduler`](/pd-control.md#scheduler-show--add--remove--pause--resume--config--describe) 来针对慢节点进行对应的检测和调度。当检测到有且只有一个 TiKV 节点为慢节点,并且该 TiKV 的 slow score 到达限定值(默认 80)时,将节点上的 Leader 驱逐(其作用类似于 `evict-leader-scheduler`)。
自 v5.2.0 起,TiKV 引入了磁盘的慢节点检测机制。通过对 TiKV 中的请求进行采样,计算出一个范围在 1~100 的分数。当分数大于等于 80 时,该 TiKV 节点会被设置为 slow 状态。可以通过添加 [`evict-slow-store-scheduler`](/pd-control.md#scheduler-show--add--remove--pause--resume--config--describe) 来针对慢节点进行对应的调度。当检测到有且只有一个 TiKV 节点为慢节点,并且该 TiKV 的 slow score 到达限定值(默认 80)时,将节点上的 Leader 驱逐(其作用类似于 `evict-leader-scheduler`)。

自 v8.5.5 起,TiKV 引入了网络的慢节点检测机制。与磁盘慢节点检测类似,该机制通过在 TiKV 节点之间进行网络延时探测并计算分数,来判断节点的网络是否出现异常。可以通过 [`enable-network-slow-store`](/pd-control.md#scheduler-config-evict-slow-store-scheduler) 来开启该机制。

> **注意:**
>
Expand Down
1 change: 0 additions & 1 deletion br/backup-and-restore-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ TiDB 备份恢复功能可以用于满足以下业务的需求:
### 使用限制

- PITR 仅支持恢复到**全新的空集群**。
- PITR 仅支持集群粒度的恢复,不支持对单个 database 或 table 的恢复。
- PITR 不支持恢复系统表中用户表和权限表的数据。
- 不支持在一个集群上**同时**运行多个数据备份任务。
- 不建议备份正在恢复的表,这样备份的数据可能存在异常。
Expand Down
60 changes: 60 additions & 0 deletions br/backup-and-restore-storages.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,66 @@ tiup br restore db --db test -u "${PD_IP}:2379" \
--storage "azure://external/backup-20220915?account-name=${account-name}"
```

- 方式四:使用 Azure 托管标识 (Managed Identity)

从 v8.5.5 起,如果你的 TiDB 集群和 br 命令行工具运行在 Azure 虚拟机 (VM) 或 Azure Kubernetes Service (AKS) 环境中,并且已为节点分配了 Azure 托管标识,则可以使用 Azure 托管标识进行鉴权。

使用此方式前,请确保已在 [Azure Portal](https://azure.microsoft.com/) 中为对应的托管标识授予目标存储账户的访问权限(如 `Storage Blob Data Contributor`)。

- **系统分配的托管标识 (System-assigned)**:

使用系统分配的托管标识时,无需配置任何 Azure 相关环境变量,直接运行 br 备份命令即可。

```shell
tiup br backup full -u "${PD_IP}:2379" \
--storage "azure://external/backup-20220915?account-name=${account-name}"
```

> **注意:**
>
> 请确保运行环境中**不存在** `AZURE_CLIENT_ID`、`AZURE_TENANT_ID` 或 `AZURE_CLIENT_SECRET` 环境变量,否则 Azure SDK 可能会优先使用其他认证方式,导致托管标识未生效。

- **用户分配的托管标识 (User-assigned)**:

使用用户分配的托管标识时,需要在 TiKV 运行环境和 br 命令行工具运行环境中配置环境变量 `AZURE_CLIENT_ID` (其值为该托管标识的 Client ID),然后再执行 br 备份命令。具体步骤如下:

1. 使用 TiUP 启动时为 TiKV 配置 Client ID:

以下步骤以 TiKV 端口 `24000`、systemd 服务名 `tikv-24000` 为例:

1. 执行以下命令进入服务配置编辑界面:

```shell
systemctl edit tikv-24000
```

2. 配置 `AZURE_CLIENT_ID` 环境变量:

```ini
[Service]
Environment="AZURE_CLIENT_ID=<your-client-id>"
```

3. 重新加载 systemd 配置并重启 TiKV:

```shell
systemctl daemon-reload
systemctl restart tikv-24000
```

2. 为 br 命令行工具配置 `AZURE_CLIENT_ID` 环境变量:

```shell
export AZURE_CLIENT_ID="<your-client-id>"
```

3. 使用 br 命令行工具将数据备份至 Azure Blob Storage:

```shell
tiup br backup full -u "${PD_IP}:2379" \
--storage "azure://external/backup-20220915?account-name=${account-name}"
```

</div>
</SimpleTab>

Expand Down
4 changes: 3 additions & 1 deletion br/backup-and-restore-use-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ tiup br restore point --pd="${PD_IP}:2379" \
--full-backup-storage='s3://tidb-pitr-bucket/backup-data/snapshot-20220514000000' \
--restored-ts '2022-05-15 18:00:00+0800'

Full Restore <--------------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
Split&Scatter Region <--------------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
Download&Ingest SST <--------------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
Restore Pipeline <--------------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
[2022/05/29 18:15:39.132 +08:00] [INFO] [collector.go:69] ["Full Restore success summary"] [total-ranges=12] [ranges-succeed=xxx] [ranges-failed=0] [split-region=xxx.xxxµs] [restore-ranges=xxx] [total-take=xxx.xxxs] [restore-data-size(after-compressed)=xxx.xxx] [Size=xxxx] [BackupTS={TS}] [total-kv=xxx] [total-kv-size=xxx] [average-speed=xxx]
Restore Meta Files <--------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
Restore KV Files <----------------------------------------------------------------------------------------------------------------------------------------------------> 100.00%
Expand Down
82 changes: 78 additions & 4 deletions br/br-checkpoint-restore.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ summary: 了解断点恢复功能,包括它的使用场景、实现原理以

## 实现原理

断点恢复的实现原理分为快照恢复和日志恢复两部分。具体实现细节请参考[实现细节](#实现细节)。
断点恢复的实现原理分为快照恢复和日志恢复两部分。具体实现细节请参考[实现细节:将断点数据存储在下游集群](#实现细节将断点数据存储在下游集群)和[实现细节:将断点数据存储在外部存储](#实现细节将断点数据存储在外部存储)。

### 快照恢复

Expand Down Expand Up @@ -65,7 +65,11 @@ br 工具暂停 GC 的原理是通过执行 `SET config tikv gc.ratio-threshold

不建议进行跨大版本的断点恢复操作。对于使用 v8.5.0 之前长期支持 (Long-Term Support, LTS) 版本 br 恢复失败的集群,无法通过 v8.5.0 或更新的 LTS 版本 br 继续恢复,反之亦然。

## 实现细节
## 实现细节:将断点数据存储在下游集群

> **注意:**
>
> 从 v8.5.5 开始,默认将断点数据存储在下游集群。你可以通过参数 `--checkpoint-storage` 来指定断点数据存储的外部存储。

断点恢复的具体操作细节分为快照恢复和 PITR 恢复两部分。

Expand All @@ -81,8 +85,78 @@ br 工具暂停 GC 的原理是通过执行 `SET config tikv gc.ratio-threshold

[PITR (Point-in-time recovery)](/br/br-pitr-guide.md) 恢复分为快照恢复和日志恢复两个阶段。

在第一次执行恢复时,br 工具首先进入快照恢复阶段。该阶段与上述只进行[快照恢复](#快照恢复-1)操作相同,断点数据,以及备份数据的上游集群的 ID 和备份数据的 BackupTS(即日志恢复的起始时间点 `start-ts`)会被记录到 `__TiDB_BR_Temporary_Snapshot_Restore_Checkpoint` 数据库中。如果在此阶段恢复失败,尝试继续断点恢复时无法再调整日志恢复的起始时间点 `start-ts`。
在第一次执行恢复时,br 工具首先进入快照恢复阶段。断点数据、备份数据的上游集群的 ID、备份数据的 BackupTS(即日志恢复的起始时间点 `start-ts`)和 PITR 恢复的 `restored-ts` 会被记录到 `__TiDB_BR_Temporary_Snapshot_Restore_Checkpoint` 数据库中。如果在此阶段恢复失败,尝试继续断点恢复时无法再调整日志恢复的起始时间点 `start-ts` 和 `restored-ts`。

在第一次执行恢复并且进入日志恢复阶段时,br 工具会在恢复集群中创建 `__TiDB_BR_Temporary_Log_Restore_Checkpoint` 数据库,用于记录断点数据,以及这次恢复的上游集群 ID 和恢复的时间范围 `start-ts` 与 `restored-ts`。如果在此阶段恢复失败,重新执行恢复命令时,你需要指定与断点记录相同的 `start-ts` 和 `restored-ts` 参数,否则 br 工具会报错,并提示上游集群 ID 或恢复的时间范围与断点记录不同。如果恢复集群已被清理,你可以手动删除 `__TiDB_BR_Temporary_Log_Restore_Checkpoint` 数据库,然后使用其他备份重试。

在第一次执行恢复并且进入日志恢复阶段前,br 工具会构造出在 `restored-ts` 时间点的上下游集群库表 ID 映射关系,并将其持久化到系统表 `mysql.tidb_pitr_id_map` 中,以避免库表 ID 被重复分配。如果删除 `mysql.tidb_pitr_id_map` 中的数据,可能会导致 PITR 恢复数据不一致。
注意在第一次执行恢复并且进入日志恢复阶段前,br 工具会构造出在 `restored-ts` 时间点的上下游集群库表 ID 映射关系,并将其持久化到系统表 `mysql.tidb_pitr_id_map` 中,以避免库表 ID 被重复分配。**如果随意删除 `mysql.tidb_pitr_id_map` 中的数据,可能会导致 PITR 恢复数据不一致。**

> **注意:**
>
> 为了兼容旧版本集群,从 v8.5.5 开始,当恢复集群不存在系统表 `mysql.tidb_pitr_id_map` 时,`pitr_id_map` 数据会写到日志备份目录下,文件名为 `pitr_id_maps/pitr_id_map.cluster_id:{downstream-cluster-ID}.restored_ts:{restored-ts}`。

## 实现细节:将断点数据存储在外部存储

> **注意:**
>
> 从 v8.5.5 开始,默认将断点数据存储在下游集群。你可以通过参数 `--checkpoint-storage` 来指定断点数据存储的外部存储。例如:
>
> ```shell
> ./br restore full -s "s3://backup-bucket/backup-prefix" --checkpoint-storage "s3://temp-bucket/checkpoints"
> ```

在外部存储中,断点数据的目录结构如下:

- 主路径 `restore-{downstream-cluster-ID}` 中的下游集群 ID `{downstream-cluster-ID}` 用于区分不同的恢复集群
- 路径 `restore-{downstream-cluster-ID}/log` 存储日志恢复阶段的日志文件断点数据
- 路径 `restore-{downstream-cluster-ID}/sst` 存储日志恢复阶段中未被日志备份覆盖的 SST 文件的断点数据
- 路径 `restore-{downstream-cluster-ID}/snapshot` 存储快照恢复阶段的断点数据

```
.
`-- restore-{downstream-cluster-ID}
|-- log
| |-- checkpoint.meta
| |-- data
| | |-- {uuid}.cpt
| | |-- {uuid}.cpt
| | `-- {uuid}.cpt
| |-- ingest_index.meta
| `-- progress.meta
|-- snapshot
| |-- checkpoint.meta
| |-- checksum
| | |-- {uuid}.cpt
| | |-- {uuid}.cpt
| | `-- {uuid}.cpt
| `-- data
| |-- {uuid}.cpt
| |-- {uuid}.cpt
| `-- {uuid}.cpt
`-- sst
`-- checkpoint.meta
```

断点恢复的具体操作细节分为快照恢复和 PITR 恢复两部分。

### 快照恢复

在第一次执行恢复时,br 工具会在恢复集群中创建路径 `restore-{downstream-cluster-ID}/snapshot`,用于记录断点数据,以及这次恢复的上游集群 ID 和备份的 BackupTS。

如果恢复执行失败,你可以使用相同的命令再次执行恢复,br 工具会从指定的存储断点数据的外部存储中读取断点信息,并从上次中断的位置继续恢复。

当恢复执行失败后,如果你尝试将与断点记录不同的备份数据恢复到同一集群,br 工具会报错,并提示上游集群 ID 或 BackupTS 与断点记录不同。如果恢复集群已被清理,你可以手动删除存储在外部存储的断点数据或更换指定的断点数据存储路径,然后使用其他备份重试。

### PITR 恢复

[PITR (Point-in-time recovery)](/br/br-pitr-guide.md) 恢复分为快照恢复和日志恢复两个阶段。

在第一次执行恢复时,br 工具首先进入快照恢复阶段。断点数据,以及备份数据的上游集群的 ID、备份数据的 BackupTS(即日志恢复的起始时间点 `start-ts`)和 PITR 恢复的 `restored-ts` 会被记录到路径 `restore-{downstream-cluster-ID}/snapshot` 中。如果在此阶段恢复失败,尝试继续断点恢复时无法再调整日志恢复的起始时间点 `start-ts` 和 `restored-ts`。

在第一次执行恢复并且进入日志恢复阶段时,br 工具会在恢复集群中创建路径 `restore-{downstream-cluster-ID}/log`,用于记录断点数据,以及这次恢复的上游集群 ID 和恢复的时间范围 `start-ts` 与 `restored-ts`。如果在此阶段恢复失败,重新执行恢复命令时,你需要指定与断点记录相同的 `start-ts` 和 `restored-ts` 参数,否则 br 工具会报错,并提示上游集群 ID 或恢复的时间范围与断点记录不同。如果恢复集群已被清理,你可以手动删除 存储在外部存储的断点数据或更换指定的断点数据存储路径,然后使用其他备份重试。

注意在第一次执行恢复并且进入日志恢复阶段前,br 工具会构造出在 `restored-ts` 时间点的上下游集群库表 ID 映射关系,并将其持久化到存放断点数据的外部存储中(文件名为 `pitr_id_maps/pitr_id_map.cluster_id:{downstream-cluster-ID}.restored_ts:{restored-ts}`),以避免库表 ID 被重复分配。**如果随意删除 `pitr_id_maps` 目录中的文件,可能会导致 PITR 恢复数据不一致。**

> **注意:**
>
> 为了兼容旧版本集群,从 v8.5.5 开始,当恢复集群不存在系统表 `mysql.tidb_pitr_id_map` 且未指定参数 `--checkpoint-storage` 时,`pitr_id_map` 数据会写到日志备份目录下,文件名为 `pitr_id_maps/pitr_id_map.cluster_id:{downstream-cluster-ID}.restored_ts:{restored-ts}`。
85 changes: 85 additions & 0 deletions br/br-compact-log-backup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: 压缩日志备份
summary: 了解如何通过压缩日志备份为 SST 格式来提升按时间点恢复 (Point-in-time recovery, PITR) 的效率。
---

# 压缩日志备份

本文介绍如何通过压缩日志备份 (Compact Log Backup) 为 [SST](/glossary.md#static-sorted-table--sorted-string-table-sst) 格式来提升按时间点恢复 (Point-in-time recovery, [PITR](/glossary.md#point-in-time-recovery-pitr)) 的效率。

## 功能概述

传统日志备份以一种高度非结构化的方式存储写入操作,可能导致以下问题:

- 恢复性能下降:无序数据需通过 Raft 协议逐条写入集群。
- 写放大:所有写入必须从 LSM Tree 的 L0 开始被逐级别 compact 到底层。
- 全量备份依赖:需频繁执行全量备份以控制恢复数据量,对业务有一定影响。

从 v8.5.5 开始,压缩日志备份功能提供了离线压缩能力,可将日志备份的非结构化数据转换为结构化的 SST 文件,从而实现以下改进:

- SST 可以被快速导入集群,从而提升恢复性能。
- 压缩过程中消除重复记录,从而减少空间消耗。
- 在确保 RTO (Recovery Time Objective) 的前提下允许用户设置更长的全量备份间隔,从而降低对业务的影响。

## 使用限制

- 压缩日志备份并不是全量备份的替代方案,需与定期全量备份配合使用。为了保证能进行 PITR,日志备份的压缩过程会保留所有 MVCC 版本,长期不进行全量备份将导致存储膨胀并且可能在未来恢复时遇到问题。
- 目前不支持压缩启用了 Local Encryption 的备份。

## 使用方法

目前仅支持手动压缩日志备份,流程较为复杂。**建议在生产中使用后续发布的 TiDB Operator 方案来压缩日志备份**。

### 手动压缩

本节介绍手动压缩日志备份的操作步骤。

#### 前提条件

手动压缩日志备份需要两个工具:`tikv-ctl` 和 `br`。

#### 第 1 步:将存储编码为 Base64

执行以下编码命令:

```shell
br operator base64ify --storage "s3://your/log/backup/storage/here" --load-creds
```

> **注意:**
>
> - 如果执行以上命令时带了 `--load-cerds` 这个选项,编码出来的 Base64 中会包含从 BR 当前环境中加载的密钥信息,请注意安全保护和权限管控。
> - 此处的 `--storage` 值应该和日志备份任务的 `log status` 命令输出的 storage 相同。

#### 第 2 步:执行日志压缩

有了存储的 Base64 之后,你可以执行以下命令通过 `tikv-ctl` 发起压缩,注意 `tikv-ctl` 默认日志等级为 `warning`,启用 `--log-level info` 来获得更多信息:

```shell
tikv-ctl --log-level info compact-log-backup \
--from "<start-tso>" --until "<end-tso>" \
-s 'bAsE64==' -N 8
```

参数解释如下:

- `-s`:已获得的存储的 Base64。
- `-N`:最大并发压缩日志任务的数量。
- `--from`:压缩开始的时间戳。
- `--until`:压缩结束的时间戳。

`--from` 和 `--until` 这对参数指定了压缩操作的时间范围。压缩操作将处理所有包含指定时间范围内任意写入的日志文件,因此最终生成的 SST 文件可能包含该范围外的写入数据。

要获取某个特定时间点的时间戳,请执行以下命令:

```shell
echo $(( $(date --date '2004-05-06 15:02:01Z' +%s%3N) << 18 ))
```

> **注意:**
>
> 如果你是 macOS 用户,需要先使用 Homebrew 安装 `coreutils`,并且使用 `gdate` 而非 `date`。
>
> ```shell
> echo $(( $(gdate --date '2004-05-06 15:02:01Z' +%s%3N) << 18 ))
> ```
Loading
Loading