diff --git a/.circleci/config.yml b/.circleci/config.yml index 7da8a1b35b4b..4a584eeb3c8d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -58,8 +58,8 @@ jobs: name: "Publish PDF" command: | sudo bash -c 'echo "222.222.95.49 uc.qbox.me" >> /etc/hosts'; - if [ "${CIRCLE_BRANCH}" == "master" ]; then - python3 scripts/upload.py output.pdf tidb-manual-cn-dev.pdf; + if [ "${CIRCLE_BRANCH}" == "release-4.0" ]; then + python3 scripts/upload.py output.pdf tidb-v4.0-zh-manual.pdf; fi - run: @@ -80,4 +80,4 @@ workflows: filters: branches: only: - - master + - release-4.0 diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md deleted file mode 100644 index d158793d3bc5..000000000000 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -name: "\U0001F41B Bug Report" -about: Typo, Grammatical error, etc.。 ---- - -## Bug 报告 - -**This repository is ONLY used to solve problems related to DOCS-CN. -For other issues (TiDB, TiKV, etc), please move to [other repositories](https://github.com/pingcap/).** - - -Please answer the following questions before submitting your issue. Thanks! - - -1. What is the document directory for the problem? - - - -2. How would you like to improve it? - - - diff --git a/.github/ISSUE_TEMPLATE/change-request.md b/.github/ISSUE_TEMPLATE/change-request.md new file mode 100644 index 000000000000..197fd4ce2c02 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/change-request.md @@ -0,0 +1,27 @@ +--- +name: "\U0001F680 Change Request" +about: Any suggestion? Want to add something new? +--- + +## Change Request + +**This repository is ONLY used to solve problems related to DOCS-CN. +For other issues (TiDB, TiKV, etc), please move to [other repositories](https://github.com/pingcap/).** + + +Please answer the following questions before submitting your issue. Thanks! + + +1. Describe what you find is inappropriate or missing in the existing docs. + + + +2. Describe your suggestion or addition. + + + +3. Provide some reference materials (documents, websites, etc) if you could. + + + diff --git a/.github/ISSUE_TEMPLATE/error-report.md b/.github/ISSUE_TEMPLATE/error-report.md new file mode 100644 index 000000000000..bb936febc510 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/error-report.md @@ -0,0 +1,23 @@ +--- +name: "\U0001F41B Error Report" +about: Typos, grammatical errors, terminology misuse, ambiguity, etc. +--- + +## Error 报告 + +**This repository is ONLY used to solve problems related to DOCS-CN. +For other issues (TiDB, TiKV, etc), please move to [other repositories](https://github.com/pingcap/).** + + +Please answer the following questions before submitting your issue. Thanks! + + +1. What is the document directory for the problem? + + + +2. How would you like to improve it? + + + diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md deleted file mode 100644 index 76394d9b70c4..000000000000 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: "\U0001F680 Feature Request" -about: Any suggestion? Want to add something new? ---- - -## Feature Request - -**This repository is ONLY used to solve problems related to DOCS-CN. -For other issues (TiDB, TiKV, etc), please move to [other repositories](https://github.com/pingcap/).** - - -1. Did you encounter a certain issue about the documentation? If yes, please describe the issue that relates to your feature request. - - - -2. Please describe your suggestion or addition. - - - -3. If convenient, please provide reference materials (Blog, Stack Overflow, etc). - - - diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index b9911c0f9e27..10623762e3ab 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -22,3 +22,5 @@ Before asking a question, make sure you have: - [TiDB Docs](https://github.com/pingcap/docs) - [TiDB Docs-cn](https://github.com/pingcap/docs-cn) + +Now, please describe your question here: diff --git a/.github/auto-label.json b/.github/auto-label.json new file mode 100644 index 000000000000..d00f6973330a --- /dev/null +++ b/.github/auto-label.json @@ -0,0 +1,6 @@ +{ + "rules": { + "translation/welcome": ["*.md", "*.yml", "*.yaml", "*.json", "media/", "scripts/"], + "status/PTAL": ["*.md", "*.yml", "*.yaml", "*.json", "media/", "scripts/"] + } +} \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index abc6eb925e3a..b29d00efb63e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,23 +1,25 @@ - + ### What is changed, added or deleted? (Required) - + ### Which TiDB version(s) do your changes apply to? (Required) - + -- [ ] master (the latest development version, including v4.0 changes for now) +- [ ] master (the latest development version) +- [ ] v4.0 (TiDB 4.0 versions) - [ ] v3.1 (TiDB 3.1 versions) - [ ] v3.0 (TiDB 3.0 versions) - [ ] v2.1 (TiDB 2.1 versions) -**If you select two or more versions from above**, to trigger the bot to cherry-pick this PR to your desired release version branch(es), you **must** add corresponding labels such as **needs-cherry-pick-3.1**, **needs-cherry-pick-3.0**, and **needs-cherry-pick-2.1**. + ### What is the related PR or file link(s)? - + -- This PR is translated from: -- Other reference link(s): +- This PR is translated from: +- Other reference link(s): diff --git a/.github/workflows/assign-to-project.yml b/.github/workflows/assign-to-project.yml new file mode 100644 index 000000000000..49e3bf43e880 --- /dev/null +++ b/.github/workflows/assign-to-project.yml @@ -0,0 +1,39 @@ +name: Assign to Project + +on: + issues: + types: [opened, labeled] + pull_request: + types: [opened, labeled] +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + assign_one_project: + runs-on: ubuntu-latest + name: Assign to Project + steps: + - name: Assign NEW issues to Docs SIG project + uses: srggrs/assign-one-project-github-action@1.2.0 + if: | + github.event_name == 'issues' && + github.event.action == 'opened' + with: + project: 'https://github.com/pingcap/docs-cn/projects/1' + column_name: 'Issue: Backlog' + - name: Assign NEW pull requests to Docs SIG project + uses: srggrs/assign-one-project-github-action@1.2.0 + if: | + github.event_name == 'pull_request' && + github.event.action == 'opened' + with: + project: 'https://github.com/pingcap/docs-cn/projects/1' + column_name: 'PR: In Progress' + - name: Assign issues or PRs with translation-welcome label + uses: srggrs/assign-one-project-github-action@1.2.0 + if: | + contains(github.event.issue.labels.*.name, 'translation/welcome') || + contains(github.event.pull_request.labels.*.name, 'translation/welcome') + with: + project: 'https://github.com/pingcap/docs-cn/projects/2' + column_name: 'To do' diff --git a/.github/workflows/auto-label.yml b/.github/workflows/auto-label.yml new file mode 100644 index 000000000000..1a498379833e --- /dev/null +++ b/.github/workflows/auto-label.yml @@ -0,0 +1,16 @@ +name: Auto Label +on: + pull_request: + branches: + - master + types: [opened] + +jobs: + auto-label: + name: Auto Label + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: banyan/auto-label@1.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/media.yml b/.github/workflows/media.yml new file mode 100644 index 000000000000..3b7cc9756c40 --- /dev/null +++ b/.github/workflows/media.yml @@ -0,0 +1,39 @@ +name: Upload media files to Qiniu and Aws when they change +on: + push: + branches: + - master + - release-2.1 + - release-3.0 + - release-3.1 + - release-4.0 + paths: + - media/** +jobs: + run: + name: Upload media files + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + with: + # Must use at least depth 2! + fetch-depth: 2 + + - name: Download cloud_assets_utils + run: | + curl -L https://github.com/pingcap/cloud-assets-utils/releases/download/v0.2.0/cloud_assets_utils-ubuntu-latest -o cloud_assets_utils + chmod +x cloud_assets_utils + sudo mv cloud_assets_utils /usr/local/bin/cloud-assets-utils + - name: Configure qshell + run: | + curl http://devtools.qiniu.com/qshell-linux-x64-v2.4.1.zip -o qshell.zip + unzip qshell.zip + sudo mv qshell-linux-x64-v2.4.1 /usr/local/bin/qshell + qshell account ${{ secrets.QINIU_ACCESS_KEY }} ${{ secrets.QINIU_SECRET_KEY }} test + - name: Configure awscli + run: | + pip3 install --upgrade setuptools + pip3 install awscli + printf "%s\n" ${{ secrets.AWS_ACCESS_KEY }} ${{ secrets.AWS_SECRET_KEY }} ${{ secrets.AWS_REGION }} "json" | aws configure + - name: Upload + run: cloud-assets-utils verify-and-sync -qiniu true -qiniu-bucket ${{ secrets.QINIU_BUCKET_NAME }} -aws true -aws-bucket ${{ secrets.AWS_BUCKET_NAME }} media -replace-first-path-to images/docs-cn diff --git a/.markdownlint.yaml b/.markdownlint.yaml index b03529ab0dbd..f7e19803bc8a 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -1,4 +1,4 @@ -comment: 'Rules for PingCAP docs-cn' +comment: 'Markdownlint Rules for PingCAP docs-cn' # disable all by default default: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2eaad676e2c..77a591babaa8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ TiDB 中文文档的日常更新特别活跃,相应地,[TiDB 英文文档](h 你可以通过以下简单几步来认领一个 PR 翻译任务: -1. 打开 [pingcap/docs-cn PR 翻译任务页面](https://github.com/pingcap/docs-cn/pulls?q=is%3Apr+label%3Atranslation%2Fwelcome+is%3Aopen+),可以看到所有打上了 `translation/welcome` label 的 PR(这类 PR 无论是 open 还是 closed 状态,均在认领的范畴)。 +1. 打开 [pingcap/docs-cn PR 翻译任务页面](https://github.com/pingcap/docs-cn/pulls?q=is%3Apr+label%3Atranslation%2Fwelcome+),可以看到所有打上了 `translation/welcome` label 的 PR(这类 PR 无论是 open 还是 closed 状态,均在认领的范畴)。 2. 打开你想认领的 PR,拉到底部留下这条 comment:`@yikeke: I'd like to translate this PR.`。 3. 仓库管理员 @yikeke 会及时联系你,并将 `translation/welcome` 改为 `translation/doing`,之后你便可以开始翻译了。 @@ -66,7 +66,7 @@ TiDB 文档的修改需要遵循一定的流程,具体如下。考虑到有些 > **注意:** > -> 目前 TiDB 主要维护四个版本的文档:dev(最新开发版),v3.1(3.1 Beta 版),v3.0(最新稳定版),v2.1(最新 2.1 版)。提 Pull Request 前请务必考虑修改会影响的文档版本,并据此修改所有相应的版本。 +> 目前 TiDB 主要维护以下几个版本的文档:dev(最新开发版)、v4.0、v3.1、v3.0 以及 v2.1。提 Pull Request 前请务必考虑修改会影响的文档版本,并据此修改所有相应的版本。 ### 第 1 步:Fork pingcap/docs-cn 仓库 @@ -136,45 +136,22 @@ git push -u origin new-branch-name > **注意:** > -> - 如果你的修改影响多个文档版本 (dev, *v4.0, v3.1, v3.0, v2.1),务必在 PR 描述框中勾选相应的版本,或者在页面右侧选择相应的 label (dev, *v4.0, v3.1, v3.0, v2.1) 来注明。v4.0 为尚未发布的新版本。 -> - 如果你的修改也同样适用于[英文版文档](https://github.com/pingcap/docs),需要在提 PR 时添加 label `pending-aligning`;也非常欢迎同时更新中文版和英文版。 +> - 如果你的修改影响多个文档版本 (dev, v4.0, v3.1, v3.0, v2.1),务必**在 PR 描述框中勾选相应的版本**,后续仓库管理员会为你的 PR 打上相应的 cherry-pick 标签。 ## 必须遵循的 Markdown 规范 TiDB 中文文档使用 Markdown 语言进行编写,为了保证文档质量和格式规范,你修改的文档需要遵循一定的 Markdown 规则。我们为 docs-cn 仓库设置了检测 markdown 文件规范的 CI check,即 [markdownlint check](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md)。如果你提交的 PR 不符合规范,很可能**无法通过 markdownlint check**,最终导致无法合并 PR。 -假如你提 PR 之前没有熟悉相关 Markdown 规范,提 PR 时遇到了 markdownlint check 失败,也不必担心,报错信息里会明确告诉你哪个文件的哪一行出了什么问题,根据提示在 PR 里更新一下文档内容即可搞定。此外,你还可以选择在本地进行 markdownlint check: +我们为 TiDB 中文文档提前设置了 25 条 [markdownlint 规则](/resources/markdownlint-rules.md),并附上了简单易懂的解释,强烈推荐花 5 分钟大致浏览一遍。 + +假如你提 PR 之前没有熟悉相关 Markdown 规范,提 PR 时遇到了 markdownlint check 失败,也不必担心,报错信息里会明确告诉你哪个文件的哪一行出了什么问题,根据提示在 PR 里更新一下文档内容即可搞定。 + +此外,你还可以选择在本地进行 markdownlint check: ```bash ./scripts/markdownlint [FILE...] ``` -👇以下是我们为 TiDB 中文文档提前设置的 25 条 [markdownlint 规则](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md),附上了简单易懂的解释,相信你花几分钟快速浏览一遍 🤓即可基本掌握。 - -| NO. | 规则 | 描述 | -| :--- | :--- | :--- | -| 1 | [MD001 - Heading levels should only increment by one level at a time](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md001---heading-levels-should-only-increment-by-one-level-at-a-time) | 标题从一级开始递增使用,禁止跳级使用。例如:一级标题下面不能直接使用三级标题;二级标题下面不能直接使用四级标题。 | -| 2 | [MD003 - Heading style](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md003---heading-style) | 标题必须统一使用 ATX 风格,即在标题前加 `#` 号来表示标题级别。 | -| 3 | [MD018 - No space after hash on atx style heading](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md018---no-space-after-hash-on-atx-style-heading) | 标题的引导符号 `#` 后必须**空一格**再接标题内容。 | -| 4 | [MD019 - Multiple spaces after hash on atx style heading](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md019---multiple-spaces-after-hash-on-atx-style-heading) | 标题的引导符号“#”后只能空**一格**后再接标题内容,不能有多个空格。 | -| 5 | [MD023 - Headings must start at the beginning of the line](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md023---headings-must-start-at-the-beginning-of-the-line) | 标题必须出现在一行行首,即标题的 `#` 号前不能有任何空格。 | -| 6 | [MD026 - Trailing punctuation in heading](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md026---trailing-punctuation-in-heading) | 标题末尾仅能出现中英文问号、反引号、中英文单双引号等符号。其余如**冒号**、逗号、句号、感叹号等符号均不能在标题末尾使用。 | -| 7 | [MD022 - Headings should be surrounded by blank lines](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md022---headings-should-be-surrounded-by-blank-lines) | 标题上下均须空一行。 | -| 8 | [MD024 - Multiple headings with the same content](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md024---multiple-headings-with-the-same-content) | 文档中不能连续出现内容重复的标题,如一级标题为 `# TiDB 架构`,紧接着的二级标题就不能是 `## TiDB 架构`。如果不是连续的标题,则标题内容可重复。 | -| 9 | [MD025 - Multiple top level headings in the same document](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md025---multiple-top-level-headings-in-the-same-document) | 文档中只能出现一个一级标题。一级标题前的元数据(写明了 `title` 和 `category`)不会违反该规则。 | -| 10 | [MD041 - First line in file should be a top level heading](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md041---first-line-in-file-should-be-a-top-level-heading) | 文档正文一开始必须是一级标题。这条规则会自动忽略文档中头几行的元数据,直接检查后面是否有一级标题。 | -| 11 | [MD007 - Unordered list indentation](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md007---unordered-list-indentation) | 一般来说,除 `TOC.md` 文件可缩进 2 个空格外,其余所有 `.md` 文件每缩进一级,默认须缩进 4 个空格。 | -| 12 | [MD010 - Hard tabs](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md010---hard-tabs) | 文档中(包括代码块内)禁止出现 **Tab 制表符**,如需缩进,必须统一用**空格**代替。 | -| 13 | [MD012 - Multiple consecutive blank lines](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md012---multiple-consecutive-blank-lines) | 禁止出现连续的空行。 | -| 14 | [MD027 - Multiple spaces after blockquote symbol](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md027---multiple-spaces-after-blockquote-symbol) | 块引用符号 `>` 后禁止出现多个空格,只能使用**一个**空格,后接引用内容。 | -| 15 | [MD029 - Ordered list item prefix](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md029---ordered-list-item-prefix) | 使用有序列表时,必须从 1 开始,按顺序递增。 | -| 16 | [MD030 - Spaces after list markers](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md030---spaces-after-list-markers) | 使用列表时,每一列表项的标识符(`+`、`-`、`*` 或数字)后只能**空一格**,后接列表内容。| -| 17 | [MD032 - Lists should be surrounded by blank lines](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md032---lists-should-be-surrounded-by-blank-lines) | 列表(包括有序和无序列表)前后必须各空一行。 | -| 18 | [MD031 - Fenced code blocks should be surrounded by blank lines](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md031---fenced-code-blocks-should-be-surrounded-by-blank-lines) | 代码块前后必须各空一行。 | -| 29 | [MD034 - Bare URL used](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md034---bare-url-used) | 文档中禁止出现裸露的 URL。如果希望用户能直接点击并打开该 URL,则使用一对尖括号 (``) 包裹该 URL。如果由于特殊情况必须使用裸露的 URL,不需要用户通过点击打开,则使用一对反引号 (``` `URL` ```) 包裹该 URL。 | -| 20 | [MD037 - Spaces inside emphasis markers](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md037---spaces-inside-emphasis-markers) | 使用加粗、斜体等强调效果时,在强调标识符内禁止出现多余的空格。如不能出现 ``` `** 加粗文本 **` ```。 | -| 21 | [MD038 - Spaces inside code span elements](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md038---spaces-inside-code-span-elements) | 单个反引号包裹的代码块内禁止出现多余的空格。如不能出现 ``` ` 示例文本 ` ```。 | -| 22 | [MD039 - Spaces inside link text](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md039---spaces-inside-link-text) | 链接文本两边禁止出现多余的空格。如不能出现 `[ 某链接 ](https://www.example.com/)`。 | -| 23 | [MD042 - No empty links](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md042---no-empty-links) | 链接必须有链接路径。如不能出现`[空链接]()`或`[空链接](#)`等情况。 | -| 24 | [MD045 - Images should have alternate text (alt text)](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md045---images-should-have-alternate-text-alt-text) | 图片链接必须添加描述文本(即 `[]()` 的 `[]` 内必须有描述文字),这是为了让无法加载出图片的人看到图片的描述性文字。 | -| 25 | [MD046 - Code block style](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md046---code-block-style) | 文档中的代码块统一使用**三个反引号** ` ``` ` 进行包裹,**禁止**使用**缩进四格**风格的代码块。 | +## 联系我们 + +加入 Slack channel:[#sig-docs](https://slack.tidb.io/invite?team=tidb-community&channel=sig-docs&ref=pingcap-docs-cn) diff --git a/README.md b/README.md index dd51e87f8663..367a98bcc8ba 100755 --- a/README.md +++ b/README.md @@ -1,42 +1,25 @@ # TiDB 文档 -欢迎来到 [TiDB](https://github.com/pingcap/tidb) 文档库!这里存放的是 [PingCAP 官网 TiDB 中文文档](https://pingcap.com/docs-cn/stable/)的源文件。[官网英文文档](https://pingcap.com/docs/stable/)的源文件则存放于 [pingcap/docs](https://github.com/pingcap/docs)。如果你发现或遇到了 TiDB 的文档问题,可随时[提 Issue](https://github.com/pingcap/docs-cn/issues/new/choose) 来反馈,或者直接[提交 Pull Request](/CONTRIBUTING.md#pull-request-提交流程) 来进行修改。 - -## TiDB 文档结构 - -目前,TiDB 的文档维护以下四个版本,分别放置在相应的 branch: - -- `master`:最新开发版 -- `release-3.1`:3.1 Beta 版 -- `release-3.0`:最新稳定版 -- `release-2.1`:2.1 稳定版 - -TiDB 的文档结构如下: - -``` -├── TOC.md -├── how-to - ├── get-started - ├── deploy - ├── orchestrated - ├── ansible.md - ├── offline-ansible.md - ├── docker.md - ├── configure - ├── maintain - ├── troubleshoot - ├── ... -├── reference - ├── tools - ├── tidb-binlog - ├── ... -├── releases -├── tidb-in-kubernetes -├── faq -├── ... -... -``` +欢迎来到 [TiDB](https://github.com/pingcap/tidb) 文档仓库! + +这里存放的是 [PingCAP 官网 TiDB 中文文档](https://pingcap.com/docs-cn/stable/)的源文件。[官网英文文档](https://pingcap.com/docs/stable/)的源文件则存放于 [pingcap/docs](https://github.com/pingcap/docs)。 + +如果你发现或遇到了 TiDB 的文档问题,可随时[提 Issue](https://github.com/pingcap/docs-cn/issues/new/choose) 来反馈,或者直接[提交 Pull Request](/CONTRIBUTING.md#pull-request-提交流程) 来进行修改。 + +## TiDB 文档维护方式及版本说明 + +目前,TiDB 的文档维护在以下 branch,对应着官网文档的不同版本: + +| 文档仓库 branch | 对应 TiDB 文档版本 | +|:---------|:----------| +| [`master`](https://github.com/pingcap/docs-cn/tree/master) | dev 最新开发版 | +| [`release-4.0`](https://github.com/pingcap/docs-cn/tree/release-4.0) | 4.0 RC 版 | +| [`release-3.1`](https://github.com/pingcap/docs-cn/tree/release-3.1) | 3.1 稳定版 | +| [`release-3.0`](https://github.com/pingcap/docs-cn/tree/release-3.0) | 3.0 稳定版 | +| [`release-2.1`](https://github.com/pingcap/docs-cn/tree/release-2.1) | 2.1 稳定版 | ## 贡献文档 +[contribution-map](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs) + 你提交的第一个 [Pull Request](https://help.github.com/en/github/getting-started-with-github/github-glossary#pull-request) (PR) 合并以后,即可成为 TiDB 文档的 Contributor。查看 [TiDB 中文文档贡献指南](/CONTRIBUTING.md),开始你的贡献吧! diff --git a/TOC.md b/TOC.md index c1aa740b5aa3..1b79f2df1f7f 100644 --- a/TOC.md +++ b/TOC.md @@ -6,448 +6,555 @@ ## 目录 + 关于 TiDB - - [TiDB 简介](/overview.md) - + Benchmark 测试 - - [如何用 Sysbench 测试 TiDB](/benchmark/how-to-run-sysbench.md) - - [如何对 TiDB 进行 TPC-C 测试](/benchmark/how-to-run-tpcc.md) - - [Sysbench 性能对比 - v3.0 对比 v2.1](/benchmark/sysbench-v4.md) - - [TPC-C 性能对比 - v3.0 对比 v2.1](/benchmark/tpcc.md) - - [线上负载与 `Add Index` 相互影响测试](/benchmark/add-index-with-load.md) -+ 主要概念 - - [整体架构](/architecture.md) - + 核心特性 - - [水平扩展](/key-features.md#水平扩展) - - [高可用](/key-features.md#高可用) -+ 操作指南 - + 快速上手 - - [使用 Docker Compose 部署 TiDB](/how-to/get-started/deploy-tidb-from-docker-compose.md) - - [SQL 基本操作](/how-to/get-started/explore-sql.md) - - [读取历史数据](/how-to/get-started/read-historical-data.md) - - [TiDB Binlog 教程](/how-to/get-started/tidb-binlog.md) - - [TiDB Data Migration 教程](https://pingcap.com/docs-cn/tidb-data-migration/stable/get-started/) - - [TiDB Lightning 教程](/how-to/get-started/tidb-lightning.md) - - [TiSpark 教程](/how-to/get-started/tispark.md) - + 部署 - - [软硬件环境需求](/how-to/deploy/hardware-recommendations.md) - + 集群部署方式 - - [使用 Ansible 部署(推荐)](/how-to/deploy/orchestrated/ansible.md) - - [使用 Ansible 离线部署](/how-to/deploy/orchestrated/offline-ansible.md) - - [使用 Docker 部署](/how-to/deploy/orchestrated/docker.md) - + 跨地域冗余 - - [跨数据中心部署方案](/how-to/deploy/geographic-redundancy/overview.md) - - [配置集群拓扑](/how-to/deploy/geographic-redundancy/location-awareness.md) - - [使用 Ansible 部署 DM 集群](https://pingcap.com/docs-cn/tidb-data-migration/stable/deploy-a-dm-cluster-using-ansible/) - + 配置 - - [时区](/how-to/configure/time-zone.md) - - [内存控制](/how-to/configure/memory-control.md) - - [Placement Rules](/how-to/configure/placement-rules.md) - + 安全 - + 安全传输层协议 (TLS) - - [为 MySQL 客户端开启 TLS](/how-to/secure/enable-tls-clients.md) - - [为 TiDB 组件间开启 TLS](/how-to/secure/enable-tls-between-components.md) - - [生成自签名证书](/how-to/secure/generate-self-signed-certificates.md) - + 监控 - - [概述](/how-to/monitor/overview.md) - - [监控 TiDB 集群](/how-to/monitor/monitor-a-cluster.md) - + 迁移 - - [迁移工具使用指南](/reference/tools/user-guide.md) - + 从 MySQL 迁移 - - [以 Amazon Aurora MySQL 为例](/how-to/migrate/from-mysql-aurora.md) - - [从 CSV 迁移](/reference/tools/tidb-lightning/csv.md) - + 运维 - - [Ansible 常见运维操作](/how-to/maintain/ansible-operations.md) - + 备份与恢复 - - [使用 Mydumper/TiDB Lightning 进行备份与恢复](/how-to/maintain/backup-and-restore/mydumper-lightning.md) - - [使用 BR 进行备份与恢复](/reference/tools/br/br.md) - - [BR 备份与恢复场景示例](/reference/tools/br/use-cases.md) - + 定位异常查询 - - [定位慢查询](/how-to/maintain/identify-abnormal-queries/identify-slow-queries.md) - - [定位消耗系统资源多的查询](/how-to/maintain/identify-abnormal-queries/identify-expensive-queries.md) - + 扩容缩容 - - [使用 Ansible 扩容缩容](/how-to/scale/with-ansible.md) - + 升级 - - [升级至最新开发版](/how-to/upgrade/from-previous-version.md) - + 故障诊断 - - [集群配置诊断](/how-to/troubleshoot/cluster-setup.md) - - [TiDB Lightning 故障诊断](/how-to/troubleshoot/tidb-lightning.md) -+ 参考手册 - + SQL - - [与 MySQL 兼容性对比](/reference/mysql-compatibility.md) - + SQL 语言结构 - - [字面值](/reference/sql/language-structure/literal-values.md) - - [Schema 对象名](/reference/sql/language-structure/schema-object-names.md) - - [关键字和保留字](/reference/sql/language-structure/keywords-and-reserved-words.md) - - [用户自定义变量](/reference/sql/language-structure/user-defined-variables.md) - - [表达式语法](/reference/sql/language-structure/expression-syntax.md) - - [注释语法](/reference/sql/language-structure/comment-syntax.md) - + 表属性和列属性 - - [`AUTO_RANDOM`](/reference/sql/attributes/auto-random.md) - + 数据类型 - - [概述](/reference/sql/data-types/overview.md) - - [默认值](/reference/sql/data-types/default-values.md) - + 数值类型 - - [`BIT`](/reference/sql/data-types/numeric.md#bit-类型) - - [`BOOL|BOOLEAN`](/reference/sql/data-types/numeric.md#boolean-类型) - - [`TINYINT`](/reference/sql/data-types/numeric.md#tinyint-类型) - - [`SMALLINT`](/reference/sql/data-types/numeric.md#smallint-类型) - - [`MEDIUMINT`](/reference/sql/data-types/numeric.md#mediumint-类型) - - [`INT|INTEGER`](/reference/sql/data-types/numeric.md#integer-类型) - - [`BIGINT`](/reference/sql/data-types/numeric.md#bigint-类型) - - [`DECIMAL`](/reference/sql/data-types/numeric.md#decimal-类型) - - [`FLOAT`](/reference/sql/data-types/numeric.md#float-类型) - - [`DOUBLE`](/reference/sql/data-types/numeric.md#double-类型) - + 日期和时间类型 - - [`DATE`](/reference/sql/data-types/date-and-time.md#date-类型) - - [`DATETIME`](/reference/sql/data-types/date-and-time.md#datetime-类型) - - [`TIMESTAMP`](/reference/sql/data-types/date-and-time.md#timestamp-类型) - - [`TIME`](/reference/sql/data-types/date-and-time.md#time-类型) - - [`YEAR`](/reference/sql/data-types/date-and-time.md#year-类型) - + 字符串类型 - - [`CHAR`](/reference/sql/data-types/string.md#char-类型) - - [`VARCHAR`](/reference/sql/data-types/string.md#varchar-类型) - - [`TEXT`](/reference/sql/data-types/string.md#text-类型) - - [`LONGTEXT`](/reference/sql/data-types/string.md#longtext-类型) - - [`BINARY`](/reference/sql/data-types/string.md#binary-类型) - - [`VARBINARY`](/reference/sql/data-types/string.md#varbinary-类型) - - [`TINYBLOB`](/reference/sql/data-types/string.md#tinyblob-类型) - - [`BLOB`](/reference/sql/data-types/string.md#blob-类型) - - [`MEDIUMBLOB`](/reference/sql/data-types/string.md#mediumblob-类型) - - [`LONGBLOB`](/reference/sql/data-types/string.md#longblob-类型) - - [`ENUM`](/reference/sql/data-types/string.md#enum-类型) - - [`SET`](/reference/sql/data-types/string.md#set-类型) - - [JSON Type](/reference/sql/data-types/json.md) - + 函数与操作符 - - [函数与操作符概述](/reference/sql/functions-and-operators/reference.md) - - [表达式求值的类型转换](/reference/sql/functions-and-operators/type-conversion.md) - - [操作符](/reference/sql/functions-and-operators/operators.md) - - [控制流程函数](/reference/sql/functions-and-operators/control-flow-functions.md) - - [字符串函数](/reference/sql/functions-and-operators/string-functions.md) - - [数值函数与操作符](/reference/sql/functions-and-operators/numeric-functions-and-operators.md) - - [日期和时间函数](/reference/sql/functions-and-operators/date-and-time-functions.md) - - [位函数和操作符](/reference/sql/functions-and-operators/bit-functions-and-operators.md) - - [Cast 函数和操作符](/reference/sql/functions-and-operators/cast-functions-and-operators.md) - - [加密和压缩函数](/reference/sql/functions-and-operators/encryption-and-compression-functions.md) - - [信息函数](/reference/sql/functions-and-operators/information-functions.md) - - [JSON 函数](/reference/sql/functions-and-operators/json-functions.md) - - [GROUP BY 聚合函数](/reference/sql/functions-and-operators/aggregate-group-by-functions.md) - - [窗口函数](/reference/sql/functions-and-operators/window-functions.md) - - [其它函数](/reference/sql/functions-and-operators/miscellaneous-functions.md) - - [精度数学](/reference/sql/functions-and-operators/precision-math.md) - - [下推到 TiKV 的表达式列表](/reference/sql/functions-and-operators/expressions-pushed-down.md) - + SQL 语句 - - [`ADD COLUMN`](/reference/sql/statements/add-column.md) - - [`ADD INDEX`](/reference/sql/statements/add-index.md) - - [`ADMIN`](/reference/sql/statements/admin.md) - - [`ALTER DATABASE`](/reference/sql/statements/alter-database.md) - - [`ALTER TABLE`](/reference/sql/statements/alter-table.md) - - [`ALTER USER`](/reference/sql/statements/alter-user.md) - - [`ANALYZE TABLE`](/reference/sql/statements/analyze-table.md) - - [`BEGIN`](/reference/sql/statements/begin.md) - - [`COMMIT`](/reference/sql/statements/commit.md) - - [`CREATE DATABASE`](/reference/sql/statements/create-database.md) - - [`CREATE INDEX`](/reference/sql/statements/create-index.md) - - [`CREATE SEQUENCE`](/reference/sql/statements/create-sequence.md) - - [`CREATE TABLE LIKE`](/reference/sql/statements/create-table-like.md) - - [`CREATE TABLE`](/reference/sql/statements/create-table.md) - - [`CREATE USER`](/reference/sql/statements/create-user.md) - - [`CREATE VIEW`](/reference/sql/statements/create-view.md) - - [`DEALLOCATE`](/reference/sql/statements/deallocate.md) - - [`DELETE`](/reference/sql/statements/delete.md) - - [`DESC`](/reference/sql/statements/desc.md) - - [`DESCRIBE`](/reference/sql/statements/describe.md) - - [`DO`](/reference/sql/statements/do.md) - - [`DROP COLUMN`](/reference/sql/statements/drop-column.md) - - [`DROP DATABASE`](/reference/sql/statements/drop-database.md) - - [`DROP INDEX`](/reference/sql/statements/drop-index.md) - - [`DROP SEQUENCE`](/reference/sql/statements/drop-sequence.md) - - [`DROP TABLE`](/reference/sql/statements/drop-table.md) - - [`DROP USER`](/reference/sql/statements/drop-user.md) - - [`DROP VIEW`](/reference/sql/statements/drop-view.md) - - [`EXECUTE`](/reference/sql/statements/execute.md) - - [`EXPLAIN ANALYZE`](/reference/sql/statements/explain-analyze.md) - - [`EXPLAIN`](/reference/sql/statements/explain.md) - - [`FLASHBACK TABLE`](/reference/sql/statements/flashback-table.md) - - [`FLUSH PRIVILEGES`](/reference/sql/statements/flush-privileges.md) - - [`FLUSH STATUS`](/reference/sql/statements/flush-status.md) - - [`FLUSH TABLES`](/reference/sql/statements/flush-tables.md) - - [`GRANT `](/reference/sql/statements/grant-privileges.md) - - [`INSERT`](/reference/sql/statements/insert.md) - - [`KILL [TIDB]`](/reference/sql/statements/kill.md) - - [`LOAD DATA`](/reference/sql/statements/load-data.md) - - [`MODIFY COLUMN`](/reference/sql/statements/modify-column.md) - - [`PREPARE`](/reference/sql/statements/prepare.md) - - [`RECOVER TABLE`](/reference/sql/statements/recover-table.md) - - [`RENAME INDEX`](/reference/sql/statements/rename-index.md) - - [`RENAME TABLE`](/reference/sql/statements/rename-table.md) - - [`REPLACE`](/reference/sql/statements/replace.md) - - [`REVOKE `](/reference/sql/statements/revoke-privileges.md) - - [`ROLLBACK`](/reference/sql/statements/rollback.md) - - [`SELECT`](/reference/sql/statements/select.md) - - [`SET [NAMES|CHARACTER SET]`](/reference/sql/statements/set-names.md) - - [`SET PASSWORD`](/reference/sql/statements/set-password.md) - - [`SET TRANSACTION`](/reference/sql/statements/set-transaction.md) - - [`SET [GLOBAL|SESSION] `](/reference/sql/statements/set-variable.md) - - [`SHOW CHARACTER SET`](/reference/sql/statements/show-character-set.md) - - [`SHOW COLLATION`](/reference/sql/statements/show-collation.md) - - [`SHOW [FULL] COLUMNS FROM`](/reference/sql/statements/show-columns-from.md) - - [`SHOW CREATE SEQUENCE`](/reference/sql/statements/show-create-sequence.md) - - [`SHOW CREATE TABLE`](/reference/sql/statements/show-create-table.md) - - [`SHOW CREATE USER`](/reference/sql/statements/show-create-user.md) - - [`SHOW DATABASES`](/reference/sql/statements/show-databases.md) - - [`SHOW ENGINES`](/reference/sql/statements/show-engines.md) - - [`SHOW ERRORS`](/reference/sql/statements/show-errors.md) - - [`SHOW [FULL] FIELDS FROM`](/reference/sql/statements/show-fields-from.md) - - [`SHOW GRANTS`](/reference/sql/statements/show-grants.md) - - [`SHOW INDEXES [FROM|IN]`](/reference/sql/statements/show-indexes.md) - - [`SHOW INDEX [FROM|IN]`](/reference/sql/statements/show-index.md) - - [`SHOW KEYS [FROM|IN]`](/reference/sql/statements/show-keys.md) - - [`SHOW PRIVILEGES`](/reference/sql/statements/show-privileges.md) - - [`SHOW [FULL] PROCESSSLIST`](/reference/sql/statements/show-processlist.md) - - [`SHOW SCHEMAS`](/reference/sql/statements/show-schemas.md) - - [`SHOW [FULL] TABLES`](/reference/sql/statements/show-tables.md) - - [`SHOW TABLE REGIONS`](/reference/sql/statements/show-table-regions.md) - - [`SHOW TABLE STATUS`](/reference/sql/statements/show-table-status.md) - - [`SHOW [GLOBAL|SESSION] VARIABLES`](/reference/sql/statements/show-variables.md) - - [`SHOW WARNINGS`](/reference/sql/statements/show-warnings.md) - - [`SPLIT REGION`](/reference/sql/statements/split-region.md) - - [`START TRANSACTION`](/reference/sql/statements/start-transaction.md) - - [`TRACE`](/reference/sql/statements/trace.md) - - [`TRUNCATE`](/reference/sql/statements/truncate.md) - - [`UPDATE`](/reference/sql/statements/update.md) - - [`USE`](/reference/sql/statements/use.md) - - [约束](/reference/sql/constraints.md) - - [生成列](/reference/sql/generated-columns.md) - - [分区表](/reference/sql/partitioning.md) - - [字符集](/reference/sql/character-set.md) - - [SQL 模式](/reference/sql/sql-mode.md) - - [SQL 诊断](/reference/system-databases/sql-diagnosis.md) - - [视图](/reference/sql/view.md) - + 配置 - + tidb-server - - [MySQL 系统变量](/reference/configuration/tidb-server/mysql-variables.md) - - [TiDB 特定系统变量](/reference/configuration/tidb-server/tidb-specific-variables.md) - - [配置参数](/reference/configuration/tidb-server/configuration.md) - - [配置文件描述](/reference/configuration/tidb-server/configuration-file.md) - + pd-server - - [配置参数](/reference/configuration/pd-server/configuration.md) - - [配置文件描述](/reference/configuration/pd-server/configuration-file.md) - + tikv-server - - [配置参数](/reference/configuration/tikv-server/configuration.md) - - [配置文件描述](/reference/configuration/tikv-server/configuration-file.md) - + 安全 - - [与 MySQL 的安全特性差异](/reference/security/compatibility.md) - - [TiDB 数据库权限管理](/reference/security/privilege-system.md) - - [TiDB 用户账户管理](/reference/security/user-account-management.md) - - [基于角色的访问控制](/reference/security/role-based-access-control.md) - - [TiDB 证书鉴权使用指南](/reference/security/cert-based-authentication.md) - + 事务 - - [事务概览](/reference/transactions/overview.md) - - [隔离级别](/reference/transactions/transaction-isolation.md) - - [乐观事务](/reference/transactions/transaction-optimistic.md) - - [悲观事务](/reference/transactions/transaction-pessimistic.md) - + 系统数据库 - - [`mysql`](/reference/system-databases/mysql.md) - - [`information_schema`](/reference/system-databases/information-schema.md) - + `sql-diagnosis` - - [`cluster_info`](/reference/system-databases/cluster-info.md) - - [`cluster_hardware`](/reference/system-databases/cluster-hardware.md) - - [`cluster_config`](/reference/system-databases/cluster-config.md) - - [`cluster_load`](/reference/system-databases/cluster-load.md) - - [`cluster_systeminfo`](/reference/system-databases/cluster-systeminfo.md) - - [`cluster_log`](/reference/system-databases/cluster-log.md) - - [`metrics_schema`](/reference/system-databases/metrics-schema.md) - - [`metrics_tables`](/reference/system-databases/metrics-tables.md) - - [`metrics_summary`](/reference/system-databases/metrics-summary.md) - - [`inspection_result`](/reference/system-databases/inspection-result.md) - - [`inspection_summary`](/reference/system-databases/inspection-summary.md) - - [错误码](/reference/error-codes.md) - - [支持的连接器和 API](/reference/supported-clients.md) - + 垃圾回收 (GC) - - [GC 机制简介](/reference/garbage-collection/overview.md) - - [GC 配置](/reference/garbage-collection/configuration.md) - + 性能调优 - - [SQL 优化流程](/reference/performance/sql-optimizer-overview.md) - - [理解 TiDB 执行计划](/reference/performance/understanding-the-query-execution-plan.md) - - [执行计划绑定](/reference/performance/execution-plan-bind.md) - - [Join Reorder 算法简介](/reference/performance/join-reorder.md) - - [统计信息概述](/reference/performance/statistics.md) - - [Optimizer Hints](/reference/performance/optimizer-hints.md) - - [Follower Read](/reference/performance/follower-read.md) - - [使用 SQL 语句检查 TiDB 集群状态](/reference/performance/check-cluster-status-using-sql-statements.md) - - [使用 Index Merge 方式访问表](/reference/performance/index-merge.md) - - [Statement Summary Table](/reference/performance/statement-summary.md) - - [TiKV 调优](/reference/performance/tune-tikv.md) - - [TiDB 最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/) - + 监控指标 - - [Overview 面板](/reference/key-monitoring-metrics/overview-dashboard.md) - - [TiDB 面板](/reference/key-monitoring-metrics/tidb-dashboard.md) - - [PD 面板](/reference/key-monitoring-metrics/pd-dashboard.md) - - [TiKV 面板](/reference/key-monitoring-metrics/tikv-dashboard.md) - - [报警规则](/reference/alert-rules.md) + + [TiDB 简介](/overview.md) + + [What's New in TiDB 4.0](/whats-new-in-tidb-4.0.md) + + [基本功能](/basic-features.md) + + 兼容性 + + [与 MySQL 的兼容性](/mysql-compatibility.md) + + [使用限制](/tidb-limitations.md) + + [荣誉列表](/credits.md) ++ 快速上手 + + [快速上手指南](/quick-start-with-tidb.md) + + [SQL 基本操作](/basic-sql-operations.md) ++ 部署集群 + + [软硬件环境需求](/hardware-and-software-requirements.md) + + [环境与系统配置检查](/check-before-deployment.md) + + 配置拓扑结构 + + [最小部署拓扑结构](/minimal-deployment-topology.md) + + [TiFlash 部署拓扑](/tiflash-deployment-topology.md) + + [TiCDC 部署拓扑](/ticdc-deployment-topology.md) + + [TiDB Binlog 部署拓扑](/tidb-binlog-deployment-topology.md) + + [跨机房部署拓扑结构](/geo-distributed-deployment-topology.md) + + [混合部署拓扑结构](/hybrid-deployment-topology.md) + + 安装与启动 + + Linux 环境 + + [使用 TiUP 部署(推荐)](/production-deployment-using-tiup.md) + + [使用 TiUP 离线部署(推荐)](/production-offline-deployment-using-tiup.md) + + [使用 Ansible 部署](/online-deployment-using-ansible.md) + + [使用 Ansible 离线部署](/offline-deployment-using-ansible.md) + + [验证集群状态](/post-installation-check.md) + + 性能测试报告及重现指南 + + [如何用 Sysbench 测试 TiDB](/benchmark/benchmark-tidb-using-sysbench.md) + + [如何对 TiDB 进行 TPC-C 测试](/benchmark/benchmark-tidb-using-tpcc.md) + + [Sysbench 性能对比 - v4.0 对比 v3.0](/benchmark/benchmark-sysbench-v4-vs-v3.md) + + [TPC-H 性能对比 - v4.0 对比 v3.0](/benchmark/v4.0-performance-benchmarking-with-tpch.md) + + [TPC-C 性能对比 - v4.0 对比 v3.0](/benchmark/v4.0-performance-benchmarking-with-tpcc.md) + + [Sysbench 性能对比 - v3.0 对比 v2.1](/benchmark/v3.0-performance-benchmarking-with-sysbench.md) + + [TPC-C 性能对比 - v3.0 对比 v2.1](/benchmark/v3.0-performance-benchmarking-with-tpcc.md) + + [线上负载与 ADD INDEX 相互影响测试](/benchmark/online-workloads-and-add-index-operations.md) ++ 数据迁移 + + [概述](/migration-overview.md) + + 从 MySQL 迁移至 TiDB + + [从 Mydumper 文件迁移](/migrate-from-mysql-mydumper-files.md) + + [使用 DM 工具从 Amazon Aurora MySQL 迁移](/migrate-from-aurora-mysql-database.md) + + 从 CSV 文件迁移至 TiDB + + [使用 TiDB Lightning 导入 CSV 文件](/tidb-lightning/migrate-from-csv-using-tidb-lightning.md) + + [使用 LOAD DATA 语句导入 CSV 文件](/sql-statements/sql-statement-load-data.md) + + [从 SQL 文件迁移到 TiDB](/migrate-from-mysql-mydumper-files.md) ++ 运维操作 + + 升级 TiDB 版本 + + [使用 TiUP 升级(推荐)](/upgrade-tidb-using-tiup.md) + + [使用 TiUP 离线升级(推荐)](/upgrade-tidb-using-tiup-offline.md) + + [使用 TiDB Operator](https://docs.pingcap.com/zh/tidb-in-kubernetes/stable/upgrade-a-tidb-cluster) + + [使用 TiDB Ansible](/upgrade-tidb-using-ansible.md) + + 扩缩容 + + [使用 TiUP(推荐)](/scale-tidb-using-tiup.md) + + [使用 TiDB Ansible](/scale-tidb-using-ansible.md) + + [使用 TiDB Operator](https://docs.pingcap.com/zh/tidb-in-kubernetes/stable/scale-a-tidb-cluster) + + 备份与恢复 + + [使用 Mydumper 和 TiDB Lightning 进行备份与恢复](/backup-and-restore-using-mydumper-lightning.md) + + [使用 Dumpling 导出或备份 TiDB 数据](/export-or-backup-using-dumpling.md) + + 使用 BR 工具 + + [使用 BR 进行备份与恢复](/br/backup-and-restore-tool.md) + + [BR 备份与恢复场景示例](/br/backup-and-restore-use-cases.md) + + [日常巡检](/daily-check.md) + + [TiCDC 运维操作及任务管理](/ticdc/manage-ticdc.md) + + [TiFlash 常用运维操作](/tiflash/maintain-tiflash.md) + + [TiUP 常用运维操作](/maintain-tidb-using-tiup.md) + + [Ansible 常用运维操作](/maintain-tidb-using-ansible.md) ++ 监控与告警 + + [监控框架概述](/tidb-monitoring-framework.md) + + [监控 API](/tidb-monitoring-api.md) + + [手动部署监控](/deploy-monitoring-services.md) + + [TiDB 集群报警规则与处理方法](/alert-rules.md) + + [TiFlash 报警规则与处理方法](/tiflash/tiflash-alert-rules.md) ++ 故障诊断 + + [定位慢查询](/identify-slow-queries.md) + + [SQL 诊断](/system-tables/system-table-sql-diagnostics.md) + + [定位消耗系统资源多的查询](/identify-expensive-queries.md) + + [SQL 语句统计](/statement-summary-tables.md) + + [TiDB 集群常见问题](/troubleshoot-tidb-cluster.md) + + [TiDB 集群问题导图](/tidb-troubleshooting-map.md) + + [热点问题处理](/troubleshoot-hot-spot-issues.md) + + [CPU 占用过多导致读写延迟增加](/troubleshoot-cpu-issues.md) + + [写冲突与写性能下降](/troubleshoot-write-conflicts.md) + + [磁盘 I/O 过高](/troubleshoot-high-disk-io.md) + + [锁冲突与 TTL 超时](/troubleshoot-lock-conflicts.md) + + [TiCDC 常见问题](/ticdc/troubleshoot-ticdc.md) + + [TiFlash 常见问题](/tiflash/troubleshoot-tiflash.md) ++ 性能调优 + + 系统调优 + + [操作系统性能参数调优](/tune-operating-system.md) + + 软件调优 + + 配置 + + [TiKV 线程调优](/tune-tikv-thread-performance.md) + + [TiKV 内存调优](/tune-tikv-memory-performance.md) + + [TiKV Follower Read](/follower-read.md) + + [TiFlash 调优](/tiflash/tune-tiflash-performance.md) + + [下推计算结果缓存](/coprocessor-cache.md) + + SQL 性能调优 + + [SQL 性能调优概览](/sql-tuning-overview.md) + + [理解 TiDB 执行计划](/query-execution-plan.md) + + SQL 优化 + + [SQL 优化流程简介](/sql-optimization-concepts.md) + + 逻辑优化 + + [逻辑优化概览](/sql-logical-optimization.md) + + [子查询相关的优化](/subquery-optimization.md) + + [列裁剪](/column-pruning.md) + + [关联子查询去关联](/correlated-subquery-optimization.md) + + [Max/Min 消除](/max-min-eliminate.md) + + [谓词下推](/predicate-push-down.md) + + [分区裁剪](/partition-pruning.md) + + [TopN 和 Limit 下推](/topn-limit-push-down.md) + + [Join Reorder](/join-reorder.md) + + 物理优化 + + [物理优化概览](/sql-physical-optimization.md) + + [索引的选择](/choose-index.md) + + [统计信息简介](/statistics.md) + + [错误索引的解决方案](/wrong-index-solution.md) + + [Distinct 优化](/agg-distinct-optimization.md) + + [执行计划缓存](/sql-prepare-plan-cache.md) + + 控制执行计划 + + [控制执行计划概览](/control-execution-plan.md) + + [Optimizer Hints](/optimizer-hints.md) + + [执行计划管理](/sql-plan-management.md) + + [优化规则及表达式下推的黑名单](/blacklist-control-plan.md) ++ 教程 + + [同城多中心部署](/multi-data-centers-in-one-city-deployment.md) + + [两地三中心部署](/three-data-centers-in-two-cities-deployment.md) + 最佳实践 - - [HAProxy 最佳实践](/reference/best-practices/haproxy.md) - - [Java 应用开发最佳实践](/reference/best-practices/java-app.md) - - [高并发写入场景最佳实践](/reference/best-practices/high-concurrency.md) - - [Grafana 监控最佳实践](/reference/best-practices/grafana-monitor.md) - - [PD 调度策略最佳实践](/reference/best-practices/pd-scheduling.md) - - [海量 Region 集群调优最佳实践](/reference/best-practices/massive-regions.md) - + [TiSpark 使用指南](/reference/tispark.md) - + TiFlash - - [概述](/reference/tiflash/overview.md) - - [部署集群](/reference/tiflash/deploy.md) - - [使用 TiFlash](/reference/tiflash/use-tiflash.md) - - [运维集群](/reference/tiflash/maintain.md) - - [监控集群](/reference/tiflash/monitor.md) - - [扩缩容集群](/reference/tiflash/scale.md) - - [升级节点](/reference/tiflash/upgrade.md) - - [配置参数](/reference/tiflash/configuration.md) - - [报警规则](/reference/tiflash/alert-rules.md) - - [性能调优](/reference/tiflash/tune-performance.md) - - [FAQ](/reference/tiflash/faq.md) + + [TiDB 最佳实践](/best-practices/tidb-best-practices.md) + + [Java 应用开发最佳实践](/best-practices/java-app-best-practices.md) + + [HAProxy 最佳实践](/best-practices/haproxy-best-practices.md) + + [高并发写入场景最佳实践](/best-practices/high-concurrency-best-practices.md) + + [Grafana 监控最佳实践](/best-practices/grafana-monitor-best-practices.md) + + [PD 调度策略最佳实践](/best-practices/pd-scheduling-best-practices.md) + + [海量 Region 集群调优](/best-practices/massive-regions-best-practices.md) + + [Placement Rules 使用文档](/configure-placement-rules.md) + + [Load Base Split 使用文档](/configure-load-base-split.md) + + [Store Limit 使用文档](/configure-store-limit.md) ++ TiDB 生态工具 + + [功能概览](/ecosystem-tool-user-guide.md) + + [适用场景](/ecosystem-tool-user-case.md) + + [工具下载](/download-ecosystem-tools.md) + + Backup & Restore (BR) + + [BR 常见问题](/br/backup-and-restore-faq.md) + + [使用 BR 进行备份和恢复](/br/backup-and-restore-tool.md) + + [BR 备份与恢复场景示例](/br/backup-and-restore-use-cases.md) + TiDB Binlog - - [概述](/reference/tidb-binlog/overview.md) - - [部署使用](/reference/tidb-binlog/deploy.md) - - [运维管理](/reference/tidb-binlog/maintain.md) - - [配置说明](/reference/tidb-binlog/configs.md) - - [Pump](/reference/tidb-binlog/configs.md#pump) - - [Drainer](/reference/tidb-binlog/configs.md#drainer) - - [版本升级](/reference/tidb-binlog/upgrade.md) - - [监控告警](/reference/tidb-binlog/monitor.md) - - [增量恢复](/reference/tidb-binlog/reparo.md) - - [Kafka 自定义开发](/reference/tidb-binlog/binlog-slave-client.md) - - [TiDB Binlog Relay Log](/reference/tidb-binlog/relay-log.md) - - [集群间双向同步](/reference/tidb-binlog/bi-repl.md) - - [术语表](/reference/tidb-binlog/glossary.md) + + [概述](/tidb-binlog/tidb-binlog-overview.md) + + [快速上手](/tidb-binlog/get-started-with-tidb-binlog.md) + + [部署使用](/tidb-binlog/deploy-tidb-binlog.md) + + [运维管理](/tidb-binlog/maintain-tidb-binlog-cluster.md) + + [配置说明](/tidb-binlog/tidb-binlog-configuration-file.md) + + [Pump](/tidb-binlog/tidb-binlog-configuration-file.md#pump) + + [Drainer](/tidb-binlog/tidb-binlog-configuration-file.md#drainer) + + [版本升级](/tidb-binlog/upgrade-tidb-binlog.md) + + [监控告警](/tidb-binlog/monitor-tidb-binlog-cluster.md) + + [增量恢复](/tidb-binlog/tidb-binlog-reparo.md) + + [binlogctl 工具](/tidb-binlog/binlog-control.md) + + [Kafka 自定义开发](/tidb-binlog/binlog-slave-client.md) + + [TiDB Binlog Relay Log](/tidb-binlog/tidb-binlog-relay-log.md) + + [集群间双向同步](/tidb-binlog/bidirectional-replication-between-tidb-clusters.md) + + [术语表](/tidb-binlog/tidb-binlog-glossary.md) + 故障诊断 - - [故障诊断](/reference/tidb-binlog/troubleshoot/binlog.md) - - [常见错误修复](/reference/tidb-binlog/troubleshoot/error-handling.md) - - [FAQ](/reference/tidb-binlog/faq.md) - + 周边工具 - - [工具使用指南](/reference/tools/user-guide.md) - - [Mydumper](/reference/tools/mydumper.md) - - [Loader](/reference/tools/loader.md) - - [Syncer](/reference/tools/syncer.md) - - [Data Migration](https://pingcap.com/docs-cn/tidb-data-migration/stable/) - + TiDB Lightning - - [概述](/reference/tools/tidb-lightning/overview.md) - - [部署执行](/reference/tools/tidb-lightning/deployment.md) - - [参数说明](/reference/tools/tidb-lightning/config.md) - - [断点续传](/reference/tools/tidb-lightning/checkpoints.md) - - [表库过滤](/reference/tools/tidb-lightning/table-filter.md) - - [CSV 支持](/reference/tools/tidb-lightning/csv.md) - - [TiDB-backend](/reference/tools/tidb-lightning/tidb-backend.md) - - [Web 界面](/reference/tools/tidb-lightning/web.md) - - [监控告警](/reference/tools/tidb-lightning/monitor.md) - - [故障诊断](/how-to/troubleshoot/tidb-lightning.md) - - [FAQ](/faq/tidb-lightning.md) - - [术语表](/reference/tools/tidb-lightning/glossary.md) - + TiCDC - - [概述](/reference/tools/ticdc/overview.md) - - [部署使用](/reference/tools/ticdc/deploy.md) - - [集群和同步任务管理](/reference/tools/ticdc/manage.md) - - [Sink URI 配置规则](/reference/tools/ticdc/sink.md) - + sync-diff-inspector - - [概述](/reference/tools/sync-diff-inspector/overview.md) - - [不同库名或表名的数据校验](/reference/tools/sync-diff-inspector/route-diff.md) - - [分库分表场景下的数据校验](/reference/tools/sync-diff-inspector/shard-diff.md) - - [TiDB 主从集群的数据校验](/reference/tools/sync-diff-inspector/tidb-diff.md) - - [PD Control](/reference/tools/pd-control.md) - - [PD Recover](/reference/tools/pd-recover.md) - - [TiKV Control](/reference/tools/tikv-control.md) - - [TiDB Controller](/reference/tools/tidb-control.md) - - [工具下载](/reference/tools/download.md) -- [TiDB in Kubernetes](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/) -+ 常见问题 (FAQ) - - [TiDB FAQ](/faq/tidb.md) - - [TiDB Lightning FAQ](/faq/tidb-lightning.md) - - [升级 FAQ](/faq/upgrade.md) -+ 技术支持 - - [支持渠道](/support-resources.md) - - [反馈问题](/report-issue.md) -+ [贡献](/contribute.md) - - [贡献代码](/contribute.md#成为-tidb-的贡献者) - - [改进文档](/contribute.md#改进文档) -+ [TiDB 路线图](/roadmap.md) -+ [版本发布历史](/releases/rn.md) + + [故障诊断](/tidb-binlog/troubleshoot-tidb-binlog.md) + + [常见错误修复](/tidb-binlog/handle-tidb-binlog-errors.md) + + [FAQ](/tidb-binlog/tidb-binlog-faq.md) + + TiDB Lightning + + [概述](/tidb-lightning/tidb-lightning-overview.md) + + [快速上手教程](/get-started-with-tidb-lightning.md) + + [部署执行](/tidb-lightning/deploy-tidb-lightning.md) + + [参数说明](/tidb-lightning/tidb-lightning-configuration.md) + + 主要功能 + + [断点续传](/tidb-lightning/tidb-lightning-checkpoints.md) + + [表库过滤](/tidb-lightning/tidb-lightning-table-filter.md) + + [CSV 支持](/tidb-lightning/migrate-from-csv-using-tidb-lightning.md) + + [TiDB-backend](/tidb-lightning/tidb-lightning-tidb-backend.md) + + [Web 界面](/tidb-lightning/tidb-lightning-web-interface.md) + + [监控告警](/tidb-lightning/monitor-tidb-lightning.md) + + [故障诊断](/troubleshoot-tidb-lightning.md) + + [FAQ](/tidb-lightning/tidb-lightning-faq.md) + + [术语表](/tidb-lightning/tidb-lightning-glossary.md) + + [TiCDC](/ticdc/ticdc-overview.md) + + sync-diff-inspector + + [概述](/sync-diff-inspector/sync-diff-inspector-overview.md) + + [不同库名或表名的数据校验](/sync-diff-inspector/route-diff.md) + + [分库分表场景下的数据校验](/sync-diff-inspector/shard-diff.md) + + [TiDB 主从集群的数据校验](/sync-diff-inspector/upstream-downstream-diff.md) + + [Loader](/loader-overview.md) + + [Mydumper](/mydumper-overview.md) + + [Syncer](/syncer-overview.md) + + TiSpark + + [TiSpark 快速上手](/get-started-with-tispark.md) + + [TiSpark 用户指南](/tispark-overview.md) ++ 参考指南 + + 架构 + + [概述](/tidb-architecture.md) + + [存储](/tidb-storage.md) + + [计算](/tidb-computing.md) + + [调度](/tidb-scheduling.md) + + 监控指标 + + [Overview 面板](/grafana-overview-dashboard.md) + + [TiDB 面板](/grafana-tidb-dashboard.md) + + [PD 面板](/grafana-pd-dashboard.md) + + [TiKV 面板](/grafana-tikv-dashboard.md) + + [TiFlash 监控指标](/tiflash/monitor-tiflash.md) + + 安全加固 + + [为 TiDB 客户端服务端间通信开启加密传输](/enable-tls-between-clients-and-servers.md) + + [为 TiDB 组件间通信开启加密传输](/enable-tls-between-components.md) + + [生成自签名证书](/generate-self-signed-certificates.md) + + 权限 + + [与 MySQL 安全特性差异](/security-compatibility-with-mysql.md) + + [权限管理](/privilege-management.md) + + [TiDB 用户账户管理](/user-account-management.md) + + [基于角色的访问控制](/role-based-access-control.md) + + [TiDB 证书鉴权使用指南](/certificate-authentication.md) + + SQL + + SQL 语言结构和语法 + + 属性 + + [AUTO_INCREMENT](/auto-increment.md) + + [AUTO_RANDOM](/auto-random.md) + + [字面值](/literal-values.md) + + [Schema 对象名](/schema-object-names.md) + + [关键字](/keywords.md) + + [用户自定义变量](/user-defined-variables.md) + + [表达式语法](/expression-syntax.md) + + [注释语法](/comment-syntax.md) + + SQL 语句 + - [`ADD COLUMN`](/sql-statements/sql-statement-add-column.md) + - [`ADD INDEX`](/sql-statements/sql-statement-add-index.md) + - [`ADMIN`](/sql-statements/sql-statement-admin.md) + - [`ALTER DATABASE`](/sql-statements/sql-statement-alter-database.md) + - [`ALTER INSTANCE`](/sql-statements/sql-statement-alter-instance.md) + - [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md) + - [`ALTER USER`](/sql-statements/sql-statement-alter-user.md) + - [`ANALYZE TABLE`](/sql-statements/sql-statement-analyze-table.md) + - [`BEGIN`](/sql-statements/sql-statement-begin.md) + - [`CHANGE COLUMN`](/sql-statements/sql-statement-change-column.md) + - [`CHANGE DRAINER`](/sql-statements/sql-statement-change-drainer.md) + - [`CHANGE PUMP`](/sql-statements/sql-statement-change-pump.md) + - [`COMMIT`](/sql-statements/sql-statement-commit.md) + - [`CREATE BINDING`](/sql-statements/sql-statement-create-binding.md) + - [`CREATE DATABASE`](/sql-statements/sql-statement-create-database.md) + - [`CREATE INDEX`](/sql-statements/sql-statement-create-index.md) + - [`CREATE SEQUENCE`](/sql-statements/sql-statement-create-sequence.md) + - [`CREATE TABLE LIKE`](/sql-statements/sql-statement-create-table-like.md) + - [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) + - [`CREATE USER`](/sql-statements/sql-statement-create-user.md) + - [`CREATE VIEW`](/sql-statements/sql-statement-create-view.md) + - [`DEALLOCATE`](/sql-statements/sql-statement-deallocate.md) + - [`DELETE`](/sql-statements/sql-statement-delete.md) + - [`DESC`](/sql-statements/sql-statement-desc.md) + - [`DESCRIBE`](/sql-statements/sql-statement-describe.md) + - [`DO`](/sql-statements/sql-statement-do.md) + - [`DROP BINDING`](/sql-statements/sql-statement-drop-binding.md) + - [`DROP COLUMN`](/sql-statements/sql-statement-drop-column.md) + - [`DROP DATABASE`](/sql-statements/sql-statement-drop-database.md) + - [`DROP INDEX`](/sql-statements/sql-statement-drop-index.md) + - [`DROP SEQUENCE`](/sql-statements/sql-statement-drop-sequence.md) + - [`DROP STATS`](/sql-statements/sql-statement-drop-stats.md) + - [`DROP TABLE`](/sql-statements/sql-statement-drop-table.md) + - [`DROP USER`](/sql-statements/sql-statement-drop-user.md) + - [`DROP VIEW`](/sql-statements/sql-statement-drop-view.md) + - [`EXECUTE`](/sql-statements/sql-statement-execute.md) + - [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) + - [`EXPLAIN`](/sql-statements/sql-statement-explain.md) + - [`FLASHBACK TABLE`](/sql-statements/sql-statement-flashback-table.md) + - [`FLUSH PRIVILEGES`](/sql-statements/sql-statement-flush-privileges.md) + - [`FLUSH STATUS`](/sql-statements/sql-statement-flush-status.md) + - [`FLUSH TABLES`](/sql-statements/sql-statement-flush-tables.md) + - [`GRANT `](/sql-statements/sql-statement-grant-privileges.md) + - [`INSERT`](/sql-statements/sql-statement-insert.md) + - [`KILL [TIDB]`](/sql-statements/sql-statement-kill.md) + - [`LOAD DATA`](/sql-statements/sql-statement-load-data.md) + - [`LOAD STATS`](/sql-statements/sql-statement-load-stats.md) + - [`MODIFY COLUMN`](/sql-statements/sql-statement-modify-column.md) + - [`PREPARE`](/sql-statements/sql-statement-prepare.md) + - [`RECOVER TABLE`](/sql-statements/sql-statement-recover-table.md) + - [`RENAME INDEX`](/sql-statements/sql-statement-rename-index.md) + - [`RENAME TABLE`](/sql-statements/sql-statement-rename-table.md) + - [`REPLACE`](/sql-statements/sql-statement-replace.md) + - [`REVOKE `](/sql-statements/sql-statement-revoke-privileges.md) + - [`ROLLBACK`](/sql-statements/sql-statement-rollback.md) + - [`SELECT`](/sql-statements/sql-statement-select.md) + - [`SET [NAMES|CHARACTER SET]`](/sql-statements/sql-statement-set-names.md) + - [`SET PASSWORD`](/sql-statements/sql-statement-set-password.md) + - [`SET ROLE`](/sql-statements/sql-statement-set-role.md) + - [`SET TRANSACTION`](/sql-statements/sql-statement-set-transaction.md) + - [`SET [GLOBAL|SESSION] `](/sql-statements/sql-statement-set-variable.md) + - [`SHOW ANALYZE STATUS`](/sql-statements/sql-statement-show-analyze-status.md) + - [`SHOW BINDINGS`](/sql-statements/sql-statement-show-bindings.md) + - [`SHOW BUILTINS`](/sql-statements/sql-statement-show-builtins.md) + - [`SHOW CHARACTER SET`](/sql-statements/sql-statement-show-character-set.md) + - [`SHOW COLLATION`](/sql-statements/sql-statement-show-collation.md) + - [`SHOW [FULL] COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md) + - [`SHOW CONFIG`](/sql-statements/sql-statement-show-config.md) + - [`SHOW CREATE SEQUENCE`](/sql-statements/sql-statement-show-create-sequence.md) + - [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) + - [`SHOW CREATE USER`](/sql-statements/sql-statement-show-create-user.md) + - [`SHOW DATABASES`](/sql-statements/sql-statement-show-databases.md) + - [`SHOW DRAINER STATUS`](/sql-statements/sql-statement-show-drainer-status.md) + - [`SHOW ENGINES`](/sql-statements/sql-statement-show-engines.md) + - [`SHOW ERRORS`](/sql-statements/sql-statement-show-errors.md) + - [`SHOW [FULL] FIELDS FROM`](/sql-statements/sql-statement-show-fields-from.md) + - [`SHOW GRANTS`](/sql-statements/sql-statement-show-grants.md) + - [`SHOW INDEX [FROM|IN]`](/sql-statements/sql-statement-show-index.md) + - [`SHOW INDEXES [FROM|IN]`](/sql-statements/sql-statement-show-indexes.md) + - [`SHOW KEYS [FROM|IN]`](/sql-statements/sql-statement-show-keys.md) + - [`SHOW MASTER STATUS`](/sql-statements/sql-statement-show-master-status.md) + - [`SHOW PLUGINS`](/sql-statements/sql-statement-show-plugins.md) + - [`SHOW PRIVILEGES`](/sql-statements/sql-statement-show-privileges.md) + - [`SHOW [FULL] PROCESSSLIST`](/sql-statements/sql-statement-show-processlist.md) + - [`SHOW PROFILES`](/sql-statements/sql-statement-show-profiles.md) + - [`SHOW PUMP STATUS`](/sql-statements/sql-statement-show-pump-status.md) + - [`SHOW SCHEMAS`](/sql-statements/sql-statement-show-schemas.md) + - [`SHOW STATS_HISTOGRAMS`](/sql-statements/sql-statement-show-histograms.md) + - [`SHOW STATS_META`](/sql-statements/sql-statement-show-stats-meta.md) + - [`SHOW STATUS`](/sql-statements/sql-statement-show-status.md) + - [`SHOW TABLE NEXT_ROW_ID`](/sql-statements/sql-statement-show-table-next-rowid.md) + - [`SHOW TABLE REGIONS`](/sql-statements/sql-statement-show-table-regions.md) + - [`SHOW TABLE STATUS`](/sql-statements/sql-statement-show-table-status.md) + - [`SHOW [FULL] TABLES`](/sql-statements/sql-statement-show-tables.md) + - [`SHOW [GLOBAL|SESSION] VARIABLES`](/sql-statements/sql-statement-show-variables.md) + - [`SHOW WARNINGS`](/sql-statements/sql-statement-show-warnings.md) + - [`SHUTDOWN`](/sql-statements/sql-statement-shutdown.md) + - [`SPLIT REGION`](/sql-statements/sql-statement-split-region.md) + - [`START TRANSACTION`](/sql-statements/sql-statement-start-transaction.md) + - [`TRACE`](/sql-statements/sql-statement-trace.md) + - [`TRUNCATE`](/sql-statements/sql-statement-truncate.md) + - [`UPDATE`](/sql-statements/sql-statement-update.md) + - [`USE`](/sql-statements/sql-statement-use.md) + + 数据类型 + + [数据类型概述](/data-type-overview.md) + + [数据类型默认值](/data-type-default-values.md) + + [数值类型](/data-type-numeric.md) + + [日期和时间类型](/data-type-date-and-time.md) + + [字符串类型](/data-type-string.md) + + [JSON 类型](/data-type-json.md) + + 函数与操作符 + + [函数与操作符概述](/functions-and-operators/functions-and-operators-overview.md) + + [表达式求值的类型转换](/functions-and-operators/type-conversion-in-expression-evaluation.md) + + [操作符](/functions-and-operators/operators.md) + + [控制流程函数](/functions-and-operators/control-flow-functions.md) + + [字符串函数](/functions-and-operators/string-functions.md) + + [数值函数与操作符](/functions-and-operators/numeric-functions-and-operators.md) + + [日期和时间函数](/functions-and-operators/date-and-time-functions.md) + + [位函数和操作符](/functions-and-operators/bit-functions-and-operators.md) + + [Cast 函数和操作符](/functions-and-operators/cast-functions-and-operators.md) + + [加密和压缩函数](/functions-and-operators/encryption-and-compression-functions.md) + + [信息函数](/functions-and-operators/information-functions.md) + + [JSON 函数](/functions-and-operators/json-functions.md) + + [GROUP BY 聚合函数](/functions-and-operators/aggregate-group-by-functions.md) + + [窗口函数](/functions-and-operators/window-functions.md) + + [其它函数](/functions-and-operators/miscellaneous-functions.md) + + [精度数学](/functions-and-operators/precision-math.md) + + [下推到 TiKV 的表达式列表](/functions-and-operators/expressions-pushed-down.md) + + [约束](/constraints.md) + + [生成列](/generated-columns.md) + + [SQL 模式](/sql-mode.md) + + 事务 + + [事务概览](/transaction-overview.md) + + [隔离级别](/transaction-isolation-levels.md) + + [乐观事务](/optimistic-transaction.md) + + [悲观事务](/pessimistic-transaction.md) + + 垃圾回收 (GC) + + [GC 机制简介](/garbage-collection-overview.md) + + [GC 配置](/garbage-collection-configuration.md) + + [视图](/views.md) + + [分区表](/partitioned-table.md) + + [字符集和排序规则](/character-set-and-collation.md) + + 系统表 + + [`mysql`](/system-tables/system-table-overview.md) + + [`information_schema`](/system-tables/system-table-information-schema.md) + + sql-diagnosis + + [`cluster_info`](/system-tables/system-table-cluster-info.md) + + [`cluster_hardware`](/system-tables/system-table-cluster-hardware.md) + + [`cluster_config`](/system-tables/system-table-cluster-config.md) + + [`cluster_load`](/system-tables/system-table-cluster-load.md) + + [`cluster_systeminfo`](/system-tables/system-table-cluster-systeminfo.md) + + [`cluster_log`](/system-tables/system-table-cluster-log.md) + + [`metrics_schema`](/system-tables/system-table-metrics-schema.md) + + [`metrics_tables`](/system-tables/system-table-metrics-tables.md) + + [`metrics_summary`](/system-tables/system-table-metrics-summary.md) + + [`inspection_result`](/system-tables/system-table-inspection-result.md) + + [`inspection_summary`](/system-tables/system-table-inspection-summary.md) + + UI + + TiDB Dashboard + + [简介](/dashboard/dashboard-intro.md) + + 运维 + + [部署](/dashboard/dashboard-ops-deploy.md) + + [反向代理](/dashboard/dashboard-ops-reverse-proxy.md) + + [安全](/dashboard/dashboard-ops-security.md) + + [访问](/dashboard/dashboard-access.md) + + [概况页面](/dashboard/dashboard-overview.md) + + [集群信息页面](/dashboard/dashboard-cluster-info.md) + + [流量可视化页面](/dashboard/dashboard-key-visualizer.md) + + SQL 语句分析 + + [列表页面](/dashboard/dashboard-statement-list.md) + + [执行详情页面](/dashboard/dashboard-statement-details.md) + + [慢查询页面](/dashboard/dashboard-slow-query.md) + + 集群诊断页面 + + [访问](/dashboard/dashboard-diagnostics-access.md) + + [查看报告](/dashboard/dashboard-diagnostics-report.md) + + [使用示例](/dashboard/dashboard-diagnostics-usage.md) + + [日志搜索页面](/dashboard/dashboard-log-search.md) + + [实例性能分析页面](/dashboard/dashboard-profiling.md) + + [常见问题](/dashboard/dashboard-faq.md) + + CLI + + [tikv-ctl](/tikv-control.md) + + [pd-ctl](/pd-control.md) + + [tidb-ctl](/tidb-control.md) + + [pd-recover](/pd-recover.md) + + [binlog-ctl](/tidb-binlog/binlog-control.md) + + 命令行参数 + + [tidb-server](/command-line-flags-for-tidb-configuration.md) + + [tikv-server](/command-line-flags-for-tikv-configuration.md) + + [tiflash-server](/tiflash/tiflash-command-line-flags.md) + + [pd-server](/command-line-flags-for-pd-configuration.md) + + 配置文件参数 + + [tidb-server](/tidb-configuration-file.md) + + [tikv-server](/tikv-configuration-file.md) + + [tiflash-server](/tiflash/tiflash-configuration.md) + + [pd-server](/pd-configuration-file.md) + + 系统变量 + + [MySQL 系统变量](/system-variables.md) + + [TiDB 特定系统变量](/tidb-specific-system-variables.md) + + 存储引擎 + + TiKV + + [TiKV 简介](/tikv-overview.md) + + [RocksDB 简介](/storage-engine/rocksdb-overview.md) + + [Titan 简介](/storage-engine/titan-overview.md) + + [Titan 配置说明](/storage-engine/titan-configuration.md) + + TiFlash + + [TiFlash 简介](/tiflash/tiflash-overview.md) + + [使用 TiFlash](/tiflash/use-tiflash.md) + + TiUP + + [文档指南](/tiup/tiup-documentation-guide.md) + + [概览](/tiup/tiup-overview.md) + + [术语及核心概念](/tiup/tiup-terminology-and-concepts.md) + + [TiUP 组件管理](/tiup/tiup-component-management.md) + + [FAQ](/tiup/tiup-faq.md) + + [故障排查](/tiup/tiup-troubleshooting-guide.md) + + TiUP 组件文档 + + [tiup-playground 运行本地测试集群](/tiup/tiup-playground.md) + + [tiup-cluster 部署运维生产集群](/tiup/tiup-cluster.md) + + [tiup-mirror 定制离线镜像](/tiup/tiup-mirror.md) + + [tiup-bench 进行 TPCC/TPCH 压力测试](/tiup/tiup-bench.md) + + [错误码](/error-codes.md) + + [TiCDC 简介](/ticdc/ticdc-overview.md) + + [TiCDC 开放数据协议](/ticdc/ticdc-open-protocol.md) + + [通过拓扑 label 进行副本调度](/schedule-replicas-by-topology-labels.md) ++ 常见问题解答 (FAQ) + + [产品 FAQ](/faq/tidb-faq.md) + + [SQL FAQ](/faq/sql-faq.md) + + [部署运维 FAQ](/faq/deploy-and-maintain-faq.md) + + [升级 FAQ](/faq/upgrade-faq.md) + + [高可用 FAQ](/faq/high-availability-faq.md) + + [高可靠 FAQ](/faq/high-reliability-faq.md) + + [迁移 FAQ](/faq/migration-tidb-faq.md) ++ [术语表](/glossary.md) ++ 版本发布历史 + + [发布版本汇总](/releases/release-notes.md) + v4.0 - - [4.0.0-beta.2](/releases/4.0.0-beta.2.md) - - [4.0.0-beta.1](/releases/4.0.0-beta.1.md) - - [4.0.0-beta](/releases/4.0.0-beta.md) + - [4.0.1](/releases/release-4.0.1.md) + - [4.0 GA](/releases/release-4.0-ga.md) + - [4.0.0-rc.2](/releases/release-4.0.0-rc.2.md) + - [4.0.0-rc.1](/releases/release-4.0.0-rc.1.md) + - [4.0.0-rc](/releases/release-4.0.0-rc.md) + - [4.0.0-beta.2](/releases/release-4.0.0-beta.2.md) + - [4.0.0-beta.1](/releases/release-4.0.0-beta.1.md) + - [4.0.0-beta](/releases/release-4.0.0-beta.md) + v3.1 - - [3.1.0-rc](/releases/3.1.0-rc.md) - - [3.1.0-beta.2](/releases/3.1.0-beta.2.md) - - [3.1.0-beta.1](/releases/3.1.0-beta.1.md) - - [3.1.0-beta](/releases/3.1.0-beta.md) + - [3.1.2](/releases/release-3.1.2.md) + - [3.1.1](/releases/release-3.1.1.md) + - [3.1.0 GA](/releases/release-3.1.0-ga.md) + - [3.1.0-rc](/releases/release-3.1.0-rc.md) + - [3.1.0-beta.2](/releases/release-3.1.0-beta.2.md) + - [3.1.0-beta.1](/releases/release-3.1.0-beta.1.md) + - [3.1.0-beta](/releases/release-3.1.0-beta.md) + v3.0 - - [3.0.12](/releases/3.0.12.md) - - [3.0.11](/releases/3.0.11.md) - - [3.0.10](/releases/3.0.10.md) - - [3.0.9](/releases/3.0.9.md) - - [3.0.8](/releases/3.0.8.md) - - [3.0.7](/releases/3.0.7.md) - - [3.0.6](/releases/3.0.6.md) - - [3.0.5](/releases/3.0.5.md) - - [3.0.4](/releases/3.0.4.md) - - [3.0.3](/releases/3.0.3.md) - - [3.0.2](/releases/3.0.2.md) - - [3.0.1](/releases/3.0.1.md) - - [3.0 GA](/releases/3.0-ga.md) - - [3.0.0-rc.3](/releases/3.0.0-rc.3.md) - - [3.0.0-rc.2](/releases/3.0.0-rc.2.md) - - [3.0.0-rc.1](/releases/3.0.0-rc.1.md) - - [3.0.0-beta.1](/releases/3.0.0-beta.1.md) - - [3.0.0-beta](/releases/3.0beta.md) + - [3.0.15](/releases/release-3.0.15.md) + - [3.0.14](/releases/release-3.0.14.md) + - [3.0.13](/releases/release-3.0.13.md) + - [3.0.12](/releases/release-3.0.12.md) + - [3.0.11](/releases/release-3.0.11.md) + - [3.0.10](/releases/release-3.0.10.md) + - [3.0.9](/releases/release-3.0.9.md) + - [3.0.8](/releases/release-3.0.8.md) + - [3.0.7](/releases/release-3.0.7.md) + - [3.0.6](/releases/release-3.0.6.md) + - [3.0.5](/releases/release-3.0.5.md) + - [3.0.4](/releases/release-3.0.4.md) + - [3.0.3](/releases/release-3.0.3.md) + - [3.0.2](/releases/release-3.0.2.md) + - [3.0.1](/releases/release-3.0.1.md) + - [3.0 GA](/releases/release-3.0-ga.md) + - [3.0.0-rc.3](/releases/release-3.0.0-rc.3.md) + - [3.0.0-rc.2](/releases/release-3.0.0-rc.2.md) + - [3.0.0-rc.1](/releases/release-3.0.0-rc.1.md) + - [3.0.0-beta.1](/releases/release-3.0.0-beta.1.md) + - [3.0.0-beta](/releases/release-3.0-beta.md) + v2.1 - - [2.1.19](/releases/2.1.19.md) - - [2.1.18](/releases/2.1.18.md) - - [2.1.17](/releases/2.1.17.md) - - [2.1.16](/releases/2.1.16.md) - - [2.1.15](/releases/2.1.15.md) - - [2.1.14](/releases/2.1.14.md) - - [2.1.13](/releases/2.1.13.md) - - [2.1.12](/releases/2.1.12.md) - - [2.1.11](/releases/2.1.11.md) - - [2.1.10](/releases/2.1.10.md) - - [2.1.9](/releases/2.1.9.md) - - [2.1.8](/releases/2.1.8.md) - - [2.1.7](/releases/2.1.7.md) - - [2.1.6](/releases/2.1.6.md) - - [2.1.5](/releases/2.1.5.md) - - [2.1.4](/releases/2.1.4.md) - - [2.1.3](/releases/2.1.3.md) - - [2.1.2](/releases/2.1.2.md) - - [2.1.1](/releases/2.1.1.md) - - [2.1 GA](/releases/2.1ga.md) - - [2.1 RC5](/releases/21rc5.md) - - [2.1 RC4](/releases/21rc4.md) - - [2.1 RC3](/releases/21rc3.md) - - [2.1 RC2](/releases/21rc2.md) - - [2.1 RC1](/releases/21rc1.md) - - [2.1 Beta](/releases/21beta.md) + - [2.1.19](/releases/release-2.1.19.md) + - [2.1.18](/releases/release-2.1.18.md) + - [2.1.17](/releases/release-2.1.17.md) + - [2.1.16](/releases/release-2.1.16.md) + - [2.1.15](/releases/release-2.1.15.md) + - [2.1.14](/releases/release-2.1.14.md) + - [2.1.13](/releases/release-2.1.13.md) + - [2.1.12](/releases/release-2.1.12.md) + - [2.1.11](/releases/release-2.1.11.md) + - [2.1.10](/releases/release-2.1.10.md) + - [2.1.9](/releases/release-2.1.9.md) + - [2.1.8](/releases/release-2.1.8.md) + - [2.1.7](/releases/release-2.1.7.md) + - [2.1.6](/releases/release-2.1.6.md) + - [2.1.5](/releases/release-2.1.5.md) + - [2.1.4](/releases/release-2.1.4.md) + - [2.1.3](/releases/release-2.1.3.md) + - [2.1.2](/releases/release-2.1.2.md) + - [2.1.1](/releases/release-2.1.1.md) + - [2.1 GA](/releases/release-2.1-ga.md) + - [2.1 RC5](/releases/release-2.1-rc.5.md) + - [2.1 RC4](/releases/release-2.1-rc.4.md) + - [2.1 RC3](/releases/release-2.1-rc.3.md) + - [2.1 RC2](/releases/release-2.1-rc.2.md) + - [2.1 RC1](/releases/release-2.1-rc.1.md) + - [2.1 Beta](/releases/release-2.1-beta.md) + v2.0 - - [2.0.11](/releases/2.0.11.md) - - [2.0.10](/releases/2.0.10.md) - - [2.0.9](/releases/209.md) - - [2.0.8](/releases/208.md) - - [2.0.7](/releases/207.md) - - [2.0.6](/releases/206.md) - - [2.0.5](/releases/205.md) - - [2.0.4](/releases/204.md) - - [2.0.3](/releases/203.md) - - [2.0.2](/releases/202.md) - - [2.0.1](/releases/201.md) - - [2.0](/releases/2.0ga.md) - - [2.0 RC5](/releases/2rc5.md) - - [2.0 RC4](/releases/2rc4.md) - - [2.0 RC3](/releases/2rc3.md) - - [2.0 RC1](/releases/2rc1.md) - - [1.1 Beta](/releases/11beta.md) - - [1.1 Alpha](/releases/11alpha.md) + - [2.0.11](/releases/release-2.0.11.md) + - [2.0.10](/releases/release-2.0.10.md) + - [2.0.9](/releases/release-2.0.9.md) + - [2.0.8](/releases/release-2.0.8.md) + - [2.0.7](/releases/release-2.0.7.md) + - [2.0.6](/releases/release-2.0.6.md) + - [2.0.5](/releases/release-2.0.5.md) + - [2.0.4](/releases/release-2.0.4.md) + - [2.0.3](/releases/release-2.0.3.md) + - [2.0.2](/releases/release-2.0.2.md) + - [2.0.1](/releases/release-2.0.1.md) + - [2.0](/releases/release-2.0-ga.md) + - [2.0 RC5](/releases/release-2.0-rc.5.md) + - [2.0 RC4](/releases/release-2.0-rc.4.md) + - [2.0 RC3](/releases/release-2.0-rc.3.md) + - [2.0 RC1](/releases/release-2.0-rc.1.md) + - [1.1 Beta](/releases/release-1.1-beta.md) + - [1.1 Alpha](/releases/release-1.1-alpha.md) + v1.0 - - [1.0](/releases/ga.md) - - [Pre-GA](/releases/prega.md) - - [RC4](/releases/rc4.md) - - [RC3](/releases/rc3.md) - - [RC2](/releases/rc2.md) - - [RC1](/releases/rc1.md) -+ [术语表](/glossary.md) + - [1.0](/releases/release-1.0-ga.md) + - [Pre-GA](/releases/release-pre-ga.md) + - [RC4](/releases/release-rc.4.md) + - [RC3](/releases/release-rc.3.md) + - [RC2](/releases/release-rc.2.md) + - [RC1](/releases/release-rc.1.md) diff --git a/_index.md b/_index.md index 667815b80c98..4a78ca397ea3 100755 --- a/_index.md +++ b/_index.md @@ -1,63 +1,113 @@ --- title: TiDB 简介 +summary: 了解 TiDB 数据库。 category: introduction --- + + # TiDB 简介 -TiDB 是 PingCAP 公司设计的开源分布式 HTAP (Hybrid Transactional and Analytical Processing) 数据库,结合了传统的 RDBMS 和 NoSQL 的最佳特性。TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性。TiDB 的目标是为 OLTP (Online Transactional Processing) 和 OLAP (Online Analytical Processing) 场景提供一站式的解决方案。 +TiDB 是 PingCAP 公司自主设计、研发的开源分布式关系型数据库,是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP)的融合型分布式数据库产品,具备水平扩容或者缩容、金融级高可用、实时 HTAP、云原生的分布式数据库、兼容 MySQL 5.7 协议和 MySQL 生态等重要特性。目标是为用户提供一站式 OLTP (Online Transactional Processing)、OLAP (Online Analytical Processing)、HTAP 解决方案。TiDB 适合高可用、强一致要求较高、数据规模较大等各种应用场景。 + + + +关于 TiDB + +- [TiDB 简介](/overview.md) +- [基本功能](/basic-features.md) +- [与 MySQL 的兼容性](/mysql-compatibility.md) +- [使用限制](/tidb-limitations.md) +- [荣誉列表](/credits.md) + + + + +快速上手 -TiDB 具备如下特性: +- [快速上手指南](/quick-start-with-tidb.md) +- [SQL 基本操作](/basic-sql-operations.md) -- 高度兼容 MySQL + - [大多数情况下](/reference/mysql-compatibility.md),无需修改代码即可从 MySQL 轻松迁移至 TiDB,分库分表后的 MySQL 集群亦可通过 TiDB 工具进行实时迁移。 + +部署使用 -- 水平弹性扩展 +- [软硬件环境需求](/hardware-and-software-requirements.md) +- [环境与系统配置检查](/check-before-deployment.md) +- [使用 TiUP 部署(推荐)](/production-deployment-using-tiup.md) +- [使用 TiFlash](/tiflash/use-tiflash.md) +- [在 Kubernetes 上部署](https://docs.pingcap.com/zh/tidb-in-kubernetes/stable) - 通过简单地增加新节点即可实现 TiDB 的水平扩展,按需扩展吞吐或存储,轻松应对高并发、海量数据场景。 + -- 分布式事务 + +数据迁移 - TiDB 100% 支持标准的 ACID 事务。 +- [概述](/migration-overview.md) +- [从 Mydumper 文件迁移](/migrate-from-mysql-mydumper-files.md) +- [从 Aurora MySQL 迁移](/migrate-from-aurora-mysql-database.md) +- [从 CSV 文件迁移](/tidb-lightning/migrate-from-csv-using-tidb-lightning.md) +- [从 SQL 文件迁移](/migrate-from-mysql-mydumper-files.md) -- 真正金融级高可用 + - 相比于传统主从 (M-S) 复制方案,基于 Raft 的多数派选举协议可以提供金融级的 100% 数据强一致性保证,且在不丢失大多数副本的前提下,可以实现故障的自动恢复 (auto-failover),无需人工介入。 + +运维操作 -- 一站式 HTAP 解决方案 +- [升级 TiDB 版本](/upgrade-tidb-using-tiup.md) +- [扩容与缩容](/scale-tidb-using-tiup.md) +- [备份与恢复](/br/backup-and-restore-tool.md) +- [TiCDC 运维操作及任务管理](/ticdc/manage-ticdc.md) +- [TiUP 常用运维操作](/maintain-tidb-using-tiup.md) +- [TiFlash 常用运维操作](/tiflash/maintain-tiflash.md) - TiDB 作为典型的 OLTP 行存数据库,同时兼具强大的 OLAP 性能,配合 TiSpark,可提供一站式 HTAP 解决方案,一份存储同时处理 OLTP & OLAP,无需传统繁琐的 ETL 过程。 + -- 云原生 SQL 数据库 + +监控告警 - TiDB 是为云而设计的数据库,支持公有云、私有云和混合云,使部署、配置和维护变得十分简单。 +- [监控框架概述](/tidb-monitoring-framework.md) +- [监控 API](/tidb-monitoring-api.md) +- [部署监控](/deploy-monitoring-services.md) +- [TiDB 集群报警规则与处理方法](/alert-rules.md) +- [TiFlash 报警规则与处理方法](/tiflash/tiflash-alert-rules.md) -TiDB 的设计目标是 100% 的 OLTP 场景和 80% 的 OLAP 场景,更复杂的 OLAP 分析可以通过 [TiSpark 项目](/reference/tispark.md)来完成。 + -TiDB 对业务没有任何侵入性,能优雅的替换传统的数据库中间件、数据库分库分表等 Sharding 方案。同时它也让开发运维人员不用关注数据库 Scale 的细节问题,专注于业务开发,极大的提升研发的生产力。 + +故障诊断 -三篇文章了解 TiDB 技术内幕: +- [定位慢查询](/identify-slow-queries.md) +- [SQL 诊断](/system-tables/system-table-sql-diagnostics.md) +- [热点问题处理](/troubleshoot-hot-spot-issues.md) +- [磁盘 I/O 过高](/troubleshoot-high-disk-io.md) +- [TiCDC 常见问题](/ticdc/troubleshoot-ticdc.md) +- [TiFlash 常见问题](/tiflash/troubleshoot-tiflash.md) -- [说存储](https://pingcap.com/blog-cn/tidb-internal-1/) -- [说计算](https://pingcap.com/blog-cn/tidb-internal-2/) -- [谈调度](https://pingcap.com/blog-cn/tidb-internal-3/) + -## 部署方式 + +参考指南 -TiDB 可以部署在本地和云平台上,支持公有云、私有云和混合云。你可以根据实际场景或需求,选择相应的方式来部署 TiDB 集群: +- [TiDB 架构](/tidb-architecture.md) +- [监控指标](/grafana-overview-dashboard.md) +- [安全加固](/enable-tls-between-clients-and-servers.md) +- [权限管理](/privilege-management.md) +- [基于角色的访问控制](/role-based-access-control.md) +- [证书鉴权](/certificate-authentication.md) -- [使用 Ansible 部署](/how-to/deploy/orchestrated/ansible.md):如果用于生产环境,须使用 TiDB Ansible 部署 TiDB 集群。 -- [使用 Ansible 离线部署](/how-to/deploy/orchestrated/offline-ansible.md):如果部署环境无法访问网络,可使用 Ansible 进行离线部署。 -- [使用 Docker Compose 部署](/how-to/get-started/deploy-tidb-from-docker-compose.md):如果你只是想测试 TiDB、体验 TiDB 的特性,或者用于开发环境,可以使用 Docker Compose 在本地快速部署 TiDB 集群。该部署方式不适用于生产环境。 -- [使用 Docker 部署](/how-to/deploy/orchestrated/docker.md):你可以使用 Docker 部署 TiDB 集群,但该部署方式不适用于生产环境。 + -## 项目源码 + +FAQ -TiDB 集群所有组件的源码均可从 GitHub 上直接访问: +- [产品 FAQ](/faq/tidb-faq.md) +- [高可用 FAQ](/faq/high-availability-faq.md) +- [SQL FAQ](/faq/sql-faq.md) +- [部署运维 FAQ](/faq/deploy-and-maintain-faq.md) +- [升级 FAQ](/faq/upgrade-faq.md) +- [迁移 FAQ](/faq/migration-tidb-faq.md) -- [TiDB](https://github.com/pingcap/tidb) -- [TiKV](https://github.com/tikv/tikv) -- [PD](https://github.com/pingcap/pd) -- [TiSpark](https://github.com/pingcap/tispark) -- [TiDB Operator](https://github.com/pingcap/tidb-operator) + + diff --git a/adopters.md b/adopters.md new file mode 100644 index 000000000000..4140a0571267 --- /dev/null +++ b/adopters.md @@ -0,0 +1,3 @@ +--- +draft: true +--- \ No newline at end of file diff --git a/agg-distinct-optimization.md b/agg-distinct-optimization.md new file mode 100644 index 000000000000..6d8f763fd75a --- /dev/null +++ b/agg-distinct-optimization.md @@ -0,0 +1,57 @@ +--- +title: Distinct 优化 +category: performance +--- + +# Distinct 优化 + +本文档介绍可用于 `DISTINCT` 的优化,包括简单 `DISTINCT` 和聚合函数 `DISTINCT` 的优化。 + +## 简单 DISTINCT + +通常简单的 `DISTINCT` 会被优化成 GROUP BY 来执行。例如: + +```sql +mysql> explain select DISTINCT a from t; ++--------------------------+---------+-----------+---------------+-------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++--------------------------+---------+-----------+---------------+-------------------------------------------------------+ +| HashAgg_6 | 2.40 | root | | group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a | +| └─TableReader_11 | 3.00 | root | | data:TableFullScan_10 | +| └─TableFullScan_10 | 3.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | ++--------------------------+---------+-----------+---------------+-------------------------------------------------------+ +3 rows in set (0.00 sec) +``` + +## 聚合函数 DISTINCT + +通常来说,带有 `DISTINCT` 的聚合函数会单线程的在 TiDB 侧执行。 +使用系统变量 [`tidb_opt_distinct_agg_push_down`](/tidb-specific-system-variables.md#tidb_opt_distinct_agg_push_down) 或者 TiDB 的配置项 [distinct-agg-push-down](/tidb-configuration-file.md#distinct-agg-push-down) 控制优化器是否执行带有 `DISTINCT` 的聚合函数(比如 `select count(distinct a) from t`)下推到 Coprocessor 的优化操作。 + +在以下示例中,`tidb_opt_distinct_agg_push_down` 开启前,TiDB 需要从 TiKV 读取所有数据,并在 TiDB 侧执行 `disctinct`。`tidb_opt_distinct_agg_push_down` 开启后,`distinct a` 被下推到了 Coprocessor,在 `HashAgg_5` 里新增了一个 `group by` 列 `test.t.a`。 + +```sql +mysql> desc select count(distinct a) from test.t; ++-------------------------+----------+-----------+---------------+------------------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------+----------+-----------+---------------+------------------------------------------+ +| StreamAgg_6 | 1.00 | root | | funcs:count(distinct test.t.a)->Column#4 | +| └─TableReader_10 | 10000.00 | root | | data:TableFullScan_9 | +| └─TableFullScan_9 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | ++-------------------------+----------+-----------+---------------+------------------------------------------+ +3 rows in set (0.01 sec) + +mysql> set session tidb_opt_distinct_agg_push_down = 1; +Query OK, 0 rows affected (0.00 sec) + +mysql> desc select count(distinct a) from test.t; ++---------------------------+----------+-----------+---------------+------------------------------------------+ +| id | estRows | task | access object | operator info | ++---------------------------+----------+-----------+---------------+------------------------------------------+ +| HashAgg_8 | 1.00 | root | | funcs:count(distinct test.t.a)->Column#3 | +| └─TableReader_9 | 1.00 | root | | data:HashAgg_5 | +| └─HashAgg_5 | 1.00 | cop[tikv] | | group by:test.t.a, | +| └─TableFullScan_7 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | ++---------------------------+----------+-----------+---------------+------------------------------------------+ +4 rows in set (0.00 sec) +``` diff --git a/alert-rules.md b/alert-rules.md new file mode 100644 index 000000000000..57049101608d --- /dev/null +++ b/alert-rules.md @@ -0,0 +1,1162 @@ +--- +title: TiDB 集群报警规则 +summary: TiDB 集群中各组件的报警规则详解。 +category: reference +aliases: ['/docs-cn/stable/reference/alert-rules/'] +--- + +# TiDB 集群报警规则 + +本文介绍了 TiDB 集群中各组件的报警规则,包括 TiDB、TiKV、PD、TiDB Binlog、Node_exporter 和 Blackbox_exporter 的各报警项的规则描述及处理方法。 + +## TiDB 报警规则 + +本节介绍了 TiDB 组件的报警项。根据严重级别,报警项可分为三类,按照严重程度由高到低依次为:紧急级别、重要级别、警告级别。 + +### 紧急级别报警项 + +紧急级别的报警通常由于服务停止或节点故障导致,此时需要马上进行人工干预。 + +#### `TiDB_schema_error` + +* 报警规则: + + `increase(tidb_session_schema_lease_error_total{type="outdated"}[15m]) > 0` + +* 规则描述: + + TiDB 在一个 Lease 时间内没有重载到最新的 Schema 信息。如果 TiDB 无法继续对外提供服务,则报警。 + +* 处理方法: + + 该问题通常由于 TiKV Region 不可用或超时导致,需要看 TiKV 的监控指标定位问题。 + +#### `TiDB_tikvclient_region_err_total` + +* 报警规则: + + `increase(tidb_tikvclient_region_err_total[10m]) > 6000` + +* 规则描述: + + TiDB 访问 TiKV 时发生了 Region 错误。如果在 10 分钟之内该错误多于 6000 次,则报警。 + +* 处理方法: + + 查看 TiKV 的监控状态。 + +#### `TiDB_domain_load_schema_total` + +* 报警规则: + + `increase(tidb_domain_load_schema_total{type="failed"}[10m]) > 10` + +* 规则描述: + + TiDB 重载最新的 Schema 信息失败的总次数。如果在 10 分钟之内重载失败次数超过 10 次,则报警。 + +* 处理方法: + + 参考 [`TiDB_schema_error`](#tidb_schema_error) 的处理方法。 + +#### `TiDB_monitor_keep_alive` + +* 报警规则: + + `increase(tidb_monitor_keep_alive_total[10m]) < 100` + +* 规则描述: + + 表示 TiDB 的进程是否仍然存在。如果在 10 分钟之内 `tidb_monitor_keep_alive_total` 增加次数少于 100,则 TiDB 的进程可能已经退出,此时会报警。 + +* 处理方法: + + * 检查 TiDB 进程是否 OOM。 + * 检查机器是否发生了重启。 + +### 重要级别报警项 + +对于重要级别的报警,需要密切关注异常指标。 + +#### `TiDB_server_panic_total` + +* 报警规则: + + `increase(tidb_server_panic_total[10m]) > 0` + +* 规则描述: + + 发生崩溃的 TiDB 线程的数量。当出现崩溃的时候会报警。该线程通常会被恢复,否则 TiDB 会频繁重启。 + +* 处理方法: + + 收集 panic 日志,定位原因。 + +### 警告级别报警项 + +警告级别的报警是对某一问题或错误的提醒。 + +#### `TiDB_memory_abnormal` + +* 报警规则: + + `go_memstats_heap_inuse_bytes{job="tidb"} > 1e+10` + +* 规则描述: + + 对 TiDB 内存使用量的监控。如果内存使用大于 10 G,则报警。 + +* 处理方法: + + 通过 HTTP API 来排查 goroutine 泄露的问题。 + +#### `TiDB_query_duration` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tidb_server_handle_query_duration_seconds_bucket[1m])) BY (le, instance)) > 1` + +* 规则描述: + + TiDB 处理请求的延时。如果 .99 的延迟大于 1 秒,则报警。 + +* 处理方法: + + 查看 TiDB 的日志,搜索 SLOW_QUERY 和 TIME_COP_PROCESS 关键字,查找慢 SQL。 + +#### `TiDB_server_event_error` + +* 报警规则: + + `increase(tidb_server_event_total{type=~"server_start|server_hang"}[15m]) > 0` + +* 规则描述: + + TiDB 服务中发生的事件数量。当出现以下事件的时候会报警: + + 1. start:TiDB 服务启动。 + 2. hang:当发生了 Critical 级别的事件时(目前只有 Binlog 写不进去一种情况),TiDB 进入 `hang` 模式,并等待人工 Kill。 + +* 处理方法: + + * 重启 TiDB 以恢复服务。 + * 检查 TiDB Binlog 服务是否正常。 + +#### `TiDB_tikvclient_backoff_total` + +* 报警规则: + + `increase(tidb_tikvclient_backoff_total[10m]) > 10` + +* 规则描述: + + TiDB 访问 TiKV 发生错误时发起重试的次数。如果在 10 分钟之内重试次数多于 10 次,则报警。 + +* 处理方法: + + 查看 TiKV 的监控状态。 + +#### `TiDB_monitor_time_jump_back_error` + +* 报警规则: + + `increase(tidb_monitor_time_jump_back_total[10m]) > 0` + +* 规则描述: + + 如果 TiDB 所在机器的时间发生了回退,则报警。 + +* 处理方法: + + 排查 NTP 配置。 + +#### `TiDB_ddl_waiting_jobs` + +* 报警规则: + + `sum(tidb_ddl_waiting_jobs) > 5` + +* 规则描述: + + 如果 TiDB 中等待执行的 DDL 任务的数量大于 5,则报警。 + +* 处理方法: + + 通过 `admin show ddl` 语句检查是否有耗时的 add index 操作正在执行。 + +## PD 报警规则 + +本节介绍了 PD 组件的报警项。根据严重级别,报警项可分为三类,按照严重程度由高到低依次为:紧急级别、重要级别、警告级别。 + +### 紧急级别报警项 + +紧急级别的报警通常由于服务停止或节点故障导致,此时需要马上进行人工干预操作。 + +#### `PD_cluster_offline_tikv_nums` + +* 报警规则: + + `sum(pd_cluster_status{type="store_down_count"}) > 0` + +* 规则描述: + + PD 长时间(默认配置是 30 分钟)没有收到 TiKV 心跳。 + +* 处理方法: + + * 检查 TiKV 进程是否正常、网络是否隔离以及负载是否过高,并尽可能地恢复服务。 + * 如果确定 TiKV 无法恢复,可做下线处理。 + +### 重要级别报警项 + +对于重要级别的报警,需要密切关注异常指标。 + +#### `PD_etcd_write_disk_latency` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket[1m])) by (instance,job,le)) > 1` + +* 规则描述: + + etcd 写盘慢,这很容易引起 PD leader 超时或者 TSO 无法及时存盘等问题,从而导致整个集群停止服务。 + +* 处理方法: + + * 排查写入慢的原因。可能是由于其他服务导致系统负载过高。可以检查 PD 本身是否占用了大量 CPU 或 IO 资源。 + * 可尝试重启 PD 或手动 transfer leader 至其他的 PD 来恢复服务。 + * 如果由于环境原因无法恢复,可将有问题的 PD 下线替换。 + +#### `PD_miss_peer_region_count` + +* 报警规则: + + `sum(pd_regions_status{type="miss_peer_region_count"}) > 100` + +* 规则描述: + + Region 的副本数小于 `max-replicas` 配置的值。这通常是由于 TiKV 宕机等问题导致一段时间内一些 Region 缺副本,下线 TiKV 节点也会导致少量 Region 缺副本(对于有 pending peer 的 Region 会走先减后加的流程)。 + +* 处理方法: + + * 查看是否有 TiKV 宕机或在做下线操作,尝试定位问题产生的原因。 + * 观察 region health 面板,查看 `miss_peer_region_count` 是否在不断减少。 + +### 警告级别报警项 + +警告级别的报警是对某一问题或错误的提醒。 + +#### `PD_cluster_lost_connect_tikv_nums` + +* 报警规则: + + `sum(pd_cluster_status{type="store_disconnected_count"}) > 0` + +* 规则描述: + + PD 在 20 秒之内未收到 TiKV 上报心跳。正常情况下是每 10 秒收到 1 次心跳。 + +* 处理方法: + + * 排查是否在重启 TiKV。 + * 检查 TiKV 进程是否正常、网络是否隔离以及负载是否过高,并尽可能地恢复服务。 + * 如果确定 TiKV 无法恢复,可做下线处理。 + * 如果确定 TiKV 可以恢复,但在短时间内还无法恢复,可以考虑延长 `max-down-time` 配置,防止超时后 TiKV 被判定为无法恢复并开始搬移数据。 + +#### `PD_cluster_low_space` + +* 报警规则: + + `sum(pd_cluster_status{type="store_low_space_count"}) > 0` + +* 规则描述: + + 表示 TiKV 节点空间不足。 + +* 处理方法: + + * 检查集群中的空间是否普遍不足。如果是,则需要扩容。 + * 检查 Region balance 调度是否有问题。如果有问题,会导致数据分布不均衡。 + * 检查是否有文件占用了大量磁盘空间,比如日志、快照、core dump 等文件。 + * 降低该节点的 Region weight 来减少数据量。 + * 无法释放空间时,可以考虑主动下线该节点,防止由于磁盘空间不足而宕机。 + +#### `PD_etcd_network_peer_latency` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(etcd_network_peer_round_trip_time_seconds_bucket[1m])) by (To,instance,job,le)) > 1` + +* 规则描述: + + PD 节点之间网络延迟高,严重情况下会导致 leader 超时和 TSO 存盘超时,从而影响集群服务。 + +* 处理方法: + + * 检查网络状况和系统负载情况。 + * 如果由于环境原因无法恢复,可将有问题的 PD 下线替换。 + +#### `PD_tidb_handle_requests_duration` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(pd_client_request_handle_requests_duration_seconds_bucket{type="tso"}[1m])) by (instance,job,le)) > 0.1` + +* 规则描述: + + PD 处理 TSO 请求耗时过长,一般是由于负载过高。 + +* 处理方法: + + * 检查服务器负载状况。 + * 使用 pprof 抓取 PD 的 CPU profile 进行分析。 + * 手动切换 PD leader。 + * 如果是环境问题,则将有问题的 PD 下线替换。 + +#### `PD_down_peer_region_nums` + +* 报警规则: + + `sum(pd_regions_status{type="down_peer_region_count"}) > 0` + +* 规则描述: + + Raft leader 上报有不响应 peer 的 Region 数量。 + +* 处理方法: + + * 检查是否有 TiKV 宕机,或刚发生重启,或者繁忙。 + * 观察 region health 面板,检查 `down_peer_region_count` 是否在不断减少。 + * 检查是否有 TiKV 之间网络不通。 + +#### `PD_pending_peer_region_count` + +* 报警规则: + + `sum(pd_regions_status{type="pending_peer_region_count"}) > 100` + +* 规则描述: + + Raft log 落后的 Region 过多。由于调度产生少量的 pending peer 是正常的,但是如果持续很高,就可能有问题。 + +* 处理方法: + + * 观察 region health 面板,检查 `pending_peer_region_count` 是否在不断减少。 + * 检查 TiKV 之间的网络状况,特别是带宽是否足够。 + +#### `PD_leader_change` + +* 报警规则: + + `count(changes(pd_server_tso{type="save"}[10m]) > 0) >= 2` + +* 规则描述: + + 近期发生了 PD leader 切换。 + +* 处理方法: + + * 排除人为因素,比如重启 PD、手动 transfer leader 或调整 leader 优先级等。 + * 检查网络状况和系统负载情况。 + * 如果由于环境原因无法恢复,可将有问题的 PD 下线替换。 + +#### `TiKV_space_used_more_than_80%` + +* 报警规则: + + `sum(pd_cluster_status{type="storage_size"}) / sum(pd_cluster_status{type="storage_capacity"}) * 100 > 80` + +* 规则描述: + + 集群空间占用超过 80%。 + +* 处理方法: + + * 确认是否需要扩容。 + * 排查是否有文件占用了大量磁盘空间,比如日志、快照或 core dump等文件。 + +#### `PD_system_time_slow` + +* 报警规则: + + `changes(pd_server_tso{type="system_time_slow"}[10m]) >= 1` + +* 规则描述: + + 系统时间可能发生回退。 + +* 处理方法: + + 检查系统时间设置是否正确。 + +#### `PD_no_store_for_making_replica` + +* 报警规则: + + `increase(pd_checker_event_count{type="replica_checker", name="no_target_store"}[1m]) > 0` + +* 规则描述: + + 没有合适的 store 用来补副本。 + +* 处理方法: + + * 检查 store 是否空间不足。 + * 根据 label 配置(如果有这个配置的话)来检查是否有可以补副本的 store。 + +## TiKV 报警规则 + +本节介绍了 TiKV 组件的报警项。根据严重级别,报警项可分为三类,按照严重程度由高到低依次为:紧急级别、重要级别、警告级别。 + +### 紧急级别报警项 + +紧急级别的报警通常由于服务停止或节点故障导致,此时需要马上进行人工干预操作。 + +#### `TiKV_memory_used_too_fast` + +* 报警规则: + + `process_resident_memory_bytes{job=~"tikv",instance=~".*"} - (process_resident_memory_bytes{job=~"tikv",instance=~".*"} offset 5m) > 5*1024*1024*1024` + +* 规则描述: + + 目前没有和内存相关的 TiKV 的监控,你可以通过 Node_exporter 监控集群内机器的内存使用情况。如上规则表示,如果在 5 分钟之内内存使用超过 5GB(TiKV 内存占用的太快),则报警。 + +* 处理方法: + + 调整 `rockdb.defaultcf` 和 `rocksdb.writecf` 的 `block-cache-size` 的大小。 + +#### `TiKV_GC_can_not_work` + +* 报警规则: + + `sum(increase(tidb_tikvclient_gc_action_result{type="success"}[6h])) < 1` + + > **注意:** + > + > 由于 3.0 中引入了分布式 GC 且 GC 不会在 TiDB 执行,因此 `tidb_tikvclient_gc_action_result` 指标虽然在 3.* 以上版本中存在,但是不会有值。 + +* 规则描述: + + 在 6 小时内 Region 上没有成功执行 GC,说明 GC 不能正常工作了。短期内 GC 不运行不会造成太大的影响,但如果 GC 一直不运行,版本会越来越多,从而导致查询变慢。 + +* 处理方法: + + 1. 执行 `select VARIABLE_VALUE from mysql.tidb where VARIABLE_NAME="tikv_gc_leader_desc"` 来找到 gc leader 对应的 `tidb-server`; + 2. 查看该 `tidb-server` 的日志,grep gc_worker tidb.log; + 3. 如果发现这段时间一直在 resolve locks(最后一条日志是 `start resolve locks`)或者 delete ranges(最后一条日志是 `start delete {number} ranges`),说明 GC 进程是正常的。否则需要报备开发人员 [support@pingcap.com](mailto:support@pingcap.com) 进行处理。 + +### 重要级别报警项 + +对于重要级别的报警,需要密切关注异常指标。 + +#### `TiKV_server_report_failure_msg_total` + +* 报警规则: + + `sum(rate(tikv_server_report_failure_msg_total{type="unreachable"}[10m])) BY (store_id) > 10` + +* 规则描述: + + 表明无法连接远端的 TiKV。 + +* 处理方法: + + 1. 检查网络是否通畅。 + 2. 检查远端 TiKV 是否挂掉。 + 3. 如果远端 TiKV 没有挂掉,检查压力是否太大,参考 [`TiKV_channel_full_total`](#tikv_channel_full_total) 处理方法。 + +#### `TiKV_channel_full_total` + +* 报警规则: + + `sum(rate(tikv_channel_full_total[10m])) BY (type, instance) > 0` + +* 规则描述: + + 该错误通常是因为 Raftstore 线程卡死,TiKV 的压力已经非常大了。 + +* 处理方法: + + 1. 观察 Raft Propose 监控,看这个报警的 TiKV 节点是否明显有比其他 TiKV 高很多。如果是,表明这个 TiKV 上有热点,需要检查热点调度是否能正常工作。 + 2. 观察 Raft IO 监控,看延迟是否升高。如果延迟很高,表明磁盘可能有瓶颈。一个能缓解但不怎么安全的办法是将 `sync-log` 改成 `false`。 + 3. 观察 Raft Process 监控,看 tick duration 是否很高。如果是,需要在 `[raftstore]` 配置下加上 `raft-base-tick-interval = “2s”`。 + +#### `TiKV_write_stall` + +* 报警规则: + + `delta(tikv_engine_write_stall[10m]) > 0` + +* 规则描述: + + RocksDB 写入压力太大,出现了 stall。 + +* 处理方法: + + 1. 观察磁盘监控,排除磁盘问题。 + 2. 看 TiKV 是否有写入热点。 + 3. 在 `[rocksdb]` 和 `[raftdb]` 配置下调大 `max-sub-compactions` 的值。 + +#### `TiKV_raft_log_lag` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tikv_raftstore_log_lag_bucket[1m])) by (le, instance)) > 5000` + +* 规则描述: + + 这个值偏大,表明 Follower 已经远远落后于 Leader,Raft 没法正常同步了。可能的原因是 Follower 所在的 TiKV 卡住或者挂掉了。 + +#### `TiKV_async_request_snapshot_duration_seconds` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tikv_storage_engine_async_request_duration_seconds_bucket{type="snapshot"}[1m])) by (le, instance, type)) > 1` + +* 规则描述: + + 这个值偏大,表明 Raftstore 负载压力很大,可能已经卡住。 + +* 处理方法: + + 参考 [`TiKV_channel_full_total`](#tikv_channel_full_total) 的处理方法。 + +#### `TiKV_async_request_write_duration_seconds` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tikv_storage_engine_async_request_duration_seconds_bucket{type="write"}[1m])) by (le, instance, type)) > 1` + +* 规则描述: + + 这个值偏大,表明 Raft write 耗时很长。 + +* 处理方法: + + 1. 检查 Raftstore 上的压力,参考 [`TiKV_channel_full_total`](#tikv_channel_full_total) 的处理方法。 + 2. 检查 apply worker 线程的压力。 + +#### `TiKV_coprocessor_request_wait_seconds` + +* 报警规则: + + `histogram_quantile(0.9999, sum(rate(tikv_coprocessor_request_wait_seconds_bucket[1m])) by (le, instance, req)) > 10` + +* 规则描述: + + 这个值偏大,表明 Coprocessor worker 压力很大。可能有比较慢的任务卡住了 Coprocessor 线程。 + +* 处理方法: + + 1. 从 TiDB 日志中查看慢查询日志,看查询是否用到了索引或全表扫,或者看是否需要做 analyze。 + 2. 排查是否有热点。 + 3. 查看 Coprocessor 监控,看 `coporcessor table/index scan` 里 `total` 和 `process` 是否匹配。如果相差太大,表明做了太多的无效查询。看是否有 `over seek bound`,如果有,表明版本太多,GC 工作不及时,需要增大并行 GC 的线程数。 + +#### `TiKV_raftstore_thread_cpu_seconds_total` + +* 报警规则: + + `sum(rate(tikv_thread_cpu_seconds_total{name=~"raftstore_.*"}[1m])) by (instance, name) > 1.6` + +* 规则描述: + + Raftstore 线程压力太大。 + +* 处理方法: + + 参考 [`TiKV_channel_full_total`](#tikv_channel_full_total) 的处理方法。 + +#### `TiKV_raft_append_log_duration_secs` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tikv_raftstore_append_log_duration_seconds_bucket[1m])) by (le, instance)) > 1` + +* 规则描述: + + 表示 append Raft log 的耗时,如果高,通常是因为 IO 太忙了。 + +#### `TiKV_raft_apply_log_duration_secs` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tikv_raftstore_apply_log_duration_seconds_bucket[1m])) by (le, instance)) > 1` + +* 规则描述: + + 表示 apply Raft log 耗时,如果高,通常是因为 IO 太忙了。 + +#### `TiKV_scheduler_latch_wait_duration_seconds` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tikv_scheduler_latch_wait_duration_seconds_bucket[1m])) by (le, instance, type)) > 1` + +* 规则描述: + + Scheduler 中写操作获取内存锁时的等待时间。如果这个值高,表明写操作冲突较多,也可能是某些引起冲突的操作耗时较长,阻塞了其它等待相同锁的操作。 + +* 处理方法: + + 1. 查看 Scheduler-All 监控中的 scheduler command duration,看哪一个命令耗时最大。 + 2. 查看 Scheduler-All 监控中的 scheduler scan details,看 `total` 和 `process` 是否匹配。如果相差太大,表明有很多无效的扫描,另外观察是否有 `over seek bound`,如果太多,表明 GC 不及时。 + 3. 查看 Storage 监控中的 storage async snapshot/write duration,看是否 Raft 操作不及时。 + +#### `TiKV_thread_apply_worker_cpu_seconds` + +* 报警规则: + + `sum(rate(tikv_thread_cpu_seconds_total{name="apply_worker"}[1m])) by (instance) > 1.8` + +* 规则描述: + + Apply Raft log 线程压力太大,通常是因为写入太猛了。 + +#### `TiDB_tikvclient_gc_action_fail`(基本不发生,只在特殊配置下才会发生) + +* 报警规则: + + `sum(increase(tidb_tikvclient_gc_action_result{type="fail”}[1m])) > 10` + + > **注意:** + > + > 由于 3.0 中引入了分布式 GC 且 GC 不会在 TiDB 执行,因此 `tidb_tikvclient_gc_action_result` 指标虽然在 3.* 以上版本中存在,但是不会有值。 + +* 规则描述: + + GC 失败的 Region 较多。 + +* 处理方法: + + 1. 一般是因为并行 GC 开的太高了,可以适当降低 GC 并行度。你需要先确认 GC 失败是由于服务器繁忙导致的。 + 2. 通过执行 `update set VARIABLE_VALUE=”{number}” where VARIABLE_NAME=”tikv_gc_concurrency”` 适当降低并行度。 + +### 警告级别报警项 + +警告级别的报警是对某一问题或错误的提醒。 + +#### `TiKV_leader_drops` + +* 报警规则: + + `delta(tikv_pd_heartbeat_tick_total{type="leader"}[30s]) < -10` + +* 规则描述: + + 该问题通常是因为 Raftstore 线程卡住了。 + +* 处理方法: + + 1. 参考 [`TiKV_channel_full_total`](#tikv_channel_full_total) 的处理方法。 + 2. 如果 TiKV 压力很小,考虑 PD 的调度是否太频繁。可以查看 PD 页面的 Operator Create 面板,排查 PD 产生调度的类型和数量。 + +#### `TiKV_raft_process_ready_duration_secs` + +* 报警规则: + + `histogram_quantile(0.999, sum(rate(tikv_raftstore_raft_process_duration_secs_bucket{type='ready'}[1m])) by (le, instance, type)) > 2` + +* 规则描述: + + 表示处理 Raft ready 的耗时。这个值大,通常是因为 append log 任务卡住了。 + +#### `TiKV_raft_process_tick_duration_secs` + +* 报警规则: + + `histogram_quantile(0.999, sum(rate(tikv_raftstore_raft_process_duration_secs_bucket{type=’tick’}[1m])) by (le, instance, type)) > 2` + +* 规则描述: + + 表示处理 Raft tick 的耗时,这个值大,通常是因为 Region 太多导致的。 + +* 处理方法: + + 1. 考虑使用更高等级的日志,比如 `warn` 或者 `error`。 + 2. 在 `[raftstore]` 配置下添加 `raft-base-tick-interval = “2s”`。 + +#### `TiKV_scheduler_context_total` + +* 报警规则: + + `abs(delta( tikv_scheduler_context_total[5m])) > 1000` + +* 规则描述: + + Scheduler 正在执行的写命令数量。这个值高,表示任务完成得不及时。 + +* 处理方法: + + 参考 [`TiKV_scheduler_latch_wait_duration_seconds`](#tikv_scheduler_latch_wait_duration_seconds) 的处理方法。 + +#### `TiKV_scheduler_command_duration_seconds` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tikv_scheduler_command_duration_seconds_bucket[1m])) by (le, instance, type) / 1000) > 1` + +* 规则描述: + + 表明 Scheduler 执行命令的耗时。 + +* 处理方法: + + 参考 [`TiKV_scheduler_latch_wait_duration_seconds`](#tikv_scheduler_latch_wait_duration_seconds) 的处理方法。 + +#### `TiKV_coprocessor_outdated_request_wait_seconds` + +* 报警规则: + + `delta(tikv_coprocessor_outdated_request_wait_seconds_count[10m]) > 0` + +* 规则描述: + + Coprocessor 已经过期的请求等待的时间。这个值高,表示 Coprocessor 压力已经非常大了。 + +* 处理方法: + + 参考 [`TiKV_coprocessor_request_wait_seconds`](#tikv_coprocessor_request_wait_seconds) 的处理方法。 + +#### `TiKV_coprocessor_request_error` + +* 报警规则: + + `increase(tikv_coprocessor_request_error{reason!="lock"}[10m]) > 100` + +* 规则描述: + + Coprocessor 的请求错误。 + +* 处理方法: + + Coprocessor 错误的主要原因分为“lock”、“outdated”和“full”等。“outdated”表示请求超时,很可能是由于排队时间过久,或者单个请求的耗时比较长。“full”表示 Coprocessor 的请求队列已经满了,可能是正在执行的请求比较耗时,导致新来的请求都在排队。耗时比较长的查询需要查看下对应的执行计划是否正确。 + +#### `TiKV_coprocessor_request_lock_error` + +* 报警规则: + + `increase(tikv_coprocessor_request_error{reason="lock"}[10m]) > 10000` + +* 规则描述: + + Coprocessor 请求锁的错误。 + +* 处理方法: + + Coprocessor 错误的主要原因分为“lock”、“outdated”、“full”等。“lock”表示读到的数据正在写入,需要等待一会再读(TiDB 内部会自动重试)。少量这种错误不用关注,如果有大量这种错误,需要查看写入和查询是否有冲突。 + +#### `TiKV_coprocessor_pending_request` + +* 报警规则: + + `delta(tikv_coprocessor_pending_request[10m]) > 5000` + +* 规则描述: + + Coprocessor 排队的请求。 + +* 处理方法: + + 参考 [`TiKV_coprocessor_request_wait_seconds`](#tikv_coprocessor_request_wait_seconds) 的处理方法。 + +#### `TiKV_batch_request_snapshot_nums` + +* 报警规则: + + `sum(rate(tikv_thread_cpu_seconds_total{name=~"cop_.*"}[1m])) by (instance) / (count(tikv_thread_cpu_seconds_total{name=~"cop_.*"}) * 0.9) / count(count(tikv_thread_cpu_seconds_total) by (instance)) > 0` + +* 规则描述: + + 某个 TiKV 的 Coprocessor CPU 使用率超过了 90%。 + +#### `TiKV_pending_task` + +* 报警规则: + + `sum(tikv_worker_pending_task_total) BY (instance,name) > 1000` + +* 规则描述: + + TiKV 等待的任务数量。 + +* 处理方法: + + 查看是哪一类任务的值偏高,通常 Coprocessor、apply worker 这类任务都可以在其他指标里找到解决办法。 + +#### `TiKV_low_space_and_add_region` + +* 报警规则: + + `count((sum(tikv_store_size_bytes{type="available"}) by (instance) / sum(tikv_store_size_bytes{type="capacity"}) by (instance) < 0.2) and (sum(tikv_raftstore_snapshot_traffic_total{type="applying"}) by (instance) > 0)) > 0` + +#### `TiKV_approximate_region_size` + +* 报警规则: + + `histogram_quantile(0.99, sum(rate(tikv_raftstore_region_size_bucket[1m])) by (le)) > 1073741824` + +* 规则描述: + + TiKV split checker 扫描到的最大的 Region approximate size 在 1 分钟内持续大于 1 GB。 + +* 处理方法: + + Region 分裂的速度不及写入的速度。为缓解这种情况,建议更新到支持 batch-split 的版本 (>= 2.1.0-rc1)。如暂时无法更新,可以使用 `pd-ctl operator add split-region --policy=approximate` 手动分裂 Region。 + +## TiDB Binlog 报警规则 + +关于 TiDB Binlog 报警规则的详细描述,参见 [TiDB Binlog 集群监控报警文档](/tidb-binlog/monitor-tidb-binlog-cluster.md#监控报警规则)。 + +## Node_exporter 主机报警规则 + +本节介绍了 Node_exporter 主机的报警项。根据严重级别,报警项可分为三类,按照严重程度由高到低依次为:紧急级别、重要级别、警告级别。 + +### 紧急级别报警项 + +紧急级别的报警通常由于服务停止或节点故障导致,此时需要马上进行人工干预操作。 + +#### `NODE_disk_used_more_than_80%` + +* 报警规则: + + `node_filesystem_avail{fstype=~"(ext.|xfs)", mountpoint!~"/boot"} / node_filesystem_size{fstype=~"(ext.|xfs)", mountpoint!~"/boot"} * 100 <= 20` + +* 规则描述: + + 机器磁盘空间使用率超过 80%。 + +* 处理方法: + + 登录机器,执行 `df -h` 命令,查看磁盘空间使用率,做好扩容计划。 + +#### `NODE_disk_inode_more_than_80%` + +* 报警规则: + + `node_filesystem_files_free{fstype=~"(ext.|xfs)"} / node_filesystem_files{fstype=~"(ext.|xfs)"} * 100 < 20` + +* 规则描述: + + 机器磁盘挂载目录文件系统 inode 使用率超过 80%。 + +* 处理方法: + + 登录机器,执行 `df -i` 命令,查看磁盘挂载目录文件系统 inode 使用率,做好扩容计划。 + +#### `NODE_disk_readonly` + +* 报警规则: + + `node_filesystem_readonly{fstype=~"(ext.|xfs)"} == 1` + +* 规则描述: + + 磁盘挂载目录文件系统只读,无法写入数据,一般是因为磁盘故障或文件系统损坏。 + +* 处理方法: + + * 登录机器创建文件测试是否正常。 + * 检查该服务器硬盘指示灯是否正常,如异常,需更换磁盘并修复该机器文件系统。 + +### 重要级别报警项 + +对于重要级别的报警,需要密切关注异常指标。 + +#### `NODE_memory_used_more_than_80%` + +* 报警规则: + + `(((node_memory_MemTotal-node_memory_MemFree-node_memory_Cached)/(node_memory_MemTotal)*100)) >= 80` + +* 规则描述: + + 机器内存使用率超过 80%。 + +* 处理方法: + + * 在 Grafana Node Exporter 页面查看该主机的 Memory 面板,检查 `Used` 是否过高,`Available` 内存是否过低。 + * 登录机器,执行 `free -m` 命令查看内存使用情况,执行 `top` 看是否有异常进程的内存使用率过高。 + +### 警告级别报警项 + +警告级别的报警是对某一问题或错误的提醒。 + +#### `NODE_node_overload` + +* 报警规则: + + `(node_load5 / count without (cpu, mode) (node_cpu{mode="system"})) > 1` + +* 规则描述: + + 机器 CPU 负载较高。 + +* 处理方法: + + * 在 Grafana Node exporter 页面上查看该主机的 CPU Usage 及 Load Average,检查是否过高。 + * 登录机器,执行 `top` 查看 load average 及 CPU 使用率,看是否是异常进程的 CPU 使用率过高。 + +#### `NODE_cpu_used_more_than_80%` + +* 报警规则: + + `avg(irate(node_cpu{mode="idle"}[5m])) by(instance) * 100 <= 20` + +* 规则描述: + + 机器 CPU 使用率超过 80%。 + +* 处理方法: + + * 在 Grafana Node exporter 页面上查看该主机的 CPU Usage 及 Load Average,检查是否过高。 + * 登录机器,执行 `top` 查看 load average 及 CPU 使用率,看是否是异常进程的 CPU 使用率过高。 + +#### `NODE_tcp_estab_num_more_than_50000` + +* 报警规则: + + `node_netstat_Tcp_CurrEstab > 50000` + +* 规则描述: + + 机器 `establish` 状态的 TCP 链接超过 50,000。 + +* 处理方法: + + 登录机器执行 `ss -s` 可查看当前系统 `estab` 状态的 TCP 链接数,执行 `netstat` 查看是否有异常链接。 + +#### `NODE_disk_read_latency_more_than_32ms` + +* 报警规则: + + `((rate(node_disk_read_time_ms{device=~".+"}[5m]) / rate(node_disk_reads_completed{device=~".+"}[5m])) or (irate(node_disk_read_time_ms{device=~".+"}[5m]) / irate(node_disk_reads_completed{device=~".+"}[5m]))) > 32` + +* 规则描述: + + 磁盘读延迟超过 32 毫秒。 + +* 处理方法: + + * 查看 Grafana Disk Performance Dashboard 观察磁盘使用情况。 + * 查看 Disk Latency 面板观察磁盘的读延迟。 + * 查看 Disk IO Utilization 面板观察 IO 使用率。 + +#### `NODE_disk_write_latency_more_than_16ms` + +* 报警规则: + + `((rate(node_disk_write_time_ms{device=~".+"}[5m]) / rate(node_disk_writes_completed{device=~".+"}[5m])) or (irate(node_disk_write_time_ms{device=~".+"}[5m]) / irate(node_disk_writes_completed{device=~".+"}[5m])))> 16` + +* 规则描述: + + 机器磁盘写延迟超过 16 毫秒。 + +* 处理方法: + + * 查看 Grafana Disk Performance Dashboard 观察磁盘使用情况。 + * 查看 Disk Latency 面板可查看磁盘的写延迟。 + * 查看 Disk IO Utilization 面板可查看 IO 使用率。 + +## Blackbox_exporter TCP、ICMP 和 HTTP 报警规则 + +本节介绍了 Blackbox_exporter TCP、ICMP 和 HTTP 的报警项。根据严重级别,报警项可分为三类,按照严重程度由高到低依次为:紧急级别、重要级别、警告级别。 + +### 紧急级别报警项 + +紧急级别的报警通常由于服务停止或节点故障导致,此时需要马上进行人工干预操作。 + +#### `TiDB_server_is_down` + +* 报警规则: + + `probe_success{group="tidb"} == 0` + +* 规则描述: + + TiDB 服务端口探测失败。 + +* 处理方法: + + * 检查 TiDB 服务所在机器是否宕机。 + * 检查 TiDB 进程是否存在。 + * 检查监控机与 TiDB 服务所在机器之间网络是否正常。 + +#### `Pump_server_is_down` + +* 报警规则: + + `probe_success{group="pump"} == 0` + +* 规则描述: + + Pump 服务端口探测失败。 + +* 处理方法: + + * 检查 Pump 服务所在机器是否宕机。 + * 检查 Pump 进程是否存在。 + * 检查监控机与 Pump 服务所在机器之间网络是否正常。 + +#### `Drainer_server_is_down` + +* 报警规则: + + `probe_success{group="drainer"} == 0` + +* 规则描述: + + Drainer 服务端口探测失败。 + +* 处理方法: + + * 检查 Drainer 服务所在机器是否宕机。 + * 检查 Drainer 进程是否存在。 + * 检查监控机与 Drainer 服务所在机器之间网络是否正常。 + +#### `TiKV_server_is_down` + +* 报警规则: + + `probe_success{group="tikv"} == 0` + +* 规则描述: + + TiKV 服务端口探测失败。 + +* 处理方法: + + * 检查 TiKV 服务所在机器是否宕机。 + * 检查 TiKV 进程是否存在。 + * 检查监控机与 TiKV 服务所在机器之间网络是否正常。 + +#### `PD_server_is_down` + +* 报警规则: + + `probe_success{group="pd"} == 0` + +* 规则描述: + + PD 服务端口探测失败。 + +* 处理方法: + + * 检查 PD 服务所在机器是否宕机。 + * 检查 PD 进程是否存在。 + * 检查监控机与 PD 服务所在机器之间网络是否正常。 + +#### `Node_exporter_server_is_down` + +* 报警规则: + + `probe_success{group="node_exporter"} == 0` + +* 规则描述: + + Node_exporter 服务端口探测失败。 + +* 处理方法: + + * 检查 Node_exporter 服务所在机器是否宕机。 + * 检查 Node_exporter 进程是否存在。 + * 检查监控机与 Node_exporter 服务所在机器之间网络是否正常。 + +#### `Blackbox_exporter_server_is_down` + +* 报警规则: + + `probe_success{group="blackbox_exporter"} == 0` + +* 规则描述: + + Blackbox_exporter 服务端口探测失败。 + +* 处理方法: + + * 检查 Blackbox_exporter 服务所在机器是否宕机。 + * 检查 Blackbox_exporter 进程是否存在。 + * 检查监控机与 Blackbox_exporter 服务所在机器之间网络是否正常。 + +#### `Grafana_server_is_down` + +* 报警规则: + + `probe_success{group="grafana"} == 0` + +* 规则描述: + + Grafana 服务端口探测失败。 + +* 处理方法: + + * 检查 Grafana 服务所在机器是否宕机。 + * 检查 Grafana 进程是否存在。 + * 检查监控机与 Grafana 服务所在机器之间网络是否正常。 + +#### `Pushgateway_server_is_down` + +* 报警规则: + + `probe_success{group="pushgateway"} == 0` + +* 规则描述: + + Pushgateway 服务端口探测失败。 + +* 处理方法: + + * 检查 Pushgateway 服务所在机器是否宕机。 + * 检查 Pushgateway 进程是否存在。 + * 检查监控机与 Pushgateway 服务所在机器之间网络是否正常。 + +#### `Kafka_exporter_is_down` + +* 报警规则: + + `probe_success{group="kafka_exporter"} == 0` + +* 规则描述: + + Kafka_exporter 服务端口探测失败。 + +* 处理方法: + + * 检查 Kafka_exporter 服务所在机器是否宕机。 + * 检查 Kafka_exporter 进程是否存在。 + * 检查监控机与 Kafka_exporter 服务所在机器之间网络是否正常。 + +#### `Pushgateway_metrics_interface` + +* 报警规则: + + `probe_success{job="blackbox_exporter_http"} == 0` + +* 规则描述: + + Pushgateway 服务 http 接口探测失败。 + +* 处理方法: + + * 检查 Pushgateway 服务所在机器是否宕机。 + * 检查 Pushgateway 进程是否存在。 + * 检查监控机与 Pushgateway 服务所在机器之间网络是否正常。 + +### 警告级别报警项 + +警告级别的报警是对某一问题或错误的提醒。 + +#### `BLACKER_ping_latency_more_than_1s` + +* 报警规则: + + `max_over_time(probe_duration_seconds{job=~"blackbox_exporter.*_icmp"}[1m]) > 1` + +* 规则描述: + + Ping 延迟超过 1 秒。 + +* 处理方法: + + * 在 Grafana Blackbox Exporter dashboard 上检查两个节点间的 ping 延迟是否太高。 + * 在 Grafana Blackbox Exporter dashboard 的 tcp 面板上检查是否有丢包。 diff --git a/auto-increment.md b/auto-increment.md new file mode 100644 index 000000000000..391914881157 --- /dev/null +++ b/auto-increment.md @@ -0,0 +1,202 @@ +--- +title: AUTO_INCREMENT +category: reference +summary: 介绍 TiDB 的 `AUTO_INCREMENT` 列属性。 +--- + +# AUTO_INCREMENT + +本文介绍列属性 `AUTO_INCREMENT` 的基本概念、实现原理、自增相关的特性,以及使用限制。 + +## 基本概念 + +`AUTO_INCREMENT` 是用于自动填充缺省列值的列属性。当 `INSERT` 语句没有指定 `AUTO_INCREMENT` 列的具体值时,系统会自动地为该列分配一个值。该值满足唯一性,以及**特殊情况下**的递增性和连续性。使用示例如下: + +{{< copyable "sql" >}} + +```sql +create table t(id int primary key AUTO_INCREMENT, c int); +``` + +{{< copyable "sql" >}} + +```sql +insert into t(c) values (1); +insert into t(c) values (2); +insert into t(c) values (3), (4), (5); +``` + +```sql +mysql> select * from t; ++----+---+ +| id | c | ++----+---+ +| 1 | 1 | +| 2 | 2 | +| 3 | 3 | +| 4 | 4 | +| 5 | 5 | ++----+---+ +5 rows in set (0.01 sec) +``` + +此外,`AUTO_INCREMENT` 还支持显式指定列值的插入语句,此时 TiDB 会保存显式指定的值: + +{{< copyable "sql" >}} + +```sql +insert into t(id, c) values (6, 6); +``` + +```sql +mysql> select * from t; ++----+---+ +| id | c | ++----+---+ +| 1 | 1 | +| 2 | 2 | +| 3 | 3 | +| 4 | 4 | +| 5 | 5 | +| 6 | 6 | ++----+---+ +6 rows in set (0.01 sec) +``` + +以上用法和 MySQL 的 `AUTO_INCREMENT` 用法一致。但在隐式分配的具体值方面,TiDB 和 MySQL 之间具有较为显著的差异。 + +## 实现原理 + +TiDB 实现 `AUTO_INCREMENT` 隐式分配的原理是,对于每一个自增列,都使用一个全局可见的键值对用于记录当前已分配的最大 ID。由于分布式环境下的节点通信存在一定开销,为了避免写请求放大的问题,每个 TiDB 节点在分配 ID 时,都申请一段 ID 作为缓存,用完之后再去取下一段,而不是每次分配都向存储节点申请。例如,对于以下新建的表: + +```sql +create table t(id int unique key AUTO_INCREMENT, c int); +``` + +假设集群中有两个 TiDB 实例 A 和 B,如果向 A 和 B 分别对 `t` 执行一条插入语句: + +```sql +insert into t (c) values (1) +``` + +实例 A 可能会缓存 `[1,30000]` 的自增 ID,而实例 B 则可能缓存 `[30001,60000]` 的自增 ID。各自实例缓存的 ID 将随着执行将来的插入语句被作为缺省值,顺序地填充到 `AUTO_INCREMENT` 列中。 + +## 基本特性 + +### 唯一性保证 + +> **警告:** +> +> 在集群中有多个 TiDB 实例时,如果表结构中有自增 ID,建议不要混用显式插入和隐式分配(即自增列的缺省值和自定义值),否则可能会破坏隐式分配值的唯一性。 + +例如在上述示例中,依次执行如下操作: + +1. 客户端向实例 B 插入一条将 `id` 设置为 `2` 的语句 `insert into t values (2, 1)`,并执行成功。 +2. 客户端向实例 A 发送 `Insert` 语句 `insert into t (c) (1)`,这条语句中没有指定 `id` 的值,所以会由 A 分配。当前 A 缓存了 `[1, 30000]` 这段 ID,可能会分配 `2` 为自增 ID 的值,并把本地计数器加 `1`。而此时数据库中已经存在 `id` 为 `2` 的数据,最终返回 `Duplicated Error` 错误。 + +### 递增性保证 + +`AUTO_INCREMENT` 列隐式分配值的递增性只能在含有单个 TiDB 实例的集群中得到保证:即对于同一个自增列,先分配的值小于后分配的值;而在含有多个 TiDB 实例的集群中,无法保证自增列的递增性。 + +例如,对于上述例子,如果先向实例 B 执行一条插入语句,再向实例 A 执行一条插入语句。根据缓存自增 ID 的性质,自增列隐式分配的值可能分别是 `30002` 和 `2`。因此从时间上看,不满足递增性。 + +### 连续性保证 + +在含有多个 TiDB 实例的集群中,`AUTO_INCREMENT` 分配值的连续性**只能**在 batch insert 语句中得到保证。 + +例如,对以下表执行以下语句: + +```sql +create table t (a int primary key AUTO_INCREMENT) +``` + +```sql +insert into t values (), (), (), () +``` + +即使存在正在执行并发写入的其他 TiDB 实例,或者当前实例剩余的缓存 ID 数量不够,都不会影响分配值的连续性。 + +### `_tidb_rowid` 的关联性 + +> **注意:** +> +> 在没有指定整数类型主键的情况下 TiDB 会使用 `_tidb_rowid` 来标识行,该数值的分配会和自增列(如果存在的话)共用一个分配器,其中缓存的大小可能会被自增列和 `_tidb_rowid` 共同消耗。因此会有以下的示例情况: + +```sql +mysql> create table t(id int unique key AUTO_INCREMENT); +Query OK, 0 rows affected (0.05 sec) + +mysql> insert into t values (),(),(); +Query OK, 3 rows affected (0.00 sec) +Records: 3 Duplicates: 0 Warnings: 0 + +mysql> select _tidb_rowid, id from t; ++-------------+------+ +| _tidb_rowid | id | ++-------------+------+ +| 4 | 1 | +| 5 | 2 | +| 6 | 3 | ++-------------+------+ +3 rows in set (0.01 sec) +``` + +### 缓存大小控制 + +TiDB 自增 ID 的缓存大小在早期版本中是对用户透明的。从 v3.1.2、v3.0.14 和 v4.0.rc-2 版本开始,TiDB 引入了 `AUTO_ID_CACHE` 表选项来允许用户自主设置自增 ID 分配缓存的大小。例如: + +```sql +mysql> create table t(a int auto_increment key) AUTO_ID_CACHE 100; +Query OK, 0 rows affected (0.02 sec) + +mysql> insert into t values(); +Query OK, 1 row affected (0.00 sec) +Records: 1 Duplicates: 0 Warnings: 0 + +mysql> select * from t; ++---+ +| a | ++---+ +| 1 | ++---+ +1 row in set (0.01 sec) +``` + +此时如果将该列的自增缓存无效化,重新进行隐式分配: + +```sql +mysql> delete from t; +Query OK, 1 row affected (0.01 sec) + +mysql> rename table t to t1; +Query OK, 0 rows affected (0.01 sec) + +mysql> insert into t1 values() +Query OK, 1 row affected (0.00 sec) + +mysql> select * from t; ++-----+ +| a | ++-----+ +| 101 | ++-----+ +1 row in set (0.00 sec) +``` + +可以看到再一次分配的值为 `101`,说明该表的自增 ID 分配缓存的大小为 `100`。 + +此外如果在批量插入的 `INSERT` 语句中所需连续 ID 长度超过 `AUTO_ID_CACHE` 的长度时,TiDB 会适当调大缓存以便能够保证该语句的正常插入。 + +### 自增步长和偏移量设置 + +从 v3.0.9 和 v4.0.rc-1 开始,和 MySQL 的行为类似,自增列隐式分配的值遵循 session 变量 `@@auto_increment_increment` 和 `@@auto_increment_offset` 的控制,其中自增列隐式分配的值 (ID) 将满足式子 `(ID - auto_increment_offset) % auto_increment_increment == 0`。 + +## 使用限制 + +目前在 TiDB 中使用 `AUTO_INCREMENT` 有以下限制: + +- 必须定义在主键或者唯一索引的列上。 +- 只能定义在类型为整数、`FLOAT` 或 `DOUBLE` 的列上。 +- 不支持与列的默认值 `DEFAULT` 同时指定在同一列上。 +- 不支持使用 `ALTER TABLE` 来添加 `AUTO_INCREMENT` 属性。 +- 支持使用 `ALTER TABLE` 来移除 `AUTO_INCREMENT` 属性。但从 TiDB 2.1.18 和 3.0.4 版本开始,TiDB 通过 session 变量 `@@tidb_allow_remove_auto_inc` 控制是否允许通过 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 来移除列的 `AUTO_INCREMENT` 属性,默认是不允许移除。 diff --git a/auto-random.md b/auto-random.md new file mode 100644 index 000000000000..aca2ecb93d1c --- /dev/null +++ b/auto-random.md @@ -0,0 +1,152 @@ +--- +title: AUTO_RANDOM +category: reference +summary: 本文介绍了 TiDB 的 `AUTO_RANDOM` 列属性。 +aliases: ['/docs-cn/stable/reference/sql/attributes/auto-random/'] +--- + +# AUTO_RANDOM 从 v3.1.0 版本开始引入 + +> **警告:** +> +> 当前 `AUTO_RANDOM` 属性为实验功能,**不建议在生产环境中使用**。在后续版本中,`AUTO_RANDOM` 的语法或语义可能会变化。 + +使用 `AUTO_RANDOM` 功能前,须在 TiDB 配置文件 `experimental` 部分设置 `allow-auto-random = true`。该参数详情可参见 [`allow-auto-random`](/tidb-configuration-file.md#allow-auto-random)。 + +## 使用场景 + +`AUTO_RANDOM` 用于解决大批量写数据入 TiDB 时因含有**整型自增主键列**的表而产生的热点问题。详情参阅 [TiDB 高并发写入场景最佳实践](/best-practices/high-concurrency-best-practices.md)。 + +以下面语句建立的表为例: + +```sql +create table t (a bigint primary key auto_increment, b varchar(255)) +``` + +在以上语句所建的表上执行大量未指定主键值的 `INSERT` 语句,示例如下: + +```sql +insert into t(b) values ('a'), ('b'), ('c') +``` + +如以上语句,由于未指定主键列的值(`a` 列),TiDB 会使用连续自增的行值作为行 ID,可能导致单个 TiKV 节点上产生写入热点,进而影响对外提供服务的性能。要避免这种性能下降,可以在执行建表语句时为 `a` 列指定 `AUTO_RANDOM` 属性而不是 `AUTO_INCREMENT` 属性。示例如下: + +{{< copyable "sql" >}} + +```sql +create table t (a bigint primary key auto_random, b varchar(255)) +``` + +或者 + +{{< copyable "sql" >}} + +```sql +create table t (a bigint auto_random, b varchar(255), primary key (a)) +``` + +此时再执行形如 `INSERT INTO t(b) values...` 的 `INSERT` 语句。 + ++ 隐式分配:如果该 `INSERT` 语句没有指定整型主键列(`a` 列)的值,或者指定为 `NULL`,TiDB 会为该列自动分配值。该值不保证自增,不保证连续,只保证唯一,避免了连续的行 ID 带来的热点问题。 ++ 显式插入:如果该 `INSERT` 语句显式指定了整型主键列的值,和 `AUTO_INCREMENT` 属性类似,TiDB 会保存该值。注意,如果未在系统变量 `@@sql_mode` 中设置 `NO_AUTO_VALUE_ON_ZERO`, 即使显式指定整型主键列的值为 `0`,TiDB 也会为该列自动分配值。 + +自动分配值的计算方式如下: + +该行值在二进制形式下,除去符号位的最高五位(称为 shard bits)由当前事务的开始时间决定,剩下的位数按照自增的顺序分配。 + +若要使用一个不同的 shard bits 的数量,可以在 `AUTO_RANDOM` 后面加一对括号,并在括号中指定想要的 shard bits 数量。示例如下: + +{{< copyable "sql" >}} + +```sql +create table t (a bigint primary key auto_random(3), b varchar(255)) +``` + +以上建表语句中,shard bits 的数量为 `3`。shard bits 的数量的取值范围是 `[1, field_max_bits)`,其中 `field_max_bits` 为整型主键列类型占用的位长度。 + +创建完表后,使用 `SHOW WARNINGS` 可以查看当前表可支持的最大隐式分配的次数: + +{{< copyable "sql" >}} + +```sql +show warnings +``` + +``` ++-------+------+----------------------------------------------------------+ +| Level | Code | Message | ++-------+------+----------------------------------------------------------+ +| Note | 1105 | Available implicit allocation times: 1152921504606846976 | ++-------+------+----------------------------------------------------------+ + +``` + +> **警告:** +> +> 建议用户使用 `bigint` 作为 `AUTO_RANDOM` 列类型,以获得最大的可隐式分配次数。 + +另外,要查看某张含有 `AUTO_RANDOM` 属性的表的 shard bits 数量,可以在系统表 `information_schema.tables` 中 `TIDB_ROW_ID_SHARDING_INFO` 一列看到模式为 `PK_AUTO_RANDOM_BITS=x` 的值,其中 `x` 为 shard bits 的数量。 + +`AUTO RANDOM` 列隐式分配的值会影响 `last_insert_id()`。可以使用 `select last_insert_id()` 获取上一次 TiDB 隐式分配的 ID,例如: + +{{< copyable "sql" >}} + +```sql +insert into t (b) values ("b") +select * from t; +select last_insert_id() +``` + +可能得到的结果如下: + +``` ++------------+---+ +| a | b | ++------------+---+ +| 1073741825 | b | ++------------+---+ + ++------------------+ +| last_insert_id() | ++------------------+ +| 1073741825 | ++------------------+ +``` + +## 兼容性 + +TiDB 支持解析版本注释语法。示例如下: + +{{< copyable "sql" >}} + +```sql +create table t (a bigint primary key /*T![auto_rand] auto_random */) +``` + +{{< copyable "sql" >}} + +```sql +create table t (a bigint primary key auto_random) +``` + +以上两个语句含义相同。 + +在 `show create table` 的结果中,`AUTO_RANDOM` 属性会被注释掉。注释会附带一个特性标识符,例如 `/*T![auto_rand] auto_random */`。其中 `auto_rand` 表示 `AUTO_RANDOM` 的特性标识符,只有实现了该标识符对应特性的 TiDB 版本才能够正常解析 SQL 语句片段。 + +该功能支持向前兼容,即降级兼容。没有实现对应特性的 TiDB 版本则会忽略表(带有上述注释)的 `AUTO_RANDOM` 属性,因此能够使用含有该属性的表。 + +## 使用限制 + +目前在 TiDB 中使用 `AUTO_RANDOM` 有以下限制: + +- 该属性必须指定在整数类型的主键列上,否则会报错。例外情况见[关于 `alter-primary-key` 配置项的说明](#关于-alter-primary-key-配置项的说明)。 +- 不支持使用 `ALTER TABLE` 来修改 `AUTO_RANDOM` 属性,包括添加或移除该属性。 +- 不支持修改含有 `AUTO_RANDOM` 属性的主键列的列类型。 +- 不支持与 `AUTO_INCREMENT` 同时指定在同一列上。 +- 不支持与列的默认值 `DEFAULT` 同时指定在同一列上。 +- 插入数据时,不建议自行显式指定含有 `AUTO_RANDOM` 列的值。不恰当地显式赋值,可能会导致该表提前耗尽用于自动分配的数值。 + +### 关于 `alter-primary-key` 配置项的说明 + +- 当 `alter-primary-key = true` 时,即使是整型主键列,也不支持使用 `AUTO_RANDOM`。 +- 配置文件中的 `alter-primary-key` 和 `allow-auto-random` 两个配置项的值不允许同时为 `true`。 diff --git a/backup-and-restore-using-mydumper-lightning.md b/backup-and-restore-using-mydumper-lightning.md new file mode 100644 index 000000000000..d056c1edb7ac --- /dev/null +++ b/backup-and-restore-using-mydumper-lightning.md @@ -0,0 +1,95 @@ +--- +title: 使用 Mydumper/TiDB Lightning 进行备份与恢复 +category: how-to +aliases: ['/docs-cn/stable/how-to/maintain/backup-and-restore/mydumper-lightning/'] +--- + +# 使用 Mydumper/TiDB Lightning 进行备份与恢复 + +本文档将详细介绍如何使用 Mydumper/TiDB Lightning 对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md)。 + +这里假定 TiDB 服务信息如下: + +|Name|Address|Port|User|Password| +|----|-------|----|----|--------| +|TiDB|127.0.0.1|4000|root|*| + +在这个备份恢复过程中,会用到下面的工具: + +- [Mydumper](/mydumper-overview.md) 从 TiDB 导出数据 +- [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 导入数据到 TiDB + +## 使用 Mydumper/TiDB Lightning 全量备份恢复数据 + +`mydumper` 是一个强大的数据备份工具,具体可以参考 [`maxbube/mydumper`](https://github.com/maxbube/mydumper)。 + +可使用 [Mydumper](/mydumper-overview.md) 从 TiDB 导出数据进行备份,然后用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 将其导入到 TiDB 里面进行恢复。 + +> **注意:** +> +> PingCAP 研发团队对 `mydumper` 进行了针对 TiDB 的适配性改造,建议使用 PingCAP 官方提供的 [Mydumper](/mydumper-overview.md)。由于使用 `mysqldump` 进行数据备份和恢复都要耗费许多时间,这里也并不推荐。 + +### Mydumper/TiDB Lightning 全量备份恢复最佳实践 + +为了快速地备份恢复数据 (特别是数据量巨大的库),可以参考以下建议: + +* 导出来的数据文件应当尽可能的小,可以通过设置参数 `-F` 来控制导出来的文件大小。如果后续使用 TiDB Lightning 对备份文件进行恢复,建议把 `mydumper` -F 参数的值设置为 `256`(单位 MB);如果使用 `loader` 恢复,则建议设置为 `64`(单位 MB)。 + +## 从 TiDB 备份数据 + +我们使用 `mydumper` 从 TiDB 备份数据,如下: + +{{< copyable "shell-regular" >}} + +```bash +./bin/mydumper -h 127.0.0.1 -P 4000 -u root -t 32 -F 256 -B test -T t1,t2 --skip-tz-utc -o ./var/test +``` + +上面,我们使用 `-B test` 表明是对 `test` 这个 database 操作,然后用 `-T t1,t2` 表明只导出 `t1`,`t2` 两张表。 + +`-t 32` 表明使用 32 个线程去导出数据。`-F 256` 是将实际的表切分成一定大小的 chunk,这里的 chunk 大小为 256MB。 + +添加 `--skip-tz-utc` 参数后,会忽略掉 TiDB 与导数据的机器之间时区设置不一致的情况,禁止自动转换。 + +如果 `mydumper` 出现以下报错: + +``` +** (mydumper:27528): CRITICAL **: 13:25:09.081: Could not read data from testSchema.testTable: GC life time is shorter than transaction duration, transaction starts at 2019-08-05 21:10:01.451 +0800 CST, GC safe point is 2019-08-05 21:14:53.801 +0800 CST +``` + +就再执行两步命令: + +1. 执行 `mydumper` 命令前,查询 TiDB 集群的 [GC](/garbage-collection-overview.md) 值并使用 MySQL 客户端将其调整为合适的值: + + {{< copyable "sql" >}} + + ```sql + SELECT * FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'; + ``` + + ``` + +-----------------------+------------------------------------------------------------------------------------------------+ + | VARIABLE_NAME | VARIABLE_VALUE | + +-----------------------+------------------------------------------------------------------------------------------------+ + | tikv_gc_life_time | 10m0s | + +-----------------------+------------------------------------------------------------------------------------------------+ + 1 rows in set (0.02 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + update mysql.tidb set VARIABLE_VALUE = '720h' where VARIABLE_NAME = 'tikv_gc_life_time'; + ``` + +2. 执行 `mydumper` 命令后,将 TiDB 集群的 GC 值恢复到第 1 步中的初始值: + + {{< copyable "sql" >}} + + ```sql + update mysql.tidb set VARIABLE_VALUE = '10m' where VARIABLE_NAME = 'tikv_gc_life_time'; + ``` + +## 向 TiDB 恢复数据 + +使用 TiDB Lightning 将之前导出的数据导入到 TiDB,完成恢复操作。具体的使用方法见 [TiDB Lightning 使用文档](/tidb-lightning/tidb-lightning-tidb-backend.md) diff --git a/basic-features.md b/basic-features.md new file mode 100644 index 000000000000..2ff9db7f3fe6 --- /dev/null +++ b/basic-features.md @@ -0,0 +1,88 @@ +--- +title: TiDB 基本功能 +category: introduction +--- + +# TiDB 基本功能 + +本文详细介绍 TiDB 具备的基本功能。 + +## 数据类型 + +- 数值类型: BIT、BOOL|BOOLEAN、SMALLINT、MEDIUMINT、INT|INTEGER、BIGINT、FLOAT、DOUBLE、DECIMAL。 + +- 日期和时间类型: DATE、TIME、DATETIME、TIMESTAMP、YEAR。 + +- 字符串类型: CHAR、VARCHAR、TEXT、TINYTEXT、MEDIUMTEXT、LONGTEXT、BINARY、VARBINARY、BLOB、TINYBLOB、MEDIUMBLOB、LONGBLOB、ENUM、SET。 + +- JSON 类型。 + +## 运算符 + +- 算术运符、位运算符、比较运算符、逻辑运算符、日期和时间运算符等。 + +## 字符集及排序规则 + +- 字符集:UTF8、UTF8MB4、BINARY、ASCII、LATIN1。 + +- 排序规则:UTF8MB4_GENERAL_CI、UTF8MB4_GENERAL_BIN、UTF8_GENERAL_CI、UTF8_GENERAL_BIN、BINARY。 + +## 函数 + +- 控制流函数、字符串函数、日期和时间函数、位函数、数据类型转换函数、数据加解密函数、压缩和解压函数、信息函数、JSON 函数、聚合函数、窗口函数、信息函数等。 + +## SQL 语句 + +- 完全支持标准的 Data Definition Statements 语句,例如:CREATE、DROP、ALTER、RENAME、TRUNCATE 等。 + +- 完全支持标准的 Data Manipulation Statements 语名,例如:INSERT、REPLACE、SELECT、Subqueries、UPDATE、LOAD DATA 等。 + +- 完全支持标准的 Transactional and Locking Statements 语名,例如:START TRANSACTION、COMMIT、ROLLBACK、SET TRANSACTION 等。 + +- 完全支持标准的 Database Administration Statements 语名,例如:SHOW、SET 等。 + +- 完全支持标准的 Utility Statements语句, 例如:DESCRIBE、EXPLAIN、USE 等。 + +- 完全支持 SQL GROUP BY 和 ORDER BY 子语句。 + +- 完全支持标准 SQL 语法的 LEFT OUTER JOIN 和 RIGHT OUTER JOIN。 + +- 完全支持标准 SQL 要求的表和列别名。 + +## 分区表 + +- 支持 Range 分区。 + +- 支持 Hash 分区。 + +## 视图 + +- 支持普通视图。 + +## 约束 + +- 支持非空约束。 + +- 支持主键约束。 + +- 支持唯一约束。 + +## 安全 + +- 支持基于 RBAC 的权限管理。 + +- 支持密码管理。 + +- 支持通信、数据加密。 + +- 支持 IP 白名单。 + +- 支持审计功能。 + +## 工具 + +- 支持快速备份功能 + +- 支持通过工具从 MySQL 迁移数据到 TiDB。 + +- 支持通过工具部署、运维 TiDB。 diff --git a/basic-sql-operations.md b/basic-sql-operations.md new file mode 100644 index 000000000000..998c05f80ba4 --- /dev/null +++ b/basic-sql-operations.md @@ -0,0 +1,282 @@ +--- +title: SQL 基本操作 +category: how-to +aliases: ['/docs-cn/stable/how-to/get-started/explore-sql/'] +--- + +# SQL 基本操作 + +成功部署 TiDB 集群之后,便可以在 TiDB 中执行 SQL 语句了。因为 TiDB 兼容 MySQL,你可以使用 MySQL 客户端连接 TiDB,并且[大多数情况下](/mysql-compatibility.md)可以直接执行 MySQL 语句。 + +SQL 是一门声明性语言,它是数据库用户与数据库交互的方式。它更像是一种自然语言,好像在用英语与数据库进行对话。本文档介绍基本的 SQL 操作。完整的 SQL 语句列表,参见 [TiDB SQL 语法详解](https://pingcap.github.io/sqlgram/)。 + +## 分类 + +SQL 语言通常按照功能划分成以下的 4 个部分: + +- DDL (Data Definition Language):数据定义语言,用来定义数据库对象,包括库、表、视图和索引等。 + +- DML (Data Manipulation Language):数据操作语言,用来操作和业务相关的记录。 + +- DQL (Data Query Language):数据查询语言,用来查询经过条件筛选的记录。 + +- DCL (Data Control Language):数据控制语言,用来定义访问权限和安全级别。 + +常用的 DDL 功能是对象(如表、索引等)的创建、属性修改和删除,对应的命令分别是 CREATE、ALTER 和 DROP。 + +## 查看、创建和删除数据库 + +TiDB 语境中的 Database 或者说数据库,可以认为是表和索引等对象的集合。 + +使用 `SHOW DATABASES` 语句查看系统中数据库列表: + +{{< copyable "sql" >}} + +```sql +SHOW DATABASES; +``` + +使用名为 `mysql` 的数据库: + +{{< copyable "sql" >}} + +```sql +use mysql; +``` + +使用 `SHOW TABLES` 语句查看数据库中的所有表。例如: + +{{< copyable "sql" >}} + +```sql +SHOW TABLES FROM mysql; +``` + +使用 `CREATE DATABASE` 语句创建数据库。语法如下: + +{{< copyable "sql" >}} + +```sql +CREATE DATABASE db_name [options]; +``` + +例如,要创建一个名为 `samp_db` 的数据库,可使用以下语句: + +{{< copyable "sql" >}} + +```sql +CREATE DATABASE IF NOT EXISTS samp_db; +``` + +添加 `IF NOT EXISTS` 可防止发生错误。 + +使用 `DROP DATABASE` 语句删除数据库。例如: + +{{< copyable "sql" >}} + +```sql +DROP DATABASE samp_db; +``` + +## 创建、查看和删除表 + +使用 `CREATE TABLE` 语句创建表。语法如下: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE table_name column_name data_type constraint; +``` + +例如,要创建一个名为 `person` 的表,包括编号、名字、生日等字段,可使用以下语句: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE person ( + id INT(11), + name VARCHAR(255), + birthday DATE + ); +``` + +使用 `SHOW CREATE` 语句查看建表语句,即 DDL。例如: + +{{< copyable "sql" >}} + +```sql +SHOW CREATE table person; +``` + +使用 `DROP TABLE` 语句删除表。例如: + +{{< copyable "sql" >}} + +```sql +DROP TABLE person; +``` + +## 创建、查看和删除索引 + +索引通常用于加速索引列上的查询。对于值不唯一的列,可使用 `CREATE INDEX` 或 `ALTER TABLE` 语句创建普通索引。例如: + +{{< copyable "sql" >}} + +```sql +CREATE INDEX person_id ON person (id); +``` + +或者: + +{{< copyable "sql" >}} + +```sql +ALTER TABLE person ADD INDEX person_id (id); +``` + +对于值唯一的列,可以创建唯一索引。例如: + +{{< copyable "sql" >}} + +```sql +CREATE UNIQUE INDEX person_unique_id ON person (id); +``` + +或者: + +{{< copyable "sql" >}} + +```sql +ALTER TABLE person ADD UNIQUE person_unique_id (id); +``` + +使用 `SHOW INDEX` 语句查看表内所有索引: + +{{< copyable "sql" >}} + +```sql +SHOW INDEX from person; +``` + +使用 `ALTER TABLE` 或 `DROP INDEX` 语句来删除索引。与 `CREATE INDEX` 语句类似,`DROP INDEX` 也可以嵌入 `ALTER TABLE` 语句。例如: + +{{< copyable "sql" >}} + +```sql +DROP INDEX person_id ON person; +``` + +{{< copyable "sql" >}} + +```sql +ALTER TABLE person DROP INDEX person_unique_id; +``` + +注意:DDL 操作不是事务,在执行 DDL 时,不需要对应 COMMIT 语句。 + +常用的 DML 功能是对表记录的新增、修改和删除,对应的命令分别是 INSERT、UPDATE 和 DELETE。 + +## 记录的增删改 + +使用 `INSERT` 语句向表内插入表记录。例如: + +{{< copyable "sql" >}} + +```sql +INSERT INTO person VALUES("1","tom","20170912"); +``` + +使用 `INSERT` 语句向表内插入包含部分字段数据的表记录。例如: + +{{< copyable "sql" >}} + +```sql +INSERT INTO person(id,name) VALUES("2","bob"); +``` + +使用 `UPDATE` 语句向表内修改表记录的部分字段数据。例如: + +{{< copyable "sql" >}} + +```sql +UPDATE person SET birthday="20180808" WHERE id=2; +``` + +使用 `DELETE` 语句向表内删除部分表记录。例如: + +{{< copyable "sql" >}} + +```sql +DELETE FROM person WHERE id=2; +``` + +注意:UPDATE 和 DELETE 操作如果不带 WHERE 过滤条件是对全表进行操作。 + +DQL 数据查询语言是从一个表或多个表中检索出想要的数据行,通常是业务开发的核心内容。 + +## 查询数据 + +使用 `SELECT` 语句检索表内数据。例如: + +{{< copyable "sql" >}} + +```sql +SELECT * FROM person; +``` + +在 SELECT 后面加上要查询的列名。例如: + +{{< copyable "sql" >}} + +```sql +SELECT name FROM person; ++------+ +| name | ++------+ +| tom | ++------+ +``` + +使用 WHERE 子句,对所有记录进行是否符合条件的筛选后再返回。例如: + +{{< copyable "sql" >}} + +```sql +SELECT * FROM person where id<5; +``` + +常用的 DCL 功能是创建或删除用户,和对用户权限的管理。 + +## 创建、授权和删除用户 + +使用 `CREATE USER` 语句创建一个用户 `tiuser`,密码为 `123456`: + +{{< copyable "sql" >}} + +```sql +CREATE USER 'tiuser'@'localhost' IDENTIFIED BY '123456'; +``` + +授权用户 `tiuser` 可检索数据库 `samp_db` 内的表: + +{{< copyable "sql" >}} + +```sql +GRANT SELECT ON samp_db.* TO 'tiuser'@'localhost'; +``` + +查询用户 `tiuser` 的权限: + +{{< copyable "sql" >}} + +```sql +SHOW GRANTS for tiuser@localhost; +``` + +删除用户 `tiuser`: + +{{< copyable "sql" >}} + +```sql +DROP USER 'tiuser'@'localhost'; +``` diff --git a/benchmark/add-index-with-load.md b/benchmark/add-index-with-load.md deleted file mode 100644 index 351461fa815c..000000000000 --- a/benchmark/add-index-with-load.md +++ /dev/null @@ -1,348 +0,0 @@ ---- -title: 线上负载与 `ADD INDEX` 相互影响测试 -category: benchmark ---- - -# 线上负载与 `ADD INDEX` 相互影响测试 - -## 测试目的 - -测试 OLTP 场景下,`ADD INDEX` 与线上负载的相互影响。 - -## 测试版本、时间、地点 - -TiDB 版本:v3.0.1 - -时间:2019 年 7 月 - -地点:北京 - -## 测试环境 - -测试在 Kubernetes 集群上进行,部署了 3 个 TiDB 实例,3 个 TiKV 实例和 3 个 PD 实例。 - -### 版本信息 - -| 组件 | GitHash | -| :--- | :---------------------------------------- | -| TiDB | `9e4e8da3c58c65123db5f26409759fe1847529f8` | -| TiKV | `4151dc8878985df191b47851d67ca21365396133` | -| PD | `811ce0b9a1335d1b2a049fd97ef9e186f1c9efc1` | - -Sysbench 版本:1.0.17 - -### TiDB 参数配置 - -TiDB、TiKV 和 PD 均使用 [TiDB Operator](https://github.com/pingcap/tidb-operator) 默认配置。 - -### 集群拓扑 - -| 机器 IP | 部署实例 | -| :-------------------------------------- | :----------| -| 172.31.8.8 | Sysbench | -| 172.31.7.69, 172.31.5.152, 172.31.11.133 | PD | -| 172.31.4.172, 172.31.1.155, 172.31.9.210 | TiKV | -| 172.31.7.80, 172.31.5.163, 172.31.11.123 | TiDB | - -### 使用 Sysbench 模拟线上负载 - -使用 Sysbench 向集群导入 **1 张表,200 万行数据**。 - -执行如下命令导入数据: - -{{< copyable "shell-regular" >}} - -```sh -sysbench oltp_common \ - --threads=16 \ - --rand-type=uniform \ - --db-driver=mysql \ - --mysql-db=sbtest \ - --mysql-host=$tidb_host \ - --mysql-port=$tidb_port \ - --mysql-user=root \ - prepare --tables=1 --table-size=2000000 -``` - -执行如下命令测试数据: - -{{< copyable "shell-regular" >}} - -```sh -sysbench $testname \ - --threads=$threads \ - --time=300000 \ - --report-interval=15 \ - --rand-type=uniform \ - --rand-seed=$RANDOM \ - --db-driver=mysql \ - --mysql-db=sbtest \ - --mysql-host=$tidb_host \ - --mysql-port=$tidb_port \ - --mysql-user=root \ - run --tables=1 --table-size=2000000 -``` - -## 测试方案 1:`ADD INDEX` 目标列被频繁 Update - -1. 开始 `oltp_read_write` 测试。 -2. 与步骤 1 同时,使用 `alter table sbtest1 add index c_idx(c)` 添加索引。 -3. 在步骤 2 结束,即索引添加完成时,停止步骤 1 的测试。 -4. 获取 `alter table ... add index` 的运行时间、sysbench 在该时间段内的平均 TPS 和 QPS 作为指标。 -5. 逐渐增大 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 两个参数的值,重复步骤 1-4。 - -### 测试结果 - -#### 无 `ADD INDEX` 时 `oltp_read_write` 的结果 - -| sysbench TPS | sysbench QPS | -| :------- | :-------- | -| 350.31 | 6806 | - -#### `tidb_ddl_reorg_batch_size = 32` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 402 | 338.4 | 6776 | -| 2 | 266 | 330.3 | 6001 | -| 4 | 174 | 288.5 | 5769 | -| 8 | 129 | 280.6 | 5612 | -| 16 | 90 | 263.5 | 5273 | -| 32 | 54 | 229.2 | 4583 | -| 48 | 57 | 230.1 | 4601 | - -![add-index-load-1-b32](/media/add-index-load-1-b32.png) - -#### `tidb_ddl_reorg_batch_size = 64` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 264 | 269.4 | 5388 | -| 2 | 163 | 266.2 | 5324 | -| 4 | 105 | 272.5 | 5430 | -| 8 | 78 | 262.5 | 5228 | -| 16 | 57 | 215.5 | 4308 | -| 32 | 42 | 185.2 | 3715 | -| 48 | 45 | 189.2 | 3794 | - -![add-index-load-1-b64](/media/add-index-load-1-b64.png) - -#### `tidb_ddl_reorg_batch_size = 128` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 171 | 289.1 | 5779 | -| 2 | 110 | 274.2 | 5485 | -| 4 | 79 | 250.6 | 5011 | -| 8 | 51 | 246.1 | 4922 | -| 16 | 39 | 171.1 | 3431 | -| 32 | 35 | 130.8 | 2629 | -| 48 | 35 | 120.5 | 2425 | - -![add-index-load-1-b128](/media/add-index-load-1-b128.png) - -#### `tidb_ddl_reorg_batch_size = 256` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 145 | 283.0 | 5659 | -| 2 | 96 | 282.2 | 5593 | -| 4 | 56 | 236.5 | 4735 | -| 8 | 45 | 194.2 | 3882 | -| 16 | 39 | 149.3 | 2893 | -| 32 | 36 | 113.5 | 2268 | -| 48 | 33 | 86.2 | 1715 | - -![add-index-load-1-b256](/media/add-index-load-1-b256.png) - -#### `tidb_ddl_reorg_batch_size = 512` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 135 | 257.8 | 5147 | -| 2 | 78 | 252.8 | 5053 | -| 4 | 49 | 222.7 | 4478 | -| 8 | 36 | 145.4 | 2904 | -| 16 | 33 | 109 | 2190 | -| 32 | 33 | 72.5 | 1503 | -| 48 | 33 | 54.2 | 1318 | - -![add-index-load-1-b512](/media/add-index-load-1-b512.png) - -#### `tidb_ddl_reorg_batch_size = 1024` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 111 | 244.3 | 4885 | -| 2 | 78 | 228.4 | 4573 | -| 4 | 54 | 168.8 | 3320 | -| 8 | 39 | 123.8 | 2475 | -| 16 | 36 | 59.6 | 1213 | -| 32 | 42 | 93.2 | 1835 | -| 48 | 51 | 115.7 | 2261 | - -![add-index-load-1-b1024](/media/add-index-load-1-b1024.png) - -#### `tidb_ddl_reorg_batch_size = 2048` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 918 | 243.3 | 4855 | -| 2 | 1160 | 209.9 | 4194 | -| 4 | 342 | 185.4 | 3707 | -| 8 | 1316 | 151.0 | 3027 | -| 16 | 795 | 30.5 | 679 | -| 32 | 1130 | 26.69 | 547 | -| 48 | 893 | 27.5 | 552 | - -![add-index-load-1-b2048](/media/add-index-load-1-b2048.png) - -#### `tidb_ddl_reorg_batch_size = 4096` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 3042 | 200.0 | 4001 | -| 2 | 3022 | 203.8 | 4076 | -| 4 | 858 | 195.5 | 3971 | -| 8 | 3015 | 177.1 | 3522 | -| 16 | 837 | 143.8 | 2875 | -| 32 | 942 | 114 | 2267 | -| 48 | 187 | 54.2 | 1416 | - -![add-index-load-1-b4096](/media/add-index-load-1-b4096.png) - -### 测试结论 - -若 `ADD INDEX` 的目标列正在进行较为频繁的写操作(本测试涉及列的 `UPDATE`、`INSERT` 和 `DELETE`),默认 `ADD INDEX` 配置对系统的线上负载有比较明显的影响,该影响主要来源于 `ADD INDEX` 与 Column Update 并发进行造成的写冲突,系统的表现反应在: - -- 随着两个参数的逐渐增大,`TiKV_prewrite_latch_wait_duration` 有明显的升高,造成写入变慢。 -- `tidb_ddl_reorg_worker_cnt` 与 `tidb_ddl_reorg_batch_size` 非常大时,`admin show ddl` 命令可以看到 DDL job 的多次重试(例如 `Write conflict, txnStartTS 410327455965380624 is stale [try again later], ErrCount:38, SnapshotVersion:410327228136030220`),此时 `ADD INDEX` 会持续非常久才能完成。 - -## 测试方案 2:`ADD INDEX` 目标列不涉及写入(仅查询) - -1. 开始 `oltp_read_only` 测试。 -2. 与步骤 1 同时,使用 `alter table sbtest1 add index c_idx(c)` 添加索引。 -3. 在步骤 2 结束,即索引添加完成时,停止步骤 1。 -4. 获取 `alter table ... add index` 的运行时间、sysbench 在该时间段内的平均 TPS 和 QPS 作为指标。 -5. 逐渐增大 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 两个参数,重复步骤 1-4。 - -### 测试结果 - -#### 无 `ADD INDEX` 时 `oltp_read_only` 结果 - -| sysbench TPS | sysbench QPS | -| :------- | :-------- | -| 550.9 | 8812.8 | - -#### `tidb_ddl_reorg_batch_size = 32` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 376 | 548.9 | 8780 | -| 2 | 212 | 541.5 | 8523 | -| 4 | 135 | 538.6 | 8549 | -| 8 | 114 | 536.7 | 8393 | -| 16 | 77 | 533.9 | 8292 | -| 32 | 46 | 533.4 | 8103 | -| 48 | 46 | 532.2 | 8074 | - -![add-index-load-2-b32](/media/add-index-load-2-b32.png) - -#### `tidb_ddl_reorg_batch_size = 1024` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 91 | 536.8 | 8316 | -| 2 | 52 | 533.9 | 8165 | -| 4 | 40 | 522.4 | 7947 | -| 8 | 36 | 510 | 7860 | -| 16 | 33 | 485.5 | 7704 | -| 32 | 31 | 467.5 | 7516 | -| 48 | 30 | 562.1 | 7442 | - -![add-index-load-2-b1024](/media/add-index-load-2-b1024.png) - -#### `tidb_ddl_reorg_batch_size = 4096` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 103 | 502.2 | 7823 | -| 2 | 63 | 486.5 | 7672 | -| 4 | 52 | 467.4 | 7516 | -| 8 | 39 | 452.5 | 7302 | -| 16 | 35 | 447.2 | 7206 | -| 32 | 30 | 441.9 | 7057 | -| 48 | 30 | 440.1 | 7004 | - -![add-index-load-2-b4096](/media/add-index-load-2-b4096.png) - -### 测试结论 - -`ADD INDEX` 的目标列仅有查询负载时,`ADD INDEX` 对负载的影响不明显。 - -## 测试方案 3:集群负载不涉及 `ADD INDEX` 目标列 - -1. 开始 `oltp_read_write` 测试。 -2. 与步骤 1 同时,使用 `alter table test add index pad_idx(pad)` 添加索引。 -3. 在步骤 2 结束,即索引添加完成时,停止步骤 1 的测试。 -4. 获取 `alter table ... add index` 的运行时间、sysbench 在该时间段内的平均 TPS 和 QPS 作为指标。 -5. 逐渐增大 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 两个参数,重复步骤 1-4。 - -### 测试结果 - -#### 无 `ADD INDEX` 时 `oltp_read_write` 的结果 - -| sysbench TPS | sysbench QPS | -| :------- | :-------- | -| 350.31 | 6806 | - -#### `tidb_ddl_reorg_batch_size = 32` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 372 | 350.4 | 6892 | -| 2 | 207 | 344.2 | 6700 | -| 4 | 140 | 343.1 | 6672 | -| 8 | 121 | 339.1 | 6579 | -| 16 | 76 | 340 | 6607 | -| 32 | 42 | 343.1 | 6695 | -| 48 | 42 | 333.4 | 6454 | - -![add-index-load-3-b32](/media/add-index-load-3-b32.png) - -#### `tidb_ddl_reorg_batch_size = 1024` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 94 | 352.4 | 6794 | -| 2 | 50 | 332 | 6493 | -| 4 | 45 | 330 | 6456 | -| 8 | 36 | 325.5 | 6324 | -| 16 | 32 | 312.5 | 6294 | -| 32 | 32 | 300.6 | 6017 | -| 48 | 31 | 279.5 | 5612 | - -![add-index-load-3-b1024](/media/add-index-load-3-b1024.png) - -#### `tidb_ddl_reorg_batch_size = 4096` - -| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | -| :------------------------ | :---------------------- | :------------- | :----------- | -| 1 | 116 | 325.5 | 6324 | -| 2 | 65 | 312.5 | 6290 | -| 4 | 50 | 300.6 | 6017 | -| 8 | 37 | 279.5 | 5612 | -| 16 | 34 | 250.4 | 5365 | -| 32 | 32 | 220.2 | 4924 | -| 48 | 33 | 214.8 | 4544 | - -![add-index-load-3-b4096](/media/add-index-load-3-b4096.png) - -### 测试结论 - -`ADD INDEX` 的目标列与负载无关时,`ADD INDEX` 对负载的影响不明显。 - -## 总结 - -- 当 `ADD INDEX` 的目标列被频繁更新(包含 `UPDATE`、`INSERT` 和 `DELETE`)时,默认配置会造成较为频繁的写冲突,使得在线负载较大;同时 `ADD INDEX` 也可能由于不断地重试,需要很长的时间才能完成。在本次测试中,将 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 的乘积调整为默认值的 1/32(例如 `tidb_ddl_reorg_worker_cnt` = 4,`tidb_ddl_reorg_batch_size` = 256)可以取得较好的效果。 -- 当 `ADD INDEX` 的目标列仅涉及查询负载,或者与线上负载不直接相关时,可以直接使用默认配置。 \ No newline at end of file diff --git a/benchmark/benchmark-sysbench-v2.md b/benchmark/benchmark-sysbench-v2.md new file mode 100644 index 000000000000..f16a41ff36ed --- /dev/null +++ b/benchmark/benchmark-sysbench-v2.md @@ -0,0 +1,130 @@ +--- +title: TiDB Sysbench 性能对比测试报告 - v2.0.0 对比 v1.0.0 +category: benchmark +aliases: ['/docs-cn/stable/benchmark/sysbench-v2/'] +--- + +# TiDB Sysbench 性能对比测试报告 - v2.0.0 对比 v1.0.0 + +## 测试目的 + +对比 TiDB 2.0 版本和 1.0 版本在 OLTP 场景下的性能。 + +## 测试版本、时间、地点 + +TiDB 版本:v1.0.8 Vs v2.0.0-rc6 + +时间:2018 年 4 月 + +地点:北京 + +## 测试环境 + +IDC 机器 + +| 类别 | 名称 | +| :--------: | :---------: | +| OS | Linux (CentOS 7.3.1611) | +| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | +| RAM | 128GB | +| DISK | Optane 500GB SSD * 1 | + +## 测试方案 + +### TiDB 版本信息 + +### v1.0.8 + +| 组件 | GitHash | +| :--------: | :---------: | +| TiDB | 571f0bbd28a0b8155a5ee831992c986b90d21ab7 | +| TiKV | 4ef5889947019e3cb55cc744f487aa63b42540e7 | +| PD | 776bcd940b71d295a2c7ed762582bc3aff7d3c0e | + +### v2.0.0-rc6 + +| 组件 | GitHash | +| :--------: | :---------: | +| TiDB | 82d35f1b7f9047c478f4e1e82aa0002abc8107e7 | +| TiKV | 7ed4f6a91f92cad5cd5323aaebe7d9f04b77cc79 | +| PD | 2c8e7d7e33b38e457169ce5dfb2f461fced82d65 | + +### TiKV 参数配置 + +* v1.0.8 + + ``` + sync-log = false + grpc-concurrency = 8 + grpc-raft-conn-num = 24 + ``` + +* v2.0.0-rc6 + + ``` + sync-log = false + grpc-concurrency = 8 + grpc-raft-conn-num = 24 + use-delete-range: false + ``` + +### 集群拓扑 + +| 机器 IP | 部署实例 | +|--------------|------------| +| 172.16.21.1 | 1*tidb 1*pd 1*sysbench | +| 172.16.21.2 | 1*tidb 1*pd 1*sysbench | +| 172.16.21.3 | 1*tidb 1*pd 1*sysbench | +| 172.16.11.4 | 1*tikv | +| 172.16.11.5 | 1*tikv | +| 172.16.11.6 | 1*tikv | +| 172.16.11.7 | 1*tikv | +| 172.16.11.8 | 1*tikv | +| 172.16.11.9 | 1*tikv | + +## 测试结果 + +### 标准 Select 测试 + +| 版本 | table count | table size | sysbench threads |qps | latency(avg / .95) | +| :---: | :---: | :---: | :---: | :---: | :---: | +| v2.0.0-rc6 | 32 | 1000 万 | 128 * 3 | 201936 | 1.9033 ms / 5.67667 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 256 * 3 | 208130 | 3.69333 ms / 8.90333 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 512 * 3 | 211788 | 7.23333 ms / 15.59 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 1024 * 3 | 212868 | 14.5933 ms / 43.2133 ms | +| v1.0.8 | 32 | 1000 万 | 128 * 3 | 188686 | 2.03667 ms / 5.99 ms | +| v1.0.8 | 32 | 1000 万 | 256 * 3 | 195090 |3.94 ms / 9.12 ms | +| v1.0.8 | 32 | 1000 万 | 512 * 3 | 203012 | 7.57333 ms / 15.3733 ms | +| v1.0.8 | 32 | 1000 万 | 1024 * 3 | 205932 | 14.9267 ms / 40.7633 ms | + +GA2.0 比 GA1.0 在 Select 查询性能上,最高提升了 10% 左右。 + +### 标准 OLTP 测试 + +| 版本 | table count | table size | sysbench threads | tps | qps | latency(avg / .95) | +| :---: | :---: | :---: | :---: | :---: | :---: | :---:| +| v2.0.0-rc6 | 32 | 1000 万 | 128 * 3 | 5404.22 | 108084.4 | 87.2033 ms / 110 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 256 * 3 | 5578.165 | 111563.3 | 167.673 ms / 275.623 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 512 * 3 | 5874.045 | 117480.9 | 315.083 ms / 674.017 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 1024 * 3 | 6290.7 | 125814 | 529.183 ms / 857.007 ms | +| v1.0.8 | 32 | 1000 万 | 128 * 3 | 5523.91 | 110478 | 69.53 ms / 88.6333 ms | +| v1.0.8 | 32 | 1000 万 | 256 * 3 | 5969.43 | 119389 |128.63 ms / 162.58 ms | +| v1.0.8 | 32 | 1000 万 | 512 * 3 | 6308.93 | 126179 | 243.543 ms / 310.913 ms | +| v1.0.8 | 32 | 1000 万 | 1024 * 3 | 6444.25 | 128885 | 476.787ms / 635.143 ms | + +GA2.0 比 GA1.0 在 OLTP 性能上,性能基本一致。 + +### 标准 Insert 测试 + +| 版本 | table count | table size | sysbench threads |qps | latency(avg / .95) | +| :---: | :---: | :---: | :---: | :---: | :---: | +| v2.0.0-rc6 | 32 | 1000 万 | 128 * 3 | 31707.5 | 12.11 ms / 21.1167 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 256 * 3 | 38741.2 | 19.8233 ms / 39.65 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 512 * 3 | 45136.8 | 34.0267 ms / 66.84 ms | +| v2.0.0-rc6 | 32 | 1000 万 | 1024 * 3 | 48667 | 63.1167 ms / 121.08 ms | +| v1.0.8 | 32 | 1000 万 | 128 * 3 | 31125.7 | 12.3367 ms / 19.89 ms | +| v1.0.8 | 32 | 1000 万 | 256 * 3 | 36800 | 20.8667 ms / 35.3767 ms | +| v1.0.8 | 32 | 1000 万 | 512 * 3 | 44123 | 34.8067 ms / 63.32 ms | +| v1.0.8 | 32 | 1000 万 | 1024 * 3 | 48496 | 63.3333 ms / 118.92 ms | + +GA2.0 比 GA1.0 在 Insert 性能上略有提升。 diff --git a/benchmark/benchmark-sysbench-v3.md b/benchmark/benchmark-sysbench-v3.md new file mode 100644 index 000000000000..22ed111aff36 --- /dev/null +++ b/benchmark/benchmark-sysbench-v3.md @@ -0,0 +1,143 @@ +--- +title: TiDB Sysbench 性能对比测试报告 - v2.1 对比 v2.0 +category: benchmark +aliases: ['/docs-cn/stable/benchmark/sysbench-v3/'] +--- + +# TiDB Sysbench 性能对比测试报告 - v2.1 对比 v2.0 + +## 测试目的 + +对比 TiDB 2.1 版本和 2.0 版本在 OLTP 场景下的性能。 + +## 测试版本、时间、地点 + +TiDB 版本:v2.1.0-rc.2 vs. v2.0.6 + +时间:2018 年 9 月 + +地点:北京 + +## 测试环境 + +IDC 机器: + +| 类别 | 名称 | +| :-: | :-: | +| OS | Linux (CentOS 7.3.1611) | +| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | +| RAM | 128GB | +| DISK | Optane 500GB SSD \* 1 | + +Sysbench 版本:1.1.0 + +## 测试方案 + +使用 Sysbench 向集群导入 **16 张表,每张数据 1000 万**。通过 HAProxy 代理,分别以递增并发数向集群发送请求,单次并发测试时间 5 分钟。 + +### TiDB 版本信息 + +### v2.1.0-rc.2 + +| 组件 | GitHash | +| :-: | :-: | +| TiDB | 08e56cd3bae166b2af3c2f52354fbc9818717f62 | +| TiKV | 57e684016dafb17dc8a6837d30224be66cbc7246 | +| PD | 6a7832d2d6e5b2923c79683183e63d030f954563 | + +### v2.0.6 + +| 组件 | GitHash | +| :-: | :-: | +| TiDB | b13bc08462a584a085f377625a7bab0cc0351570 | +| TiKV | 57c83dc4ebc93d38d77dc8f7d66db224760766cc | +| PD | b64716707b7279a4ae822be767085ff17b5f3fea | + +### TiDB 参数配置 + +两版本 TiDB 均使用**默认配置**。 + +### TiKV 参数配置 + +两版本 TiKV 均使用如下配置: + +```txt +[readpool.storage] +normal-concurrency = 8 +[server] +grpc-concurrency = 8 +[raftstore] +sync-log = false +[rocksdb.defaultcf] +block-cache-size = "60GB" +[rocksdb.writecf] +block-cache-size = "20GB" +``` + +### 集群拓扑 + +| 机器 IP | 部署实例 | +| :-: | :-: | +| 172.16.30.31 | 1\*Sysbench 1\*HAProxy | +| 172.16.30.32 | 1\*TiDB 1\*pd 1\*TiKV | +| 172.16.30.33 | 1\*TiDB 1\*TiKV | +| 172.16.30.34 | 1\*TiDB 1\*TiKV | + +## 测试结果 + +### Point Select 测试 + +| 版本 | threads | qps | 95% latency(ms) | +| :-: | :-: | :-: | :-: | +| v2.1 | 64 | 111481.09 | 1.16 | +| v2.1 | 128 | 145102.62 | 2.52 | +| v2.1 | 256 | 161311.9 | 4.57 | +| v2.1 | 512 | 184991.19 | 7.56 | +| v2.1 | 1024 | 230282.74 | 10.84 | +| v2.0 | 64 | 75285.87 | 1.93 | +| v2.0 | 128 | 92141.79 | 3.68 | +| v2.0 | 256 | 107464.93 | 6.67 | +| v2.0 | 512 | 121350.61 | 11.65 | +| v2.0 | 1024 | 150036.31 | 17.32 | + +![point select](/media/sysbench_v3_point_select.png) + +v2.1 比 v2.0 在 Point Select 查询性能上,**提升了 50%**。 + +### Update Non-Index 测试 + +| 版本 | threads | qps | 95% latency(ms) | +| :-: | :-: | :-: | :-: | +| v2.1 | 64 | 18946.09 | 5.77 | +| v2.1 | 128 | 22022.82 | 12.08 | +| v2.1 | 256 | 24679.68 | 25.74 | +| v2.1 | 512 | 25107.1 | 51.94 | +| v2.1 | 1024 | 27144.92 | 106.75 | +| v2.0 | 64 | 16316.85 | 6.91 | +| v2.0 | 128 | 20944.6 | 11.45 | +| v2.0 | 256 | 24017.42 | 23.1 | +| v2.0 | 512 | 25994.33 | 46.63 | +| v2.0 | 1024 | 27917.52 | 92.42 | + +![update non-index](/media/sysbench_v3_update_non_index.png) + +v2.1 与 v2.0 在 Update Non-Index 写入性能上基本一致。 + +### Update Index 测试 + +| 版本 | threads | qps | 95% latency(ms) | +| :-: | :-: | :-: | :-: | +| v2.1 | 64 | 9934.49 | 12.08 | +| v2.1 | 128 | 10505.95 | 25.28 | +| v2.1 | 256 | 11007.7 | 55.82 | +| v2.1 | 512 | 11198.81 | 106.75 | +| v2.1 | 1024 | 11591.89 | 200.47 | +| v2.0 | 64 | 9754.68 | 11.65 | +| v2.0 | 128 | 10603.31 | 24.38 | +| v2.0 | 256 | 11011.71 | 50.11 | +| v2.0 | 512 | 11162.63 | 104.84 | +| v2.0 | 1024 | 12067.63 | 179.94 | + +![update index](/media/sysbench_v3_update_index.png) + +v2.1 与 v2.0 在 Update Index 写入性能上基本一致。 diff --git a/benchmark/benchmark-sysbench-v4-vs-v3.md b/benchmark/benchmark-sysbench-v4-vs-v3.md new file mode 100644 index 000000000000..5a7748819dd9 --- /dev/null +++ b/benchmark/benchmark-sysbench-v4-vs-v3.md @@ -0,0 +1,173 @@ +--- +title: TiDB Sysbench 性能对比测试报告 - v4.0 对比 v3.0 +category: benchmark +--- + +# TiDB Sysbench 性能对比测试报告 - v4.0 对比 v3.0 + +## 测试目的 + +测试对比 TiDB v4.0 和 v3.0 在 OLTP 场景下的性能。 + +## 测试环境 (AWS EC2) + +### 硬件配置 + +| 服务类型 | EC2 类型 | 实例数 | +|:----------|:----------|:----------| +| PD | m5.xlarge | 3 | +| TiKV | i3.4xlarge| 3 | +| TiDB | c5.4xlarge| 3 | +| Sysbench | m5.4xlarge| 1 | + +### 软件版本 + +| 服务类型 | 软件版本 | +|:----------|:-----------| +| PD | 3.0、4.0 | +| TiDB | 3.0、4.0 | +| TiKV | 3.0、4.0 | +| Sysbench | 1.0.20 | + +### 参数配置 + +#### TiDB v3.0 参数配置 + +{{< copyable "" >}} + +```yaml +log.level: “error” +performance.max-procs: 20 +prepared-plan-cache.enabled: true +tikv-client.max-batch-wait-time: 2000000 +``` + +#### TiKV v3.0 参数配置 + +{{< copyable "" >}} + +```yaml +storage.scheduler-worker-pool-size: 5 +raftstore.store-pool-size: 3 +raftstore.apply-pool-size: 3 +rocksdb.max-background-jobs: 3 +raftdb.max-background-jobs: 3 +raftdb.allow-concurrent-memtable-write: true +server.grpc-concurrency: 6 +readpool.storage.normal-concurrency: 10 +readpool.coprocessor.normal-concurrency: 5 +``` + +#### TiDB v4.0 参数配置 + +{{< copyable "" >}} + +```yaml +log.level: “error” +performance.max-procs: 20 +prepared-plan-cache.enabled: true +tikv-client.max-batch-wait-time: 2000000 +``` + +#### TiKV v4.0 参数配置 + +{{< copyable "" >}} + +```yaml +storage.scheduler-worker-pool-size: 5 +raftstore.store-pool-size: 3 +raftstore.apply-pool-size: 3 +rocksdb.max-background-jobs: 3 +raftdb.max-background-jobs: 3 +raftdb.allow-concurrent-memtable-write: true +server.request-batch-enable-cross-command: false +server.grpc-concurrency: 6 +readpool.unifiy-read-pool: true +readpool.unified.min-thread-count: 5 +readpool.unified.max-thread-count: 20 +readpool.storage.normal-concurrency: 10 +pessimistic-txn.pipelined: true +``` + +#### 全局变量配置 + +{{< copyable "sql" >}} + +```sql +set global tidb_hashagg_final_concurrency=1; +set global tidb_hashagg_partial_concurrency=1; +set global tidb_disable_txn_auto_retry=0; +``` + +## 测试方案 + +1. 通过 TiUP 部署 TiDB v4.0 和 v3.0。 +2. 通过 Sysbench 导入 16 张表,每张表有 1000 万行数据。 +3. 分别对每个表执行 `analyze table` 命令。 +4. 备份数据,用于不同并发测试前进行数据恢复,以保证每次数据一致。 +5. 启动 Sysbench 客户端,进行 `point_select`、`read_write`、`update_index` 和 `update_non_index` 测试。通过 AWS NLB 向 TiDB 加压,单轮预热 1 分钟,测试 5 分钟。 +6. 每轮完成后停止集群,使用之前的备份的数据覆盖,再启动集群。 + +### 准备测试数据 + +执行以下命令来准备测试数据: + +{{< copyable "shell-regular" >}} + +```bash +sysbench oltp_common \ + --threads=16 \ + --rand-type=uniform \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=$aws_nlb_host \ + --mysql-port=$aws_nlb_port \ + --mysql-user=root \ + --mysql-password=password \ + prepare --tables=16 --table-size=10000000 +``` + +### 执行测试命令 + +执行以下命令来执行测试: + +{{< copyable "shell-regular" >}} + +```bash +sysbench $testname \ + --threads=$threads \ + --time=300 \ + --report-interval=1 \ + --rand-type=uniform \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=$aws_nlb_host \ + --mysql-port=$aws_nlb_port \ + run --tables=16 --table-size=10000000 +``` + +## 测试结果 + +### Point Select 性能 + +v4.0 对比 v3.0,Point Select 性能提升了 14%。 + +![Point Select](/media/sysbench_v4vsv3_point_select.png) + +### Update Non-index 性能 + +v4.0 对比 v3.0,Update Non-index 性能提升了 15%。 + +![Update Non-index](/media/sysbench_v4vsv3_update_non_index.png) + +### Update Index 性能 + +v4.0 对比 v3.0,Update Index 性能提升了 17%。 + +![Update Index](/media/sysbench_v4vsv3_update_index.png) + +### Read Write 性能 + +v4.0 对比 v3.0,Read Write 性能提升了 31%。 + +![Read Write](/media/sysbench_v4vsv3_read_write.png) diff --git a/benchmark/benchmark-tidb-using-sysbench.md b/benchmark/benchmark-tidb-using-sysbench.md new file mode 100644 index 000000000000..3bd91b5c436a --- /dev/null +++ b/benchmark/benchmark-tidb-using-sysbench.md @@ -0,0 +1,278 @@ +--- +title: 如何用 Sysbench 测试 TiDB +category: benchmark +aliases: ['/docs-cn/stable/benchmark/how-to-run-sysbench/'] +--- + +# 如何用 Sysbench 测试 TiDB + +本次测试使用的是 TiDB 3.0 Beta 和 Sysbench 1.0.14。建议使用 Sysbench 1.0 或之后的更新版本,可在 [Sysbench Release 1.0.14 页面](https://github.com/akopytov/sysbench/releases/tag/1.0.14)下载。 + +## 测试环境 + +- [硬件要求](/hardware-and-software-requirements.md) + +- 参考 [TiDB 部署文档](https://pingcap.com/docs-cn/v3.0/how-to/deploy/orchestrated/ansible/)部署 TiDB 集群。在 3 台服务器的条件下,建议每台机器部署 1 个 TiDB,1 个 PD,和 1 个 TiKV 实例。关于磁盘,以 32 张表、每张表 10M 行数据为例,建议 TiKV 的数据目录所在的磁盘空间大于 512 GB。 + 对于单个 TiDB 的并发连接数,建议控制在 500 以内,如需增加整个系统的并发压力,可以增加 TiDB 实例,具体增加的 TiDB 个数视测试压力而定。 + +IDC 机器: + +| 类别 | 名称 | +|:---- |:---- | +| OS | Linux (CentOS 7.3.1611) | +| CPU | 40 vCPUs, Intel® Xeon® CPU E5-2630 v4 @ 2.20GHz | +| RAM | 128GB | +| DISK | Intel Optane SSD P4800X 375G * 1 | +| NIC | 10Gb Ethernet | + +## 测试方案 + +### TiDB 版本信息 + +| 组件 | GitHash | +|:---- |:---- | +| TiDB | 7a240818d19ae96e4165af9ea35df92466f59ce6 | +| TiKV | e26ceadcdfe94fb6ff83b5abb614ea3115394bcd | +| PD | 5e81548c3c1a1adab056d977e7767307a39ecb70 | + +### 集群拓扑 + +| 机器 IP | 部署实例 | +|:---- |:---- | +| 172.16.30.31 | 3*sysbench | +| 172.16.30.33 | 1\*tidb 1\*pd 1\*tikv | +| 172.16.30.34 | 1\*tidb 1\*pd 1\*tikv | +| 172.16.30.35 | 1\*tidb 1\*pd 1\*tikv | + +### TiDB 配置 + +升高日志级别,可以减少打印日志数量,对 TiDB 的性能有积极影响。开启 TiDB 配置中的 `prepared plan cache`,以减少优化执行计划的开销。具体在 TiDB 配置文件中加入: + +```toml +[log] +level = "error" +[prepared-plan-cache] +enabled = true +``` + +### TiKV 配置 + +升高 TiKV 的日志级别同样有利于提高性能表现。 + +由于 TiKV 是以集群形式部署的,在 Raft 算法的作用下,能保证大多数节点已经写入数据。因此,除了对数据安全极端敏感的场景之外,raftstore 中的 `sync-log` 选项可以关闭。 + +TiKV 集群存在两个 Column Family(Default CF 和 Write CF),主要用于存储不同类型的数据。对于 Sysbench 测试,导入数据的 Column Family 在 TiDB 集群中的比例是固定的。这个比例是: + +Default CF : Write CF = 4 : 1 + +在 TiKV 中需要根据机器内存大小配置 RocksDB 的 block cache,以充分利用内存。以 40 GB 内存的虚拟机部署一个 TiKV 为例,其 block cache 建议配置如下: + +```toml +log-level = "error" +[raftstore] +sync-log = false +[rocksdb.defaultcf] +block-cache-size = "24GB" +[rocksdb.writecf] +block-cache-size = "6GB" +``` + +对于 3.0 及以后的版本,还可以使用共享 block cache 的方式进行设置: + +```toml +log-level = "error" +[raftstore] +sync-log = false +[storage.block-cache] +capacity = "30GB" +``` + +更详细的 TiKV 参数调优请参考 [TiKV 内存参数性能调优](/tune-tikv-memory-performance.md)。 + +## 测试过程 + +> **注意:** +> +> 此次测试并没有使用如 HAproxy 等负载均衡工具。在 TiDB 单一节点上进行 Sysbench 测试,并把结果相加。负载均衡工具和不同版本参数也会影响性能表现。 + +### Sysbench 配置 + +以下为 Sysbench 配置文件样例: + +```txt +mysql-host={TIDB_HOST} +mysql-port=4000 +mysql-user=root +mysql-password=password +mysql-db=sbtest +time=600 +threads={8, 16, 32, 64, 128, 256} +report-interval=10 +db-driver=mysql +``` + +可根据实际需求调整其参数,其中 `TIDB_HOST` 为 TiDB server 的 IP 地址(配置文件中不能写多个地址),`threads` 为测试中的并发连接数,可在 “8, 16, 32, 64, 128, 256” 中调整,导入数据时,建议设置 threads = 8 或者 16。调整后,将该文件保存为名为 **config** 的文件。 + +**配置文件**参考示例如下: + +```txt +mysql-host=172.16.30.33 +mysql-port=4000 +mysql-user=root +mysql-password=password +mysql-db=sbtest +time=600 +threads=16 +report-interval=10 +db-driver=mysql +``` + +### 数据导入 + +在数据导入前,需要对 TiDB 进行简单设置。在 MySQL 客户端中执行如下命令: + +{{< copyable "sql" >}} + +```sql +set global tidb_disable_txn_auto_retry = off; +``` + +然后退出客户端。TiDB 使用乐观事务模型,当发现并发冲突时,会回滚事务。将 `tidb_disable_txn_auto_retry` 设置为 `off` 会开启事务冲突后的自动重试机制,可以尽可能避免事务冲突报错导致 Sysbench 程序退出的问题。 + +重新启动 MySQL 客户端执行以下 SQL 语句,创建数据库 `sbtest`: + +{{< copyable "sql" >}} + +```sql +create database sbtest; +``` + +调整 Sysbench 脚本创建索引的顺序。Sysbench 按照“建表->插入数据->创建索引”的顺序导入数据。该方式对于 TiDB 需要花费更多的导入时间。用户可以通过调整顺序来加速数据的导入。 + +假设用户使用的 [Sysbench](https://github.com/akopytov/sysbench/tree/1.0.14) 版本。我们可以通过以下两种方式来修改。 + +1. 直接下载为 TiDB 修改好的 [oltp_common.lua](https://raw.githubusercontent.com/pingcap/tidb-bench/master/sysbench/sysbench-patch/oltp_common.lua) 文件,覆盖 `/usr/share/sysbench/oltp_common.lua` 文件。 +2. 将 `/usr/share/sysbench/oltp_common.lua` 的第 [235](https://github.com/akopytov/sysbench/blob/1.0.14/src/lua/oltp_common.lua#L235) 行到第 [240](https://github.com/akopytov/sysbench/blob/1.0.14/src/lua/oltp_common.lua#L240) 行移动到第 198 行以后。 + +> **注意:** +> +> 此操作为可选操作,仅节约了数据导入时间。 + +命令行输入以下命令,开始导入数据,config 文件为上一步中配置的文件: + +{{< copyable "shell-regular" >}} + +```bash +sysbench --config-file=config oltp_point_select --tables=32 --table-size=10000000 prepare +``` + +### 数据预热与统计信息收集 + +数据预热可将磁盘中的数据载入内存的 block cache 中,预热后的数据对系统整体的性能有较大的改善,建议在每次重启集群后进行一次数据预热。 + +Sysbench 1.0.14 没有提供数据预热的功能,因此需要手动进行数据预热。如果使用更新的 Sysbench 版本,可以使用自带的预热功能。 + +以 Sysbench 中某张表 sbtest7 为例,执行如下 SQL 语句 进行数据预热: + +{{< copyable "sql" >}} + +```sql +SELECT COUNT(pad) FROM sbtest7 USE INDEX (k_7); +``` + +统计信息收集有助于优化器选择更为准确的执行计划,可以通过 `analyze` 命令来收集表 sbtest 的统计信息,每个表都需要统计。 + +{{< copyable "sql" >}} + +```sql +ANALYZE TABLE sbtest7; +``` + +### Point select 测试命令 + +{{< copyable "shell-regular" >}} + +```bash +sysbench --config-file=config oltp_point_select --tables=32 --table-size=10000000 run +``` + +### Update index 测试命令 + +{{< copyable "shell-regular" >}} + +```bash +sysbench --config-file=config oltp_update_index --tables=32 --table-size=10000000 run +``` + +### Read-only 测试命令 + +{{< copyable "shell-regular" >}} + +```bash +sysbench --config-file=config oltp_read_only --tables=32 --table-size=10000000 run +``` + +## 测试结果 + +测试了数据 32 表,每表有 10M 数据。 + +对每个 tidb-server 进行了 Sysbench 测试,将结果相加,得出最终结果: + +### oltp_point_select + +| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | +|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | +| point_select | 3\*8 | 67502.55 | 67502.55 | 0.36 | 0.42 | 141.92 | +| point_select | 3\*16 | 120141.84 | 120141.84 | 0.40 | 0.52 | 20.99 | +| point_select | 3\*32 | 170142.92 | 170142.92 | 0.58 | 0.99 | 28.08 | +| point_select | 3\*64 | 195218.54 | 195218.54 | 0.98 | 2.14 | 21.82 | +| point_select | 3\*128 | 208189.53 | 208189.53 | 1.84 | 4.33 | 31.02 | + +![oltp_point_select](/media/oltp_point_select.png) + +### oltp_update_index + +| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | +|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | +| oltp_update_index | 3\*8 | 9668.98 | 9668.98 | 2.51 | 3.19 | 103.88| +| oltp_update_index | 3\*16 | 12834.99 | 12834.99 | 3.79 | 5.47 | 176.90 | +| oltp_update_index | 3\*32 | 15955.77 | 15955.77 | 6.07 | 9.39 | 4787.14 | +| oltp_update_index | 3\*64 | 18697.17 | 18697.17 | 10.34 | 17.63 | 4539.04 | +| oltp_update_index | 3\*128 | 20446.81 | 20446.81 | 18.98 | 40.37 | 5394.75 | +| oltp_update_index | 3\*256 | 23563.03 | 23563.03 | 32.86 | 78.60 | 5530.69 | + +![oltp_update_index](/media/oltp_update_index.png) + +### oltp_read_only + +| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | +|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | +| oltp_read_only | 3\*8 | 2411.00 | 38575.96 | 9.92 | 20.00 | 92.23 | +| oltp_read_only | 3\*16 | 3873.53 | 61976.50 | 12.25 | 16.12 | 56.94 | +| oltp_read_only | 3\*32 | 5066.88 | 81070.16 | 19.42 | 26.20 | 123.41 | +| oltp_read_only | 3\*64 | 5466.36 | 87461.81 | 34.65 | 63.20 | 231.19 | +| oltp_read_only | 3\*128 | 6684.16 | 106946.59 | 57.29 | 97.55 | 180.85 | + +![oltp_read_only](/media/oltp_read_only.png) + +## 常见问题 + +### 在高并发压力下,TiDB、TiKV 的配置都合理,为什么整体性能还是偏低? + +这种情况可能与使用了 proxy 有关。可以尝试直接对单个 TiDB 加压,将求和后的结果与使用 proxy 的情况进行对比。 + +以 HAproxy 为例。`nbproc` 参数可以增加其最大启动的进程数,较新版本的 HAproxy 还支持 `nbthread` 和 `cpu-map` 等。这些都可以减少对其性能的不利影响。 + +### 在高并发压力下,为什么 TiKV 的 CPU 利用率依然很低? + +TiKV 虽然整体 CPU 偏低,但部分模块的 CPU 可能已经达到了很高的利用率。 + +TiKV 的其他模块,如 storage readpool、coprocessor 和 gRPC 的最大并发度限制是可以通过 TiKV 的配置文件进行调整的。 + +通过 Grafana 的 TiKV Thread CPU 监控面板可以观察到其实际使用率。如出现多线程模块瓶颈,可以通过增加该模块并发度进行调整。 + +### 在高并发压力下,TiKV 也未达到 CPU 使用瓶颈,为什么 TiDB 的 CPU 利用率依然很低? + +在某些高端设备上,使用的是 NUMA 架构的 CPU,跨 CPU 访问远端内存将极大降低性能。TiDB 默认将使用服务器所有 CPU,goroutine 的调度不可避免地会出现跨 CPU 内存访问。 + +因此,建议在 NUMA 架构服务器上,部署 *n* 个 TiDB(*n* = NUMA CPU 的个数),同时将 TiDB 的 `max-procs` 变量的值设置为与 NUMA CPU 的核数相同。 diff --git a/benchmark/benchmark-tidb-using-tpcc.md b/benchmark/benchmark-tidb-using-tpcc.md new file mode 100644 index 000000000000..e6fe3546b5bd --- /dev/null +++ b/benchmark/benchmark-tidb-using-tpcc.md @@ -0,0 +1,285 @@ +--- +title: 如何对 TiDB 进行 TPC-C 测试 +category: benchmark +aliases: ['/docs-cn/stable/benchmark/how-to-run-tpcc/'] +--- + +# 如何对 TiDB 进行 TPC-C 测试 + +本文介绍如何对 TiDB 进行 [TPC-C](http://www.tpc.org/tpcc/) 测试。 + +## 准备测试程序 + +TPC-C 是一个对 OLTP(联机交易处理)系统进行测试的规范,使用一个商品销售模型对 OLTP 系统进行测试,其中包含五类事务: + +* NewOrder – 新订单的生成 +* Payment – 订单付款 +* OrderStatus – 最近订单查询 +* Delivery – 配送 +* StockLevel – 库存缺货状态分析 + +在测试开始前,TPC-C Benchmark 规定了数据库的初始状态,也就是数据库中数据生成的规则,其中 ITEM 表中固定包含 10 万种商品,仓库的数量可进行调整,假设 WAREHOUSE 表中有 W 条记录,那么: + +* STOCK 表中应有 W \* 10 万条记录(每个仓库对应 10 万种商品的库存数据) +* DISTRICT 表中应有 W \* 10 条记录(每个仓库为 10 个地区提供服务) +* CUSTOMER 表中应有 W \* 10 \* 3000 条记录(每个地区有 3000 个客户) +* HISTORY 表中应有 W \* 10 \* 3000 条记录(每个客户一条交易历史) +* ORDER 表中应有 W \* 10 \* 3000 条记录(每个地区 3000 个订单),并且最后生成的 900 个订单被添加到 NEW-ORDER 表中,每个订单随机生成 5 ~ 15 条 ORDER-LINE 记录。 + +我们将以 1000 WAREHOUSE 为例进行测试。 + +TPC-C 使用 tpmC 值(Transactions per Minute)来衡量系统最大有效吞吐量 (MQTh, Max Qualified Throughput),其中 Transactions 以 NewOrder Transaction 为准,即最终衡量单位为每分钟处理的新订单数。 + +本文使用开源的 BenchmarkSQL 5.0 作为 TPC-C 测试实现并添加了对 MySQL 协议的支持,可以通过以下命令下载测试程序: + +{{< copyable "shell-regular" >}} + +```shell +git clone -b 5.0-mysql-support-opt-2.1 https://github.com/pingcap/benchmarksql.git +``` + +安装 java 和 ant,以 CentOS 为例,可以执行以下命令进行安装 + +{{< copyable "shell-regular" >}} + +```shell +sudo yum install -y java ant +``` + +进入 benchmarksql 目录并执行 ant 构建 + +{{< copyable "shell-regular" >}} + +```shell +cd benchmarksql +ant +``` + +## 部署 TiDB 集群 + +对于 1000 WAREHOUSE,在 3 台服务器上部署集群。 + +在 3 台服务器的条件下,建议每台机器部署 1 个 TiDB,1 个 PD 和 1 个 TiKV 实例。 + +比如这里采用的机器硬件配置是: + +| 类别 | 名称 | +| :-: | :-: | +| OS | Linux (CentOS 7.3.1611) | +| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | +| RAM | 128GB | +| DISK | Optane 500GB SSD | + +因为该型号 CPU 是 NUMA 架构,建议用 `numactl` 进行绑核。 + +1. [安装 numactl 工具](/check-before-deployment.md#安装-numactl-工具) 。 + +2. 用 `lscpu` 查看 NUMA node,比如: + + ```text + NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38 + NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39 + ``` + +3. 通过修改 `{tidb_deploy_path}/scripts/run_tidb.sh` 启动脚本,加入 `numactl` 来启动 TiDB: + + ```text + #!/bin/bash + set -e + + ulimit -n 1000000 + + # WARNING: This file was auto-generated. Do not edit! + # All your edit might be overwritten! + DEPLOY_DIR=/home/damon/deploy/tidb1-1 + + cd "${DEPLOY_DIR}" || exit 1 + + export TZ=Asia/Shanghai + + # 同一台机器不同的 TiDB 实例需要指定不同的 cpunodebind 以及 membind;来绑定不同的 Numa node + exec numactl --cpunodebind=0 --membind=0 bin/tidb-server \ + -P 4111 \ + --status="10191" \ + --advertise-address="172.16.4.53" \ + --path="172.16.4.10:2490" \ + --config=conf/tidb.toml \ + --log-slow-query="/home/damon/deploy/tidb1-1/log/tidb_slow_query.log" \ + --log-file="/home/damon/deploy/tidb1-1/log/tidb.log" 2>> "/home/damon/deploy/tidb1-1/log/tidb_stderr.log" + ``` + + > **注意:** + > + > 直接修改 `run_tidb.sh` 可能会被覆盖,因此在生产环境中,如有绑核需求,建议使用 TiUP 绑核。 + +4. 选择部署一个 HAproxy 来进行多个 TiDB node 的负载均衡,推荐配置 nbproc 为 CPU 核数。 + +## 配置调整 + +### TiDB 配置 + +```toml +[log] +level = "error" + +[performance] +# 根据 NUMA 配置,设置单个 TiDB 最大使用的 CPU 核数 +max-procs = 20 + +[prepared_plan_cache] +# 开启 TiDB 配置中的 prepared plan cache,以减少优化执行计划的开销 +enabled = true +``` + +### TiKV 配置 + +开始可以使用基本的配置,压测运行后可以通过观察 Grafana 并参考 [TiKV 线程池调优说明](/tune-tikv-thread-performance.md)进行调整。 + +### BenchmarkSQL 配置 + +修改 `benchmarksql/run/props.mysql`: + +```text +conn=jdbc:mysql://{HAPROXY-HOST}:{HAPROXY-PORT}/tpcc?useSSL=false&useServerPrepStmts=true&useConfigs=maxPerformance +warehouses=1000 # 使用 1000 个 warehouse +terminals=500 # 使用 500 个终端 +loadWorkers=32 # 导入数据的并发数 +``` + +## 导入数据 + +**导入数据通常是整个 TPC-C 测试中最耗时,也是最容易出问题的阶段。** + +首先用 MySQL 客户端连接到 TiDB-Server 并执行: + +{{< copyable "sql" >}} + +```sql +create database tpcc +``` + +之后在 shell 中运行 BenchmarkSQL 建表脚本: + +{{< copyable "shell-regular" >}} + +```shell +cd run && \ +./runSQL.sh props.mysql sql.mysql/tableCreates.sql && \ +./runSQL.sh props.mysql sql.mysql/indexCreates.sql +``` + +### 直接使用 BenchmarkSQL 导入 + +运行导入数据脚本: + +{{< copyable "shell-regular" >}} + +```shell +./runLoader.sh props.mysql +``` + +根据机器配置这个过程可能会持续几个小时。 + +### 通过 TiDB Lightning 导入 + +由于导入数据量随着 warehouse 的增加而增加,当需要导入 1000 warehouse 以上数据时,可以先用 BenchmarkSQL 生成 csv 文件,再将文件通过 TiDB Lightning(以下简称 Lightning)导入的方式来快速导入。生成的 csv 文件也可以多次复用,节省每次生成所需要的时间。 + +#### 修改 BenchmarkSQL 的配置文件 + +1 warehouse 的 csv 文件需要 77 MB 磁盘空间,在生成之前要根据需要分配足够的磁盘空间来保存 csv 文件。可以在 `benchmarksql/run/props.mysql` 文件中增加一行: + +```text +fileLocation=/home/user/csv/ # 存储 csv 文件的目录绝对路径,需保证有足够的空间 +``` + +因为最终要使用 Lightning 导入数据,所以 csv 文件名最好符合 Lightning 要求,即 `{database}.{table}.csv` 的命名法。这里可以将以上配置改为: + +```text +fileLocation=/home/user/csv/tpcc. # 存储 csv 文件的目录绝对路径 + 文件名前缀(database) +``` + +这样生成的 csv 文件名将会是类似 `tpcc.bmsql_warehouse.csv` 的样式,符合 Lightning 的要求。 + +#### 生成 csv 文件 + +{{< copyable "shell-regular" >}} + +```shell +./runLoader.sh props.mysql +``` + +#### 通过 Lightning 导入 + +通过 Lightning 导入数据请参考 [Lightning 部署执行](/tidb-lightning/deploy-tidb-lightning.md)章节。这里我们介绍下通过 TiDB Ansible 部署 Lightning 导入数据的方法。 + +##### 修改 inventory.ini + +这里最好手动指定清楚部署的 IP、端口、目录,避免各种冲突问题带来的异常,其中 import_dir 的磁盘空间参考 [Lightning 部署执行](/tidb-lightning/deploy-tidb-lightning.md),data_source_dir 就是存储上一节 csv 数据的目录。 + +```ini +[importer_server] +IS1 ansible_host=172.16.5.34 deploy_dir=/data2/is1 tikv_importer_port=13323 import_dir=/data2/import + +[lightning_server] +LS1 ansible_host=172.16.5.34 deploy_dir=/data2/ls1 tidb_lightning_pprof_port=23323 data_source_dir=/home/user/csv +``` + +##### 修改 conf/tidb-lightning.yml + +```yaml +mydumper: + no-schema: true + csv: + separator: ',' + delimiter: '' + header: false + not-null: false + 'null': 'NULL' + backslash-escape: true + trim-last-separator: false +``` + +##### 部署 Lightning 和 Importer + +{{< copyable "shell-regular" >}} + +```shell +ansible-playbook deploy.yml --tags=lightning +``` + +##### 启动 + +* 登录到部署 Lightning 和 Importer 的服务器 +* 进入部署目录 +* 在 Importer 目录下执行 `scripts/start_importer.sh`,启动 Importer +* 在 Lightning 目录下执行 `scripts/start_lightning.sh`,开始导入数据 + +由于是用 TiDB Ansible 进行部署的,可以在监控页面看到 Lightning 的导入进度,或者通过日志查看导入是否结束。 + +### 导入完成后 + +数据导入完成之后,可以运行 `sql.common/test.sql` 进行数据正确性验证,如果所有 SQL 语句都返回结果为空,即为数据导入正确。 + +## 运行测试 + +执行 BenchmarkSQL 测试脚本: + +{{< copyable "shell-regular" >}} + +```shell +nohup ./runBenchmark.sh props.mysql &> test.log & +``` + +运行结束后通过 `test.log` 查看结果: + +```text +07:09:53,455 [Thread-351] INFO jTPCC : Term-00, Measured tpmC (NewOrders) = 77373.25 +07:09:53,455 [Thread-351] INFO jTPCC : Term-00, Measured tpmTOTAL = 171959.88 +07:09:53,455 [Thread-351] INFO jTPCC : Term-00, Session Start = 2019-03-21 07:07:52 +07:09:53,456 [Thread-351] INFO jTPCC : Term-00, Session End = 2019-03-21 07:09:53 +07:09:53,456 [Thread-351] INFO jTPCC : Term-00, Transaction Count = 345240 +``` + +tpmC 部分即为测试结果。 + +测试完成之后,也可以运行 `sql.common/test.sql` 进行数据正确性验证,如果所有 SQL 语句的返回结果都为空,即为数据测试过程正确。 diff --git a/benchmark/benchmark-tpch.md b/benchmark/benchmark-tpch.md new file mode 100644 index 000000000000..76d505b0353c --- /dev/null +++ b/benchmark/benchmark-tpch.md @@ -0,0 +1,109 @@ +--- +title: TiDB TPC-H 50G 性能测试报告 +category: benchmark +aliases: ['/docs-cn/stable/benchmark/tpch/'] +--- + +# TiDB TPC-H 50G 性能测试报告 + +## 测试目的 + +测试 TiDB 在 OLAP 场景下 1.0 和 2.0 版本的性能对比。 + +> **注意:** +> +> 不同的测试环境可能使测试结果发生改变。 + +## 测试环境 + +### 测试机器信息 + +1. 系统信息 + + | 机器 IP | 操作系统 | 内核版本 | 文件系统类型 | + |--------------|------------------------|------------------------------|--------------| + | 172.16.31.2 | Ubuntu 17.10 64bit | 4.13.0-16-generic | ext4 | + | 172.16.31.3 | Ubuntu 17.10 64bit | 4.13.0-16-generic | ext4 | + | 172.16.31.4 | Ubuntu 17.10 64bit | 4.13.0-16-generic | ext4 | + | 172.16.31.6 | CentOS 7.4.1708 64bit | 3.10.0-693.11.6.el7.x86\_64 | ext4 | + | 172.16.31.8 | CentOS 7.4.1708 64bit | 3.10.0-693.11.6.el7.x86\_64 | ext4 | + | 172.16.31.10 | CentOS 7.4.1708 64bit | 3.10.0-693.11.6.el7.x86\_64 | ext4 | + +2. 硬件信息 + + | 类别 | 名称 | + |------------|------------------------------------------------------| + | CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | + | 内存 | 128GB, 8条16GB RDIMM, 2400MT/s, 双列, x8 带宽 | + | 磁盘 | 2 块 Intel P4500 系列 4T SSD 硬盘 | + | 网卡 | 万兆网卡 | + +### TPC-H + +[tidb-bench/tpch](https://github.com/pingcap/tidb-bench/tree/master/tpch) + +### 集群拓扑 + +| 机器 IP | 部署的实例 | +|--------------|------------| +| 172.16.31.2 | TiKV \* 2 | +| 172.16.31.3 | TiKV \* 2 | +| 172.16.31.6 | TiKV \* 2 | +| 172.16.31.8 | TiKV \* 2 | +| 172.16.31.10 | TiKV \* 2 | +| 172.16.31.10 | PD \* 1 | +| 172.16.31.4 | TiDB \* 1 | + +### TiDB 版本信息 + +TiDB 1.0: + +| 组件名 | 版本号 | commit hash | +|--------|-------------|--------------------------------------------| +| TiDB | v1.0.9 | 4c7ee3580cd0a69319b2c0c08abdc59900df7344 | +| TiKV | v1.0.8 | 2bb923a4cd23dbf68f0d16169fd526dc5c1a9f4a | +| PD | v1.0.8 | 137fa734472a76c509fbfd9cb9bc6d0dc804a3b7 | + +TiDB 2.0: + +| 组件名 | 版本号 | commit hash | +|--------|-------------|--------------------------------------------| +| TiDB | v2.0.0-rc.6 | 82d35f1b7f9047c478f4e1e82aa0002abc8107e7 | +| TiKV | v2.0.0-rc.6 | 8bd5c54966c6ef42578a27519bce4915c5b0c81f | +| PD | v2.0.0-rc.6 | 9b824d288126173a61ce7d51a71fc4cb12360201 | + +## 测试结果 + +| Query ID | TiDB 2.0 | TiDB 1.0 | +|-----------|--------------------|------------------| +| 1 | 33.915s | 215.305s | +| 2 | 25.575s | NaN | +| 3 | 59.631s | 196.003s | +| 4 | 30.234s | 249.919s | +| 5 | 31.666s | OOM | +| 6 | 13.111s | 118.709s | +| 7 | 31.710s | OOM | +| 8 | 31.734s | 800.546s | +| 9 | 34.211s | 630.639s | +| 10 | 30.774s | 133.547s | +| 11 | 27.692s | 78.026s | +| 12 | 27.962s | 124.641s | +| 13 | 27.676s | 174.695s | +| 14 | 19.676s | 110.602s | +| 15 | View Required | View Required | +| 16 | 24.890s | 40.529s | +| 17 | 245.796s | NaN | +| 18 | 91.256s | OOM | +| 19 | 37.615s | NaN | +| 20 | 44.167s | 212.201s | +| 21 | 31.466s | OOM | +| 22 | 31.539s | 125.471s | + +![TPC-H Query Result](/media/tpch-query-result.png) + +说明: + +- 图中橙色为 Release 1.0,蓝色为 Release 2.0,纵坐标是 Query 的处理时间,越低越好 +- Query 15 因为 1.0 和 2.0 都还未支持视图,所以结果标记为 "View Required" +- Query 2, 17, 19 因为 TiDB 1.0 长时间未跑出结果,所以结果标记为 "Nan" +- Query 5, 7, 18, 21 因为 TiDB 1.0 在跑的过程中内存占用过多被 oom-killer 杀死,所以结果标记为 "OOM" diff --git a/benchmark/how-to-run-sysbench.md b/benchmark/how-to-run-sysbench.md deleted file mode 100644 index d6b7bab5934b..000000000000 --- a/benchmark/how-to-run-sysbench.md +++ /dev/null @@ -1,277 +0,0 @@ ---- -title: 如何用 Sysbench 测试 TiDB -category: benchmark ---- - -# 如何用 Sysbench 测试 TiDB - -本次测试使用的是 TiDB 3.0 Beta 和 Sysbench 1.0.14。建议使用 Sysbench 1.0 或之后的更新版本,可在 [Sysbench Release 1.0.14 页面](https://github.com/akopytov/sysbench/releases/tag/1.0.14)下载。 - -## 测试环境 - -- [硬件要求](/how-to/deploy/hardware-recommendations.md) - -- 参考 [TiDB 部署文档](/how-to/deploy/orchestrated/ansible.md)部署 TiDB 集群。在 3 台服务器的条件下,建议每台机器部署 1 个 TiDB,1 个 PD,和 1 个 TiKV 实例。关于磁盘,以 32 张表、每张表 10M 行数据为例,建议 TiKV 的数据目录所在的磁盘空间大于 512 GB。 - 对于单个 TiDB 的并发连接数,建议控制在 500 以内,如需增加整个系统的并发压力,可以增加 TiDB 实例,具体增加的 TiDB 个数视测试压力而定。 - -IDC 机器: - -| 类别 | 名称 | -|:---- |:---- | -| OS | Linux (CentOS 7.3.1611) | -| CPU | 40 vCPUs, Intel® Xeon® CPU E5-2630 v4 @ 2.20GHz | -| RAM | 128GB | -| DISK | Intel Optane SSD P4800X 375G * 1 | -| NIC | 10Gb Ethernet | - -## 测试方案 - -### TiDB 版本信息 - -| 组件 | GitHash | -|:---- |:---- | -| TiDB | 7a240818d19ae96e4165af9ea35df92466f59ce6 | -| TiKV | e26ceadcdfe94fb6ff83b5abb614ea3115394bcd | -| PD | 5e81548c3c1a1adab056d977e7767307a39ecb70 | - -### 集群拓扑 - -| 机器 IP | 部署实例 | -|:---- |:---- | -| 172.16.30.31 | 3*sysbench | -| 172.16.30.33 | 1\*tidb 1\*pd 1\*tikv | -| 172.16.30.34 | 1\*tidb 1\*pd 1\*tikv | -| 172.16.30.35 | 1\*tidb 1\*pd 1\*tikv | - -### TiDB 配置 - -升高日志级别,可以减少打印日志数量,对 TiDB 的性能有积极影响。开启 TiDB 配置中的 `prepared plan cache`,以减少优化执行计划的开销。具体在 TiDB 配置文件中加入: - -```toml -[log] -level = "error" -[prepared-plan-cache] -enabled = true -``` - -### TiKV 配置 - -升高 TiKV 的日志级别同样有利于提高性能表现。 - -由于 TiKV 是以集群形式部署的,在 Raft 算法的作用下,能保证大多数节点已经写入数据。因此,除了对数据安全极端敏感的场景之外,raftstore 中的 `sync-log` 选项可以关闭。 - -TiKV 集群存在两个 Column Family(Default CF 和 Write CF),主要用于存储不同类型的数据。对于 Sysbench 测试,导入数据的 Column Family 在 TiDB 集群中的比例是固定的。这个比例是: - -Default CF : Write CF = 4 : 1 - -在 TiKV 中需要根据机器内存大小配置 RocksDB 的 block cache,以充分利用内存。以 40 GB 内存的虚拟机部署一个 TiKV 为例,其 block cache 建议配置如下: - -```toml -log-level = "error" -[raftstore] -sync-log = false -[rocksdb.defaultcf] -block-cache-size = "24GB" -[rocksdb.writecf] -block-cache-size = "6GB" -``` - -对于 3.0 及以后的版本,还可以使用共享 block cache 的方式进行设置: - -```toml -log-level = "error" -[raftstore] -sync-log = false -[storage.block-cache] -capacity = "30GB" -``` - -更详细的 TiKV 参数调优请参考 [TiKV 性能参数调优](/reference/performance/tune-tikv.md)。 - -## 测试过程 - -> **注意:** -> -> 此次测试并没有使用如 HAproxy 等负载均衡工具。在 TiDB 单一节点上进行 Sysbench 测试,并把结果相加。负载均衡工具和不同版本参数也会影响性能表现。 - -### Sysbench 配置 - -以下为 Sysbench 配置文件样例: - -```txt -mysql-host={TIDB_HOST} -mysql-port=4000 -mysql-user=root -mysql-password=password -mysql-db=sbtest -time=600 -threads={8, 16, 32, 64, 128, 256} -report-interval=10 -db-driver=mysql -``` - -可根据实际需求调整其参数,其中 `TIDB_HOST` 为 TiDB server 的 IP 地址(配置文件中不能写多个地址),`threads` 为测试中的并发连接数,可在 “8, 16, 32, 64, 128, 256” 中调整,导入数据时,建议设置 threads = 8 或者 16。调整后,将该文件保存为名为 **config** 的文件。 - -**配置文件**参考示例如下: - -```txt -mysql-host=172.16.30.33 -mysql-port=4000 -mysql-user=root -mysql-password=password -mysql-db=sbtest -time=600 -threads=16 -report-interval=10 -db-driver=mysql -``` - -### 数据导入 - -在数据导入前,需要对 TiDB 进行简单设置。在 MySQL 客户端中执行如下命令: - -{{< copyable "sql" >}} - -```sql -set global tidb_disable_txn_auto_retry = off; -``` - -然后退出客户端。TiDB 使用乐观事务模型,当发现并发冲突时,会回滚事务。将 `tidb_disable_txn_auto_retry` 设置为 `off` 会开启事务冲突后的自动重试机制,可以尽可能避免事务冲突报错导致 Sysbench 程序退出的问题。 - -重新启动 MySQL 客户端执行以下 SQL 语句,创建数据库 `sbtest`: - -{{< copyable "sql" >}} - -```sql -create database sbtest; -``` - -调整 Sysbench 脚本创建索引的顺序。Sysbench 按照“建表->插入数据->创建索引”的顺序导入数据。该方式对于 TiDB 需要花费更多的导入时间。用户可以通过调整顺序来加速数据的导入。 - -假设用户使用的 [Sysbench](https://github.com/akopytov/sysbench/tree/1.0.14) 版本。我们可以通过以下两种方式来修改。 - -1. 直接下载为 TiDB 修改好的 [oltp_common.lua](https://raw.githubusercontent.com/pingcap/tidb-bench/master/sysbench/sysbench-patch/oltp_common.lua) 文件,覆盖 `/usr/share/sysbench/oltp_common.lua` 文件。 -2. 将 `/usr/share/sysbench/oltp_common.lua` 的第 [235](https://github.com/akopytov/sysbench/blob/1.0.14/src/lua/oltp_common.lua#L235) 行到第 [240](https://github.com/akopytov/sysbench/blob/1.0.14/src/lua/oltp_common.lua#L240) 行移动到第 198 行以后。 - -> **注意:** -> -> 此操作为可选操作,仅节约了数据导入时间。 - -命令行输入以下命令,开始导入数据,config 文件为上一步中配置的文件: - -{{< copyable "shell-regular" >}} - -```bash -sysbench --config-file=config oltp_point_select --tables=32 --table-size=10000000 prepare -``` - -### 数据预热与统计信息收集 - -数据预热可将磁盘中的数据载入内存的 block cache 中,预热后的数据对系统整体的性能有较大的改善,建议在每次重启集群后进行一次数据预热。 - -Sysbench 1.0.14 没有提供数据预热的功能,因此需要手动进行数据预热。如果使用更新的 Sysbench 版本,可以使用自带的预热功能。 - -以 Sysbench 中某张表 sbtest7 为例,执行如下 SQL 语句 进行数据预热: - -{{< copyable "sql" >}} - -```sql -SELECT COUNT(pad) FROM sbtest7 USE INDEX (k_7); -``` - -统计信息收集有助于优化器选择更为准确的执行计划,可以通过 `analyze` 命令来收集表 sbtest 的统计信息,每个表都需要统计。 - -{{< copyable "sql" >}} - -```sql -ANALYZE TABLE sbtest7; -``` - -### Point select 测试命令 - -{{< copyable "shell-regular" >}} - -```bash -sysbench --config-file=config oltp_point_select --tables=32 --table-size=10000000 run -``` - -### Update index 测试命令 - -{{< copyable "shell-regular" >}} - -```bash -sysbench --config-file=config oltp_update_index --tables=32 --table-size=10000000 run -``` - -### Read-only 测试命令 - -{{< copyable "shell-regular" >}} - -```bash -sysbench --config-file=config oltp_read_only --tables=32 --table-size=10000000 run -``` - -## 测试结果 - -测试了数据 32 表,每表有 10M 数据。 - -对每个 tidb-server 进行了 Sysbench 测试,将结果相加,得出最终结果: - -### oltp_point_select - -| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | -|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | -| point_select | 3\*8 | 67502.55 | 67502.55 | 0.36 | 0.42 | 141.92 | -| point_select | 3\*16 | 120141.84 | 120141.84 | 0.40 | 0.52 | 20.99 | -| point_select | 3\*32 | 170142.92 | 170142.92 | 0.58 | 0.99 | 28.08 | -| point_select | 3\*64 | 195218.54 | 195218.54 | 0.98 | 2.14 | 21.82 | -| point_select | 3\*128 | 208189.53 | 208189.53 | 1.84 | 4.33 | 31.02 | - -![oltp_point_select](/media/oltp_point_select.png) - -### oltp_update_index - -| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | -|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | -| oltp_update_index | 3\*8 | 9668.98 | 9668.98 | 2.51 | 3.19 | 103.88| -| oltp_update_index | 3\*16 | 12834.99 | 12834.99 | 3.79 | 5.47 | 176.90 | -| oltp_update_index | 3\*32 | 15955.77 | 15955.77 | 6.07 | 9.39 | 4787.14 | -| oltp_update_index | 3\*64 | 18697.17 | 18697.17 | 10.34 | 17.63 | 4539.04 | -| oltp_update_index | 3\*128 | 20446.81 | 20446.81 | 18.98 | 40.37 | 5394.75 | -| oltp_update_index | 3\*256 | 23563.03 | 23563.03 | 32.86 | 78.60 | 5530.69 | - -![oltp_update_index](/media/oltp_update_index.png) - -### oltp_read_only - -| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | -|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | -| oltp_read_only | 3\*8 | 2411.00 | 38575.96 | 9.92 | 20.00 | 92.23 | -| oltp_read_only | 3\*16 | 3873.53 | 61976.50 | 12.25 | 16.12 | 56.94 | -| oltp_read_only | 3\*32 | 5066.88 | 81070.16 | 19.42 | 26.20 | 123.41 | -| oltp_read_only | 3\*64 | 5466.36 | 87461.81 | 34.65 | 63.20 | 231.19 | -| oltp_read_only | 3\*128 | 6684.16 | 106946.59 | 57.29 | 97.55 | 180.85 | - -![oltp_read_only](/media/oltp_read_only.png) - -## 常见问题 - -### 在高并发压力下,TiDB、TiKV 的配置都合理,为什么整体性能还是偏低? - -这种情况可能与使用了 proxy 有关。可以尝试直接对单个 TiDB 加压,将求和后的结果与使用 proxy 的情况进行对比。 - -以 HAproxy 为例。`nbproc` 参数可以增加其最大启动的进程数,较新版本的 HAproxy 还支持 `nbthread` 和 `cpu-map` 等。这些都可以减少对其性能的不利影响。 - -### 在高并发压力下,为什么 TiKV 的 CPU 利用率依然很低? - -TiKV 虽然整体 CPU 偏低,但部分模块的 CPU 可能已经达到了很高的利用率。 - -TiKV 的其他模块,如 storage readpool、coprocessor 和 gRPC 的最大并发度限制是可以通过 TiKV 的配置文件进行调整的。 - -通过 Grafana 的 TiKV Thread CPU 监控面板可以观察到其实际使用率。如出现多线程模块瓶颈,可以通过增加该模块并发度进行调整。 - -### 在高并发压力下,TiKV 也未达到 CPU 使用瓶颈,为什么 TiDB 的 CPU 利用率依然很低? - -在某些高端设备上,使用的是 NUMA 架构的 CPU,跨 CPU 访问远端内存将极大降低性能。TiDB 默认将使用服务器所有 CPU,goroutine 的调度不可避免地会出现跨 CPU 内存访问。 - -因此,建议在 NUMA 架构服务器上,部署 *n* 个 TiDB(*n* = NUMA CPU 的个数),同时将 TiDB 的 `max-procs` 变量的值设置为与 NUMA CPU 的核数相同。 diff --git a/benchmark/how-to-run-tpcc.md b/benchmark/how-to-run-tpcc.md deleted file mode 100644 index c28c4a64b260..000000000000 --- a/benchmark/how-to-run-tpcc.md +++ /dev/null @@ -1,258 +0,0 @@ ---- -title: 如何对 TiDB 进行 TPC-C 测试 -category: benchmark ---- - -# 如何对 TiDB 进行 TPC-C 测试 - -本文介绍如何对 TiDB 进行 [TPC-C](http://www.tpc.org/tpcc/) 测试。 - -## 准备测试程序 - -TPC-C 是一个对 OLTP(联机交易处理)系统进行测试的规范,使用一个商品销售模型对 OLTP 系统进行测试,其中包含五类事务: - -* NewOrder – 新订单的生成 -* Payment – 订单付款 -* OrderStatus – 最近订单查询 -* Delivery – 配送 -* StockLevel – 库存缺货状态分析 - -在测试开始前,TPC-C Benchmark 规定了数据库的初始状态,也就是数据库中数据生成的规则,其中 ITEM 表中固定包含 10 万种商品,仓库的数量可进行调整,假设 WAREHOUSE 表中有 W 条记录,那么: - -* STOCK 表中应有 W \* 10 万条记录(每个仓库对应 10 万种商品的库存数据) -* DISTRICT 表中应有 W \* 10 条记录(每个仓库为 10 个地区提供服务) -* CUSTOMER 表中应有 W \* 10 \* 3000 条记录(每个地区有 3000 个客户) -* HISTORY 表中应有 W \* 10 \* 3000 条记录(每个客户一条交易历史) -* ORDER 表中应有 W \* 10 \* 3000 条记录(每个地区 3000 个订单),并且最后生成的 900 个订单被添加到 NEW-ORDER 表中,每个订单随机生成 5 ~ 15 条 ORDER-LINE 记录。 - -我们将以 1000 WAREHOUSE 为例进行测试。 - -TPC-C 使用 tpmC 值(Transactions per Minute)来衡量系统最大有效吞吐量 (MQTh, Max Qualified Throughput),其中 Transactions 以 NewOrder Transaction 为准,即最终衡量单位为每分钟处理的新订单数。 - -本文使用开源的 BenchmarkSQL 5.0 作为 TPC-C 测试实现并添加了对 MySQL 协议的支持,可以通过以下命令下载测试程序: - -{{< copyable "shell-regular" >}} - -```shell -git clone -b 5.0-mysql-support-opt-2.1 https://github.com/pingcap/benchmarksql.git -``` - -安装 java 和 ant,以 CentOS 为例,可以执行以下命令进行安装 - -{{< copyable "shell-regular" >}} - -```shell -sudo yum install -y java ant -``` - -进入 benchmarksql 目录并执行 ant 构建 - -{{< copyable "shell-regular" >}} - -```shell -cd benchmarksql -ant -``` - -## 部署 TiDB 集群 - -对于 1000 WAREHOUSE 我们将在 3 台服务器上部署集群。 - -在 3 台服务器的条件下,建议每台机器部署 1 个 TiDB,1 个 PD 和 1 个 TiKV 实例。 - -比如这里采用的机器硬件配置是: - -| 类别 | 名称 | -| :-: | :-: | -| OS | Linux (CentOS 7.3.1611) | -| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | -| RAM | 128GB | -| DISK | Optane 500GB SSD | - -因为该型号 CPU 是 NUMA 架构,建议先用 `taskset` 进行绑核,首先用 `lscpu` 查看 NUMA node,比如: - -```text -NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38 -NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39 -``` - -之后可以通过下面的命令来启动 TiDB: - -{{< copyable "shell-regular" >}} - -```shell -nohup taskset -c 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38 bin/tidb-server && \ -nohup taskset -c 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39 bin/tidb-server -``` - -最后,可以选择部署一个 HAproxy 来进行多个 TiDB node 的负载均衡,推荐配置 nbproc 为 CPU 核数。 - -## 配置调整 - -### TiDB 配置 - -```toml -[log] -level = "error" - -[performance] -# 根据 NUMA 配置,设置单个 TiDB 最大使用的 CPU 核数 -max-procs = 20 - -[prepared_plan_cache] -# 开启 TiDB 配置中的 prepared plan cache,以减少优化执行计划的开销 -enabled = true -``` - -### TiKV 配置 - -开始可以使用基本的配置,压测运行后可以通过观察 Grafana 并参考 [TiKV 调优说明](/reference/performance/tune-tikv.md)进行调整。 - -### BenchmarkSQL 配置 - -修改 `benchmarksql/run/props.mysql`: - -```text -conn=jdbc:mysql://{HAPROXY-HOST}:{HAPROXY-PORT}/tpcc?useSSL=false&useServerPrepStmts=true&useConfigs=maxPerformance -warehouses=1000 # 使用 1000 个 warehouse -terminals=500 # 使用 500 个终端 -loadWorkers=32 # 导入数据的并发数 -``` - -## 导入数据 - -**导入数据通常是整个 TPC-C 测试中最耗时,也是最容易出问题的阶段。** - -首先用 MySQL 客户端连接到 TiDB-Server 并执行: - -{{< copyable "sql" >}} - -```sql -create database tpcc -``` - -之后在 shell 中运行 BenchmarkSQL 建表脚本: - -{{< copyable "shell-regular" >}} - -```shell -cd run && \ -./runSQL.sh props.mysql sql.mysql/tableCreates.sql && \ -./runSQL.sh props.mysql sql.mysql/indexCreates.sql -``` - -### 直接使用 BenchmarkSQL 导入 - -运行导入数据脚本: - -{{< copyable "shell-regular" >}} - -```shell -./runLoader.sh props.mysql -``` - -根据机器配置这个过程可能会持续几个小时。 - -### 通过 TiDB Lightning 导入 - -由于导入数据量随着 warehouse 的增加而增加,当需要导入 1000 warehouse 以上数据时,可以先用 BenchmarkSQL 生成 csv 文件,再将文件通过 TiDB Lightning(以下简称 Lightning)导入的方式来快速导入。生成的 csv 文件也可以多次复用,节省每次生成所需要的时间。 - -#### 修改 BenchmarkSQL 的配置文件 - -1 warehouse 的 csv 文件需要 77 MB 磁盘空间,在生成之前要根据需要分配足够的磁盘空间来保存 csv 文件。可以在 `benchmarksql/run/props.mysql` 文件中增加一行: - -```text -fileLocation=/home/user/csv/ # 存储 csv 文件的目录绝对路径,需保证有足够的空间 -``` - -因为最终要使用 Lightning 导入数据,所以 csv 文件名最好符合 Lightning 要求,即 `{database}.{table}.csv` 的命名法。这里可以将以上配置改为: - -```text -fileLocation=/home/user/csv/tpcc. # 存储 csv 文件的目录绝对路径 + 文件名前缀(database) -``` - -这样生成的 csv 文件名将会是类似 `tpcc.bmsql_warehouse.csv` 的样式,符合 Lightning 的要求。 - -#### 生成 csv 文件 - -{{< copyable "shell-regular" >}} - -```shell -./runLoader.sh props.mysql -``` - -#### 通过 Lightning 导入 - -通过 Lightning 导入数据请参考 [Lightning 部署执行](/reference/tools/tidb-lightning/deployment.md)章节。这里我们介绍下通过 TiDB Ansible 部署 Lightning 导入数据的方法。 - -##### 修改 inventory.ini - -这里最好手动指定清楚部署的 IP、端口、目录,避免各种冲突问题带来的异常,其中 import_dir 的磁盘空间参考 [Lightning 部署执行](/reference/tools/tidb-lightning/deployment.md),data_source_dir 就是存储上一节 csv 数据的目录。 - -```ini -[importer_server] -IS1 ansible_host=172.16.5.34 deploy_dir=/data2/is1 tikv_importer_port=13323 import_dir=/data2/import - -[lightning_server] -LS1 ansible_host=172.16.5.34 deploy_dir=/data2/ls1 tidb_lightning_pprof_port=23323 data_source_dir=/home/user/csv -``` - -##### 修改 conf/tidb-lightning.yml - -```yaml -mydumper: - no-schema: true - csv: - separator: ',' - delimiter: '' - header: false - not-null: false - 'null': 'NULL' - backslash-escape: true - trim-last-separator: false -``` - -##### 部署 Lightning 和 Importer - -{{< copyable "shell-regular" >}} - -```shell -ansible-playbook deploy.yml --tags=lightning -``` - -##### 启动 - -* 登录到部署 Lightning 和 Importer 的服务器 -* 进入部署目录 -* 在 Importer 目录下执行 `scripts/start_importer.sh`,启动 Importer -* 在 Lightning 目录下执行 `scripts/start_lightning.sh`,开始导入数据 - -由于是用 TiDB Ansible 进行部署的,可以在监控页面看到 Lightning 的导入进度,或者通过日志查看导入是否结束。 - -### 导入完成后 - -数据导入完成之后,可以运行 `sql.common/test.sql` 进行数据正确性验证,如果所有 SQL 语句都返回结果为空,即为数据导入正确。 - -## 运行测试 - -执行 BenchmarkSQL 测试脚本: - -{{< copyable "shell-regular" >}} - -```shell -nohup ./runBenchmark.sh props.mysql &> test.log & -``` - -运行结束后通过 `test.log` 查看结果: - -```text -07:09:53,455 [Thread-351] INFO jTPCC : Term-00, Measured tpmC (NewOrders) = 77373.25 -07:09:53,455 [Thread-351] INFO jTPCC : Term-00, Measured tpmTOTAL = 171959.88 -07:09:53,455 [Thread-351] INFO jTPCC : Term-00, Session Start = 2019-03-21 07:07:52 -07:09:53,456 [Thread-351] INFO jTPCC : Term-00, Session End = 2019-03-21 07:09:53 -07:09:53,456 [Thread-351] INFO jTPCC : Term-00, Transaction Count = 345240 -``` - -tpmC 部分即为测试结果。 - -测试完成之后,也可以运行 `sql.common/test.sql` 进行数据正确性验证,如果所有 SQL 语句的返回结果都为空,即为数据测试过程正确。 diff --git a/benchmark/online-workloads-and-add-index-operations.md b/benchmark/online-workloads-and-add-index-operations.md new file mode 100644 index 000000000000..561b463a62fc --- /dev/null +++ b/benchmark/online-workloads-and-add-index-operations.md @@ -0,0 +1,349 @@ +--- +title: 线上负载与 `ADD INDEX` 相互影响测试 +category: benchmark +aliases: ['/docs-cn/stable/benchmark/add-index-with-load/'] +--- + +# 线上负载与 `ADD INDEX` 相互影响测试 + +## 测试目的 + +测试 OLTP 场景下,`ADD INDEX` 与线上负载的相互影响。 + +## 测试版本、时间、地点 + +TiDB 版本:v3.0.1 + +时间:2019 年 7 月 + +地点:北京 + +## 测试环境 + +测试在 Kubernetes 集群上进行,部署了 3 个 TiDB 实例,3 个 TiKV 实例和 3 个 PD 实例。 + +### 版本信息 + +| 组件 | GitHash | +| :--- | :---------------------------------------- | +| TiDB | `9e4e8da3c58c65123db5f26409759fe1847529f8` | +| TiKV | `4151dc8878985df191b47851d67ca21365396133` | +| PD | `811ce0b9a1335d1b2a049fd97ef9e186f1c9efc1` | + +Sysbench 版本:1.0.17 + +### TiDB 参数配置 + +TiDB、TiKV 和 PD 均使用 [TiDB Operator](https://github.com/pingcap/tidb-operator) 默认配置。 + +### 集群拓扑 + +| 机器 IP | 部署实例 | +| :-------------------------------------- | :----------| +| 172.31.8.8 | Sysbench | +| 172.31.7.69, 172.31.5.152, 172.31.11.133 | PD | +| 172.31.4.172, 172.31.1.155, 172.31.9.210 | TiKV | +| 172.31.7.80, 172.31.5.163, 172.31.11.123 | TiDB | + +### 使用 Sysbench 模拟线上负载 + +使用 Sysbench 向集群导入 **1 张表,200 万行数据**。 + +执行如下命令导入数据: + +{{< copyable "shell-regular" >}} + +```sh +sysbench oltp_common \ + --threads=16 \ + --rand-type=uniform \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=$tidb_host \ + --mysql-port=$tidb_port \ + --mysql-user=root \ + prepare --tables=1 --table-size=2000000 +``` + +执行如下命令测试数据: + +{{< copyable "shell-regular" >}} + +```sh +sysbench $testname \ + --threads=$threads \ + --time=300000 \ + --report-interval=15 \ + --rand-type=uniform \ + --rand-seed=$RANDOM \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=$tidb_host \ + --mysql-port=$tidb_port \ + --mysql-user=root \ + run --tables=1 --table-size=2000000 +``` + +## 测试方案 1:`ADD INDEX` 目标列被频繁 Update + +1. 开始 `oltp_read_write` 测试。 +2. 与步骤 1 同时,使用 `alter table sbtest1 add index c_idx(c)` 添加索引。 +3. 在步骤 2 结束,即索引添加完成时,停止步骤 1 的测试。 +4. 获取 `alter table ... add index` 的运行时间、sysbench 在该时间段内的平均 TPS 和 QPS 作为指标。 +5. 逐渐增大 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 两个参数的值,重复步骤 1-4。 + +### 测试结果 + +#### 无 `ADD INDEX` 时 `oltp_read_write` 的结果 + +| sysbench TPS | sysbench QPS | +| :------- | :-------- | +| 350.31 | 6806 | + +#### `tidb_ddl_reorg_batch_size = 32` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 402 | 338.4 | 6776 | +| 2 | 266 | 330.3 | 6001 | +| 4 | 174 | 288.5 | 5769 | +| 8 | 129 | 280.6 | 5612 | +| 16 | 90 | 263.5 | 5273 | +| 32 | 54 | 229.2 | 4583 | +| 48 | 57 | 230.1 | 4601 | + +![add-index-load-1-b32](/media/add-index-load-1-b32.png) + +#### `tidb_ddl_reorg_batch_size = 64` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 264 | 269.4 | 5388 | +| 2 | 163 | 266.2 | 5324 | +| 4 | 105 | 272.5 | 5430 | +| 8 | 78 | 262.5 | 5228 | +| 16 | 57 | 215.5 | 4308 | +| 32 | 42 | 185.2 | 3715 | +| 48 | 45 | 189.2 | 3794 | + +![add-index-load-1-b64](/media/add-index-load-1-b64.png) + +#### `tidb_ddl_reorg_batch_size = 128` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 171 | 289.1 | 5779 | +| 2 | 110 | 274.2 | 5485 | +| 4 | 79 | 250.6 | 5011 | +| 8 | 51 | 246.1 | 4922 | +| 16 | 39 | 171.1 | 3431 | +| 32 | 35 | 130.8 | 2629 | +| 48 | 35 | 120.5 | 2425 | + +![add-index-load-1-b128](/media/add-index-load-1-b128.png) + +#### `tidb_ddl_reorg_batch_size = 256` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 145 | 283.0 | 5659 | +| 2 | 96 | 282.2 | 5593 | +| 4 | 56 | 236.5 | 4735 | +| 8 | 45 | 194.2 | 3882 | +| 16 | 39 | 149.3 | 2893 | +| 32 | 36 | 113.5 | 2268 | +| 48 | 33 | 86.2 | 1715 | + +![add-index-load-1-b256](/media/add-index-load-1-b256.png) + +#### `tidb_ddl_reorg_batch_size = 512` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 135 | 257.8 | 5147 | +| 2 | 78 | 252.8 | 5053 | +| 4 | 49 | 222.7 | 4478 | +| 8 | 36 | 145.4 | 2904 | +| 16 | 33 | 109 | 2190 | +| 32 | 33 | 72.5 | 1503 | +| 48 | 33 | 54.2 | 1318 | + +![add-index-load-1-b512](/media/add-index-load-1-b512.png) + +#### `tidb_ddl_reorg_batch_size = 1024` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 111 | 244.3 | 4885 | +| 2 | 78 | 228.4 | 4573 | +| 4 | 54 | 168.8 | 3320 | +| 8 | 39 | 123.8 | 2475 | +| 16 | 36 | 59.6 | 1213 | +| 32 | 42 | 93.2 | 1835 | +| 48 | 51 | 115.7 | 2261 | + +![add-index-load-1-b1024](/media/add-index-load-1-b1024.png) + +#### `tidb_ddl_reorg_batch_size = 2048` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 918 | 243.3 | 4855 | +| 2 | 1160 | 209.9 | 4194 | +| 4 | 342 | 185.4 | 3707 | +| 8 | 1316 | 151.0 | 3027 | +| 16 | 795 | 30.5 | 679 | +| 32 | 1130 | 26.69 | 547 | +| 48 | 893 | 27.5 | 552 | + +![add-index-load-1-b2048](/media/add-index-load-1-b2048.png) + +#### `tidb_ddl_reorg_batch_size = 4096` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 3042 | 200.0 | 4001 | +| 2 | 3022 | 203.8 | 4076 | +| 4 | 858 | 195.5 | 3971 | +| 8 | 3015 | 177.1 | 3522 | +| 16 | 837 | 143.8 | 2875 | +| 32 | 942 | 114 | 2267 | +| 48 | 187 | 54.2 | 1416 | + +![add-index-load-1-b4096](/media/add-index-load-1-b4096.png) + +### 测试结论 + +若 `ADD INDEX` 的目标列正在进行较为频繁的写操作(本测试涉及列的 `UPDATE`、`INSERT` 和 `DELETE`),默认 `ADD INDEX` 配置对系统的线上负载有比较明显的影响,该影响主要来源于 `ADD INDEX` 与 Column Update 并发进行造成的写冲突,系统的表现反应在: + +- 随着两个参数的逐渐增大,`TiKV_prewrite_latch_wait_duration` 有明显的升高,造成写入变慢。 +- `tidb_ddl_reorg_worker_cnt` 与 `tidb_ddl_reorg_batch_size` 非常大时,`admin show ddl` 命令可以看到 DDL job 的多次重试(例如 `Write conflict, txnStartTS 410327455965380624 is stale [try again later], ErrCount:38, SnapshotVersion:410327228136030220`),此时 `ADD INDEX` 会持续非常久才能完成。 + +## 测试方案 2:`ADD INDEX` 目标列不涉及写入(仅查询) + +1. 开始 `oltp_read_only` 测试。 +2. 与步骤 1 同时,使用 `alter table sbtest1 add index c_idx(c)` 添加索引。 +3. 在步骤 2 结束,即索引添加完成时,停止步骤 1。 +4. 获取 `alter table ... add index` 的运行时间、sysbench 在该时间段内的平均 TPS 和 QPS 作为指标。 +5. 逐渐增大 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 两个参数,重复步骤 1-4。 + +### 测试结果 + +#### 无 `ADD INDEX` 时 `oltp_read_only` 结果 + +| sysbench TPS | sysbench QPS | +| :------- | :-------- | +| 550.9 | 8812.8 | + +#### `tidb_ddl_reorg_batch_size = 32` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 376 | 548.9 | 8780 | +| 2 | 212 | 541.5 | 8523 | +| 4 | 135 | 538.6 | 8549 | +| 8 | 114 | 536.7 | 8393 | +| 16 | 77 | 533.9 | 8292 | +| 32 | 46 | 533.4 | 8103 | +| 48 | 46 | 532.2 | 8074 | + +![add-index-load-2-b32](/media/add-index-load-2-b32.png) + +#### `tidb_ddl_reorg_batch_size = 1024` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 91 | 536.8 | 8316 | +| 2 | 52 | 533.9 | 8165 | +| 4 | 40 | 522.4 | 7947 | +| 8 | 36 | 510 | 7860 | +| 16 | 33 | 485.5 | 7704 | +| 32 | 31 | 467.5 | 7516 | +| 48 | 30 | 562.1 | 7442 | + +![add-index-load-2-b1024](/media/add-index-load-2-b1024.png) + +#### `tidb_ddl_reorg_batch_size = 4096` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 103 | 502.2 | 7823 | +| 2 | 63 | 486.5 | 7672 | +| 4 | 52 | 467.4 | 7516 | +| 8 | 39 | 452.5 | 7302 | +| 16 | 35 | 447.2 | 7206 | +| 32 | 30 | 441.9 | 7057 | +| 48 | 30 | 440.1 | 7004 | + +![add-index-load-2-b4096](/media/add-index-load-2-b4096.png) + +### 测试结论 + +`ADD INDEX` 的目标列仅有查询负载时,`ADD INDEX` 对负载的影响不明显。 + +## 测试方案 3:集群负载不涉及 `ADD INDEX` 目标列 + +1. 开始 `oltp_read_write` 测试。 +2. 与步骤 1 同时,使用 `alter table test add index pad_idx(pad)` 添加索引。 +3. 在步骤 2 结束,即索引添加完成时,停止步骤 1 的测试。 +4. 获取 `alter table ... add index` 的运行时间、sysbench 在该时间段内的平均 TPS 和 QPS 作为指标。 +5. 逐渐增大 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 两个参数,重复步骤 1-4。 + +### 测试结果 + +#### 无 `ADD INDEX` 时 `oltp_read_write` 的结果 + +| sysbench TPS | sysbench QPS | +| :------- | :-------- | +| 350.31 | 6806 | + +#### `tidb_ddl_reorg_batch_size = 32` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 372 | 350.4 | 6892 | +| 2 | 207 | 344.2 | 6700 | +| 4 | 140 | 343.1 | 6672 | +| 8 | 121 | 339.1 | 6579 | +| 16 | 76 | 340 | 6607 | +| 32 | 42 | 343.1 | 6695 | +| 48 | 42 | 333.4 | 6454 | + +![add-index-load-3-b32](/media/add-index-load-3-b32.png) + +#### `tidb_ddl_reorg_batch_size = 1024` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 94 | 352.4 | 6794 | +| 2 | 50 | 332 | 6493 | +| 4 | 45 | 330 | 6456 | +| 8 | 36 | 325.5 | 6324 | +| 16 | 32 | 312.5 | 6294 | +| 32 | 32 | 300.6 | 6017 | +| 48 | 31 | 279.5 | 5612 | + +![add-index-load-3-b1024](/media/add-index-load-3-b1024.png) + +#### `tidb_ddl_reorg_batch_size = 4096` + +| tidb_ddl_reorg_worker_cnt | add_index_durations(s) | sysbench TPS | sysbench QPS | +| :------------------------ | :---------------------- | :------------- | :----------- | +| 1 | 116 | 325.5 | 6324 | +| 2 | 65 | 312.5 | 6290 | +| 4 | 50 | 300.6 | 6017 | +| 8 | 37 | 279.5 | 5612 | +| 16 | 34 | 250.4 | 5365 | +| 32 | 32 | 220.2 | 4924 | +| 48 | 33 | 214.8 | 4544 | + +![add-index-load-3-b4096](/media/add-index-load-3-b4096.png) + +### 测试结论 + +`ADD INDEX` 的目标列与负载无关时,`ADD INDEX` 对负载的影响不明显。 + +## 总结 + +- 当 `ADD INDEX` 的目标列被频繁更新(包含 `UPDATE`、`INSERT` 和 `DELETE`)时,默认配置会造成较为频繁的写冲突,使得在线负载较大;同时 `ADD INDEX` 也可能由于不断地重试,需要很长的时间才能完成。在本次测试中,将 `tidb_ddl_reorg_worker_cnt` 和 `tidb_ddl_reorg_batch_size` 的乘积调整为默认值的 1/32(例如 `tidb_ddl_reorg_worker_cnt` = 4,`tidb_ddl_reorg_batch_size` = 256)可以取得较好的效果。 +- 当 `ADD INDEX` 的目标列仅涉及查询负载,或者与线上负载不直接相关时,可以直接使用默认配置。 \ No newline at end of file diff --git a/benchmark/sysbench-v2.md b/benchmark/sysbench-v2.md deleted file mode 100644 index bce70f8a8400..000000000000 --- a/benchmark/sysbench-v2.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: TiDB Sysbench 性能对比测试报告 - v2.0.0 对比 v1.0.0 -category: benchmark ---- - -# TiDB Sysbench 性能对比测试报告 - v2.0.0 对比 v1.0.0 - -## 测试目的 - -对比 TiDB 2.0 版本和 1.0 版本在 OLTP 场景下的性能。 - -## 测试版本、时间、地点 - -TiDB 版本:v1.0.8 Vs v2.0.0-rc6 - -时间:2018 年 4 月 - -地点:北京 - -## 测试环境 - -IDC 机器 - -| 类别 | 名称 | -| :--------: | :---------: | -| OS | Linux (CentOS 7.3.1611) | -| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | -| RAM | 128GB | -| DISK | Optane 500GB SSD * 1 | - -## 测试方案 - -### TiDB 版本信息 - -### v1.0.8 - -| 组件 | GitHash | -| :--------: | :---------: | -| TiDB | 571f0bbd28a0b8155a5ee831992c986b90d21ab7 | -| TiKV | 4ef5889947019e3cb55cc744f487aa63b42540e7 | -| PD | 776bcd940b71d295a2c7ed762582bc3aff7d3c0e | - -### v2.0.0-rc6 - -| 组件 | GitHash | -| :--------: | :---------: | -| TiDB | 82d35f1b7f9047c478f4e1e82aa0002abc8107e7 | -| TiKV | 7ed4f6a91f92cad5cd5323aaebe7d9f04b77cc79 | -| PD | 2c8e7d7e33b38e457169ce5dfb2f461fced82d65 | - -### TiKV 参数配置 - -* v1.0.8 - - ``` - sync-log = false - grpc-concurrency = 8 - grpc-raft-conn-num = 24 - ``` - -* v2.0.0-rc6 - - ``` - sync-log = false - grpc-concurrency = 8 - grpc-raft-conn-num = 24 - use-delete-range: false - ``` - -### 集群拓扑 - -| 机器 IP | 部署实例 | -|--------------|------------| -| 172.16.21.1 | 1*tidb 1*pd 1*sysbench | -| 172.16.21.2 | 1*tidb 1*pd 1*sysbench | -| 172.16.21.3 | 1*tidb 1*pd 1*sysbench | -| 172.16.11.4 | 1*tikv | -| 172.16.11.5 | 1*tikv | -| 172.16.11.6 | 1*tikv | -| 172.16.11.7 | 1*tikv | -| 172.16.11.8 | 1*tikv | -| 172.16.11.9 | 1*tikv | - -## 测试结果 - -### 标准 Select 测试 - -| 版本 | table count | table size | sysbench threads |qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | -| v2.0.0-rc6 | 32 | 1000 万 | 128 * 3 | 201936 | 1.9033 ms / 5.67667 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 256 * 3 | 208130 | 3.69333 ms / 8.90333 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 512 * 3 | 211788 | 7.23333 ms / 15.59 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 1024 * 3 | 212868 | 14.5933 ms / 43.2133 ms | -| v1.0.8 | 32 | 1000 万 | 128 * 3 | 188686 | 2.03667 ms / 5.99 ms | -| v1.0.8 | 32 | 1000 万 | 256 * 3 | 195090 |3.94 ms / 9.12 ms | -| v1.0.8 | 32 | 1000 万 | 512 * 3 | 203012 | 7.57333 ms / 15.3733 ms | -| v1.0.8 | 32 | 1000 万 | 1024 * 3 | 205932 | 14.9267 ms / 40.7633 ms | - -GA2.0 比 GA1.0 在 Select 查询性能上,最高提升了 10% 左右。 - -### 标准 OLTP 测试 - -| 版本 | table count | table size | sysbench threads | tps | qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | :---:| -| v2.0.0-rc6 | 32 | 1000 万 | 128 * 3 | 5404.22 | 108084.4 | 87.2033 ms / 110 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 256 * 3 | 5578.165 | 111563.3 | 167.673 ms / 275.623 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 512 * 3 | 5874.045 | 117480.9 | 315.083 ms / 674.017 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 1024 * 3 | 6290.7 | 125814 | 529.183 ms / 857.007 ms | -| v1.0.8 | 32 | 1000 万 | 128 * 3 | 5523.91 | 110478 | 69.53 ms / 88.6333 ms | -| v1.0.8 | 32 | 1000 万 | 256 * 3 | 5969.43 | 119389 |128.63 ms / 162.58 ms | -| v1.0.8 | 32 | 1000 万 | 512 * 3 | 6308.93 | 126179 | 243.543 ms / 310.913 ms | -| v1.0.8 | 32 | 1000 万 | 1024 * 3 | 6444.25 | 128885 | 476.787ms / 635.143 ms | - -GA2.0 比 GA1.0 在 OLTP 性能上,性能基本一致。 - -### 标准 Insert 测试 - -| 版本 | table count | table size | sysbench threads |qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | -| v2.0.0-rc6 | 32 | 1000 万 | 128 * 3 | 31707.5 | 12.11 ms / 21.1167 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 256 * 3 | 38741.2 | 19.8233 ms / 39.65 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 512 * 3 | 45136.8 | 34.0267 ms / 66.84 ms | -| v2.0.0-rc6 | 32 | 1000 万 | 1024 * 3 | 48667 | 63.1167 ms / 121.08 ms | -| v1.0.8 | 32 | 1000 万 | 128 * 3 | 31125.7 | 12.3367 ms / 19.89 ms | -| v1.0.8 | 32 | 1000 万 | 256 * 3 | 36800 | 20.8667 ms / 35.3767 ms | -| v1.0.8 | 32 | 1000 万 | 512 * 3 | 44123 | 34.8067 ms / 63.32 ms | -| v1.0.8 | 32 | 1000 万 | 1024 * 3 | 48496 | 63.3333 ms / 118.92 ms | - -GA2.0 比 GA1.0 在 Insert 性能上略有提升。 diff --git a/benchmark/sysbench-v3.md b/benchmark/sysbench-v3.md deleted file mode 100644 index 35270f2451c3..000000000000 --- a/benchmark/sysbench-v3.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: TiDB Sysbench 性能对比测试报告 - v2.1 对比 v2.0 -category: benchmark ---- - -# TiDB Sysbench 性能对比测试报告 - v2.1 对比 v2.0 - -## 测试目的 - -对比 TiDB 2.1 版本和 2.0 版本在 OLTP 场景下的性能。 - -## 测试版本、时间、地点 - -TiDB 版本:v2.1.0-rc.2 vs. v2.0.6 - -时间:2018 年 9 月 - -地点:北京 - -## 测试环境 - -IDC 机器: - -| 类别 | 名称 | -| :-: | :-: | -| OS | Linux (CentOS 7.3.1611) | -| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | -| RAM | 128GB | -| DISK | Optane 500GB SSD \* 1 | - -Sysbench 版本:1.1.0 - -## 测试方案 - -使用 Sysbench 向集群导入 **16 张表,每张数据 1000 万**。通过 HAProxy 代理,分别以递增并发数向集群发送请求,单次并发测试时间 5 分钟。 - -### TiDB 版本信息 - -### v2.1.0-rc.2 - -| 组件 | GitHash | -| :-: | :-: | -| TiDB | 08e56cd3bae166b2af3c2f52354fbc9818717f62 | -| TiKV | 57e684016dafb17dc8a6837d30224be66cbc7246 | -| PD | 6a7832d2d6e5b2923c79683183e63d030f954563 | - -### v2.0.6 - -| 组件 | GitHash | -| :-: | :-: | -| TiDB | b13bc08462a584a085f377625a7bab0cc0351570 | -| TiKV | 57c83dc4ebc93d38d77dc8f7d66db224760766cc | -| PD | b64716707b7279a4ae822be767085ff17b5f3fea | - -### TiDB 参数配置 - -两版本 TiDB 均使用**默认配置**。 - -### TiKV 参数配置 - -两版本 TiKV 均使用如下配置: - -```txt -[readpool.storage] -normal-concurrency = 8 -[server] -grpc-concurrency = 8 -[raftstore] -sync-log = false -[rocksdb.defaultcf] -block-cache-size = "60GB" -[rocksdb.writecf] -block-cache-size = "20GB" -``` - -### 集群拓扑 - -| 机器 IP | 部署实例 | -| :-: | :-: | -| 172.16.30.31 | 1\*Sysbench 1\*HAProxy | -| 172.16.30.32 | 1\*TiDB 1\*pd 1\*TiKV | -| 172.16.30.33 | 1\*TiDB 1\*TiKV | -| 172.16.30.34 | 1\*TiDB 1\*TiKV | - -## 测试结果 - -### Point Select 测试 - -| 版本 | threads | qps | 95% latency(ms) | -| :-: | :-: | :-: | :-: | -| v2.1 | 64 | 111481.09 | 1.16 | -| v2.1 | 128 | 145102.62 | 2.52 | -| v2.1 | 256 | 161311.9 | 4.57 | -| v2.1 | 512 | 184991.19 | 7.56 | -| v2.1 | 1024 | 230282.74 | 10.84 | -| v2.0 | 64 | 75285.87 | 1.93 | -| v2.0 | 128 | 92141.79 | 3.68 | -| v2.0 | 256 | 107464.93 | 6.67 | -| v2.0 | 512 | 121350.61 | 11.65 | -| v2.0 | 1024 | 150036.31 | 17.32 | - -![point select](/media/sysbench_v3_point_select.png) - -v2.1 比 v2.0 在 Point Select 查询性能上,**提升了 50%**。 - -### Update Non-Index 测试 - -| 版本 | threads | qps | 95% latency(ms) | -| :-: | :-: | :-: | :-: | -| v2.1 | 64 | 18946.09 | 5.77 | -| v2.1 | 128 | 22022.82 | 12.08 | -| v2.1 | 256 | 24679.68 | 25.74 | -| v2.1 | 512 | 25107.1 | 51.94 | -| v2.1 | 1024 | 27144.92 | 106.75 | -| v2.0 | 64 | 16316.85 | 6.91 | -| v2.0 | 128 | 20944.6 | 11.45 | -| v2.0 | 256 | 24017.42 | 23.1 | -| v2.0 | 512 | 25994.33 | 46.63 | -| v2.0 | 1024 | 27917.52 | 92.42 | - -![update non-index](/media/sysbench_v3_update_non_index.png) - -v2.1 与 v2.0 在 Update Non-Index 写入性能上基本一致。 - -### Update Index 测试 - -| 版本 | threads | qps | 95% latency(ms) | -| :-: | :-: | :-: | :-: | -| v2.1 | 64 | 9934.49 | 12.08 | -| v2.1 | 128 | 10505.95 | 25.28 | -| v2.1 | 256 | 11007.7 | 55.82 | -| v2.1 | 512 | 11198.81 | 106.75 | -| v2.1 | 1024 | 11591.89 | 200.47 | -| v2.0 | 64 | 9754.68 | 11.65 | -| v2.0 | 128 | 10603.31 | 24.38 | -| v2.0 | 256 | 11011.71 | 50.11 | -| v2.0 | 512 | 11162.63 | 104.84 | -| v2.0 | 1024 | 12067.63 | 179.94 | - -![update index](/media/sysbench_v3_update_index.png) - -v2.1 与 v2.0 在 Update Index 写入性能上基本一致。 diff --git a/benchmark/sysbench-v4.md b/benchmark/sysbench-v4.md deleted file mode 100644 index 31175bd29a26..000000000000 --- a/benchmark/sysbench-v4.md +++ /dev/null @@ -1,278 +0,0 @@ ---- -title: TiDB Sysbench 性能对比测试报告 - v3.0 对比 v2.1 -category: benchmark ---- - -# TiDB Sysbench 性能对比测试报告 - v3.0 对比 v2.1 - -## 测试目的 - -对比 TiDB 3.0 版本和 2.1 版本在 OLTP 场景下的性能。 - -## 测试版本、时间、地点 - -TiDB 版本:v3.0.0 vs. v2.1.13 - -时间:2019 年 6 月 - -地点:北京 - -## 测试环境 - -测试在 AWS EC2 上进行,使用 CentOS-7.6.1810-Nitro (ami-028946f4cffc8b916) 镜像,各组件实例类型如下: - -| 组件 | 实例类型 | -| :--- | :--------- | -| PD | r5d.xlarge | -| TiKV | c5d.4xlarge | -| TiDB | c5.4xlarge | - -Sysbench 版本:1.0.17 - -## 测试方案 - -使用 Sysbench 向集群导入 **16 张表,每张数据 1000 万**。起 3 个 sysbench 分别向 3 个 TiDB 发压,请求并发数逐步增加,单次测试时间 5 分钟。 - -准备数据命令: - -{{< copyable "shell-regular" >}} - -```sh -sysbench oltp_common \ - --threads=16 \ - --rand-type=uniform \ - --db-driver=mysql \ - --mysql-db=sbtest \ - --mysql-host=$tidb_host \ - --mysql-port=$tidb_port \ - --mysql-user=root \ - --mysql-password=password \ - prepare --tables=16 --table-size=10000000 -``` - -执行测试命令: - -{{< copyable "shell-regular" >}} - -```sh -sysbench $testname \ - --threads=$threads \ - --time=300 \ - --report-interval=15 \ - --rand-type=uniform \ - --rand-seed=$RANDOM \ - --db-driver=mysql \ - --mysql-db=sbtest \ - --mysql-host=$tidb_host \ - --mysql-port=$tidb_port \ - --mysql-user=root \ - --mysql-password=password \ - run --tables=16 --table-size=10000000 -``` - -### TiDB 版本信息 - -### v3.0.0 - -| 组件 | GitHash | -| :--- | :---------------------------------------- | -| TiDB | `8efbe62313e2c1c42fd76d35c6f020087eef22c2` | -| TiKV | `a467f410d235fa9c5b3c355e3b620f81d3ac0e0c` | -| PD | `70aaa5eee830e21068f1ba2d4c9bae59153e5ca3` | - -### v2.1.13 - -| 组件 | GitHash | -| :--- | :---------------------------------------- | -| TiDB | `6b5b1a6802f9b8f5a22d8aab24ac80729331e1bc` | -| TiKV | `b3cf3c8d642534ea6fa93d475a46da285cc6acbf` | -| PD | `886362ebfb26ef0834935afc57bcee8a39c88e54` | - -### TiDB 参数配置 - -2.1 和 3.0 中开启 prepared plan cache (出于优化考虑,2.1 的 point select 与 read write 并未开启): - -```toml -[prepared-plan-cache] -enabled = true -``` - -并设置全局变量: - -{{< copyable "sql" >}} - -```sql -set global tidb_hashagg_final_concurrency=1; -set global tidb_hashagg_partial_concurrency=1; -set global tidb_disable_txn_auto_retry=0; -``` - -此外 3.0 还做了如下配置: - -```toml -[tikv-client] -max-batch-wait-time = 2000000 -``` - -### TiKV 参数配置 - -2.1 和 3.0 使用如下配置: - -```toml -log-level = "error" -[readpool.storage] -normal-concurrency = 10 -[server] -grpc-concurrency = 6 -[rocksdb.defaultcf] -block-cache-size = "14GB" -[rocksdb.writecf] -block-cache-size = "8GB" -[rocksdb.lockcf] -block-cache-size = "1GB" -``` - -3.0 还做了如下配置: - -```toml -[raftstore] -apply-pool-size = 3 -store-pool-size = 3 -``` - -### 集群拓扑 - -| 机器 IP | 部署实例 | -| :-------------------------------------- | :----------| -| 172.31.8.8 | 3 * Sysbench | -| 172.31.7.80, 172.31.5.163, 172.31.11.123 | PD | -| 172.31.4.172, 172.31.1.155, 172.31.9.210 | TiKV | -| 172.31.7.80, 172.31.5.163, 172.31.11.123 | TiDB | - -## 测试结果 - -### Point Select 测试 - -**v2.1** - -| Threads | QPS | 95% latency(ms) | -| :------- | :-------- | :------------- | -| 150 | 240304.06 | 1.61 | -| 300 | 276635.75 | 2.97 | -| 600 | 307838.06 | 5.18 | -| 900 | 323667.93 | 7.30 | -| 1200 | 330925.73 | 9.39 | -| 1500 | 336250.38 | 11.65 | - - - -**v3.0** - -| Threads | QPS | 95% latency(ms) | -| :------- | :-------- | :-------------- | -| 150 | 334219.04 | 0.64 | -| 300 | 456444.86 | 1.10 | -| 600 | 512177.48 | 2.11 | -| 900 | 525945.13 | 3.13 | -| 1200 | 534577.36 | 4.18 | -| 1500 | 533944.64 | 5.28 | - -![point select](/media/sysbench_v4_point_select.png) - -### Update Non-Index 测试 - -**v2.1** - -| threads | qps | 95% latency(ms) | -| ------- | -------: | --------------: | -| 150 | 21785.37 | 8.58 | -| 300 | 28979.27 | 13.70 | -| 600 | 34629.72 | 24.83 | -| 900 | 36410.06 | 43.39 | -| 1200 | 37174.15 | 62.19 | -| 1500 | 37408.88 | 87.56 | - -**v3.0** - -| threads | qps | 95% latency(ms) | -| ------- | -------: | --------------: | -| 150 | 28045.75 | 6.67 | -| 300 | 39237.77 | 9.91 | -| 600 | 49536.56 | 16.71 | -| 900 | 55963.73 | 22.69 | -| 1200 | 59904.02 | 29.72 | -| 1500 | 62247.95 | 42.61 | - -![update non-index](/media/sysbench_v4_update_non_index.png) - -### Update Index 测试 - -**v2.1** - -| Threads | QPS | 95% latency(ms) | -| :------- | :------- | :-------------- | -| 150 | 14378.24 | 13.22 | -| 300 | 16916.43 | 24.38 | -| 600 | 17636.11 | 57.87 | -| 900 | 17740.92 | 95.81 | -| 1200 | 17929.24 | 130.13 | -| 1500 | 18012.80 | 161.51 | - -**v3.0** - -| Threads | QPS | 95% latency(ms) | -| :------- | :------- | :-------------| -| 150 | 19047.32 | 10.09 | -| 300 | 24467.64 | 16.71 | -| 600 | 28882.66 | 31.94 | -| 900 | 30298.41 | 57.87 | -| 1200 | 30419.40 | 92.42 | -| 1500 | 30643.55 | 125.52 | - -![update index](/media/sysbench_v4_update_index.png) - -### Read Write 测试 - -**v2.1** - -| Threads | QPS | 95% latency(ms) | -| :------- | :-------- | :-------------- | -| 150 | 85140.60 | 44.98 | -| 300 | 96773.01 | 82.96 | -| 600 | 105139.81 | 153.02 | -| 900 | 110041.83 | 215.44 | -| 1200 | 113242.70 | 277.21 | -| 1500 | 114542.19 | 337.94 | - - - -**v3.0** - -| Threads | QPS | 95% latency(ms) | -| :------- | :-------- | :-------------- | -| 150 | 105692.08 | 35.59 | -| 300 | 129769.69 | 58.92 | -| 600 | 141430.86 | 114.72 | -| 900 | 144371.76 | 170.48 | -| 1200 | 143344.37 | 223.34 | -| 1500 | 144567.91 | 277.21 | - -![read write](/media/sysbench_v4_read_write.png) diff --git a/benchmark/sysbench.md b/benchmark/sysbench.md deleted file mode 100644 index 41c6f79e10e0..000000000000 --- a/benchmark/sysbench.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: TiDB Sysbench 性能测试报告 - v1.0.0 -category: benchmark -draft: true ---- - -# TiDB Sysbench 性能测试报告 - v1.0.0 - -## 测试目的 - -测试 TiDB 在 OLTP 场景下的性能以及水平扩展能力。 - -> **注意:** -> -> 不同的测试环境可能使测试结果发生改变。 - -## 测试版本、时间、地点 - -TiDB 版本:v1.0.0 -时间:2017 年 10 月 20 日 -地点:北京 - -## 测试环境 - -IDC 机器 - -| 类别 | 名称 | -| :--------: | :---------: | -| OS | linux (CentOS 7.3.1611) | -| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | -| RAM | 128GB | -| DISK | 1.5T SSD \* 2 + Optane SSD \* 1 | - -Sysbench 版本: 1.0.6 - -测试脚本: - -## 测试方案 - -### 场景一:sysbench 标准性能测试 - -测试表结构 - -``` -CREATE TABLE `sbtest` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `k` int(10) unsigned NOT NULL DEFAULT '0', - `c` char(120) NOT NULL DEFAULT '', - `pad` char(60) NOT NULL DEFAULT '', - PRIMARY KEY (`id`), - KEY `k_1` (`k`) -) ENGINE=InnoDB -``` - -部署方案以及配置参数 - -``` -// TiDB 部署方案 -172.16.20.4 4*tikv 1*tidb 1*sysbench -172.16.20.6 4*tikv 1*tidb 1*sysbench -172.16.20.7 4*tikv 1*tidb 1*sysbench -172.16.10.8 1*tidb 1*pd 1*sysbench - -// 每个物理节点有三块盘: -data3: 2 tikv (Optane SSD) -data2: 1 tikv -data1: 1 tikv - -// TiKV 参数配置 -sync-log = false -grpc-concurrency = 8 -grpc-raft-conn-num = 24 -[defaultcf] -block-cache-size = "12GB" -[writecf] -block-cache-size = "5GB" -[raftdb.defaultcf] -block-cache-size = "2GB" - -// Mysql 部署方案 -// 分别使用半同步复制和异步复制,部署两副本 -172.16.20.4 master -172.16.20.6 slave -172.16.20.7 slave -172.16.10.8 1*sysbench -Mysql version: 5.6.37 - -// Mysql 参数配置 -thread_cache_size = 64 -innodb_buffer_pool_size = 64G -innodb_file_per_table = 1 -innodb_flush_log_at_trx_commit = 0 -datadir = /data3/mysql -max_connections = 2000 -``` - -* 标准 oltp 测试 - -| - | table count | table size | sysbench threads | tps | qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| TiDB | 32 | 100 万 | 64 * 4 | 3834 | 76692 | 67.04 ms / 110.88 ms | -| TiDB | 32 | 100 万 | 128 * 4 | 4172 | 83459 | 124.00 ms / 194.21 ms | -| TiDB | 32 | 100 万 | 256 * 4 | 4577 | 91547 | 228.36 ms / 334.02 ms | -| TiDB | 32 | 500 万 | 256 * 4 | 4032 | 80657 | 256.62 ms / 443.88 ms | -| TiDB | 32 | 1000 万 | 256 * 4 | 3811 | 76233 | 269.46 ms / 505.20 ms | -| Mysql | 32 | 100 万 | 64 | 2392 | 47845 | 26.75 ms / 73.13 ms | -| Mysql | 32 | 100 万 | 128 | 2493 | 49874 | 51.32 ms / 173.58 ms | -| Mysql | 32 | 100 万 | 256 | 2561 | 51221 | 99.95 ms / 287.38 ms | -| Mysql | 32 | 500 万 | 256 | 1902 | 38045 | 134.56 ms / 363.18 ms | -| Mysql | 32 | 1000 万 | 256 | 1770 | 35416 | 144.55 ms / 383.33 ms | - -![sysbench-01](/media/sysbench-01.png) - -![sysbench-02](/media/sysbench-02.png) - -* 标准 select 测试 - -| - | table count | table size | sysbench threads |qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | -| TiDB | 32 | 100 万 | 64 * 4 | 160299 | 1.61ms / 50.06 ms | -| TiDB | 32 | 100 万 | 128 * 4 | 183347 | 2.85 ms / 8.66 ms | -| TiDB | 32 | 100 万 | 256 * 4 | 196515 | 5.42 ms / 14.43 ms | -| TiDB | 32 | 500 万 | 256 * 4 | 187628 | 5.66 ms / 15.04 ms | -| TiDB | 32 | 1000 万 | 256 * 4 | 187440 | 5.65 ms / 15.37 ms | -| Mysql | 32 | 100 万 | 64 | 359572 | 0.18 ms / 0.45 ms | -| Mysql | 32 | 100 万 | 128 | 410426 |0.31 ms / 0.74 ms | -| Mysql | 32 | 100 万 | 256 | 396867 | 0.64 ms / 1.58 ms | -| Mysql | 32 | 500 万 | 256 | 386866 | 0.66 ms / 1.64 ms | -| Mysql | 32 | 1000 万 | 256 | 388273 | 0.66 ms / 1.64 ms | - -![sysbench-03](/media/sysbench-03.png) - -![sysbench-04](/media/sysbench-04.png) - -* 标准 insert 测试 - -| - | table count | table size | sysbench threads | qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | -| TiDB | 32 | 100 万 | 64 * 4 | 25308 | 10.12 ms / 25.40 ms | -| TiDB | 32 | 100 万 | 128 * 4 | 28773 | 17.80 ms / 44.58 ms | -| TiDB | 32 | 100 万 | 256 * 4 | 32641 | 31.38 ms / 73.47 ms | -| TiDB | 32 | 500 万 | 256 * 4 | 30430 | 33.65 ms / 79.32 ms | -| TiDB | 32 | 1000 万 | 256 * 4 | 28925 | 35.41 ms / 78.96 ms | -| Mysql | 32 | 100 万 | 64 | 14806 | 4.32 ms / 9.39 ms | -| Mysql | 32 | 100 万 | 128 | 14884 | 8.58 ms / 21.11 ms | -| Mysql | 32 | 100 万 | 256 | 14508 | 17.64 ms / 44.98 ms | -| Mysql | 32 | 500 万 | 256 | 10593 | 24.16 ms / 82.96 ms | -| Mysql | 32 | 1000 万 | 256 | 9813 | 26.08 ms / 94.10 ms | - -![sysbench-05](/media/sysbench-05.png) - -![sysbench-06](/media/sysbench-06.png) - -### 场景二:TiDB 水平扩展能力测试 - -部署方案以及配置参数 - -``` -// TiDB 部署方案 -172.16.20.3 4*tikv -172.16.10.2 1*tidb 1*pd 1*sysbench - -每个物理节点有三块盘: -data3: 2 tikv (Optane SSD) -data2: 1 tikv -data1: 1 tikv - -// TiKV 参数配置 -sync-log = false -grpc-concurrency = 8 -grpc-raft-conn-num = 24 -[defaultcf] -block-cache-size = "12GB" -[writecf] -block-cache-size = "5GB" -[raftdb.defaultcf] -block-cache-size = "2GB" -``` - -* 标准 oltp 测试 - -| - | table count | table size | sysbench threads | tps | qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| 1 物理节点 TiDB | 32 | 100 万 | 256 * 1 | 2495 | 49902 | 102.42 ms / 125.52 ms | -| 2 物理节点 TiDB | 32 | 100 万 | 256 * 2 | 5007 | 100153 | 102.23 ms / 125.52 ms | -| 4 物理节点 TiDB | 32 | 100 万 | 256 * 4 | 8984 | 179692 | 114.96 ms / 176.73 ms | -| 6 物理节点 TiDB | 32 | 500 万 | 256 * 6 | 12953 | 259072 | 117.80 ms / 200.47 ms | - -![sysbench-07](/media/sysbench-07.png) - -* 标准 select 测试 - -| - | table count | table size | sysbench threads | qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | -| 1 物理节点 TiDB | 32 | 100 万 | 256 * 1 | 71841 | 3.56 ms / 8.74 ms | -| 2 物理节点 TiDB | 32 | 100 万 | 256 * 2 | 146615 | 3.49 ms / 8.74 ms | -| 4 物理节点 TiDB | 32 | 100 万 | 256 * 4 | 289933 | 3.53 ms / 8.74 ms | -| 6 物理节点 TiDB | 32 | 500 万 | 256 * 6 | 435313 | 3.55 ms / 9.17 ms | - -![sysbench-08](/media/sysbench-08.png) - -* 标准 insert 测试 - -| - | table count | table size | sysbench threads | qps | latency(avg / .95) | -| :---: | :---: | :---: | :---: | :---: | :---: | -| 3 物理节点 TiKV | 32 | 100 万 |256 * 3 | 40547 | 18.93 ms / 38.25 ms | -| 5 物理节点 TiKV | 32 | 100 万 | 256 * 3 | 60689 | 37.96 ms / 29.9 ms | -| 7 物理节点 TiKV | 32 | 100 万 | 256 * 3 | 80087 | 9.62 ms / 21.37 ms | - -![sysbench-09](/media/sysbench-09.png) diff --git a/benchmark/tpcc.md b/benchmark/tpcc.md deleted file mode 100644 index 8cf3926501a2..000000000000 --- a/benchmark/tpcc.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: TiDB TPC-C 性能对比测试报告 - v3.0 对比 v2.1 -category: benchmark ---- - -# TiDB TPC-C 性能对比测试报告 - v3.0 对比 v2.1 - -## 测试目的 - -对比 TiDB 3.0 版本和 2.1 版本的 TPC-C 性能表现。 - -## 测试版本、时间、地点 - -TiDB 版本:v3.0.0 vs. v2.1.13 - -时间:2019 年 6 月 - -地点:北京 - -## 测试环境 - -IDC 机器: - -| 类别 | 名称 | -| :-: | :-: | -| OS | Linux (CentOS 7.3.1611) | -| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | -| RAM | 128GB | -| DISK | 1.5TB SSD \* 2 | - -本文使用开源的 BenchmarkSQL 5.0 作为 TPC-C 测试工具并添加对 MySQL 协议支持, 可以通过以下命令下载测试程序: - -{{< copyable "shell-regular" >}} - -```shell -git clone -b 5.0-mysql-support-opt https://github.com/pingcap/benchmarksql.git -``` - -## 测试方案 - -使用 BenchmarkSQL 向集群导入 **1000 warehouse** 的数据。通过 HAProxy 代理,分别以递增并发数向集群发送请求,单次并发测试时间 10 分钟。 - -### TiDB 版本信息 - -### v3.0.0 - -| 组件 | GitHash | -| :-: | :-: | -| TiDB | 46c38e15eba43346fb3001280c5034385171ee20 | -| TiKV | a467f410d235fa9c5b3c355e3b620f81d3ac0e0c | -| PD | 70aaa5eee830e21068f1ba2d4c9bae59153e5ca3 | - -### v2.1.13 - -| 组件 | GitHash | -| :-: | :-: | -| TiDB | 6b5b1a6802f9b8f5a22d8aab24ac80729331e1bc | -| TiKV | b3cf3c8d642534ea6fa93d475a46da285cc6acbf | -| PD | 886362ebfb26ef0834935afc57bcee8a39c88e54 | - -### TiDB 参数配置 - -```toml -[log] -level = "error" -[performance] -max-procs = 20 -[prepared_plan_cache] -enabled = true -``` - -### TiKV 参数配置 - -默认配置 - -### 集群拓扑 - -| 机器 IP | 部署实例 | -| :-: | :-: | -| 172.16.4.75 | 2\*TiDB 2\*TiKV 1\*pd | -| 172.16.4.76 | 2\*TiDB 2\*TiKV 1\*pd | -| 172.16.4.77 | 2\*TiDB 2\*TiKV 1\*pd | - -## 测试结果 - -| 版本 | threads | tpmC | -| :-: | :-: | :-: | -| v3.0 | 128 | 44068.55 | -| v3.0 | 256 | 47094.06 | -| v3.0 | 512 | 48808.65 | -| v2.1 | 128 | 10641.71 | -| v2.1 | 256 | 10861.62 | -| v2.1 | 512 | 10965.39 | - -![tpcc](/media/tpcc-2.1-3.0.png) - -v3.0 比 v2.1 在 TPC-C 性能上,**提升了 450%**。 diff --git a/benchmark/tpch-v2.md b/benchmark/tpch-v2.md deleted file mode 100644 index 688a9d0a7e26..000000000000 --- a/benchmark/tpch-v2.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: TiDB TPC-H 50G 性能测试报告 -category: benchmark ---- - -# TiDB TPC-H 50G 性能测试报告 - -## 测试目的 - -测试 TiDB 在 OLAP 场景下 2.0 和 2.1 版本的性能对比。 - -> **注意:** -> -> 不同的测试环境可能使测试结果发生改变。 - -## 测试环境 - -### 测试机器信息 - -1. 系统信息 - - | 机器 IP | 操作系统 | 内核版本 | 文件系统类型 | - |--------------|------------------------|------------------------------|--------------| - | 10.0.1.4 | CentOS 7.5.1804 64bit | 3.10.0-862.3.3.el7.x86\_64 | ext4 | - | 10.0.1.5 | CentOS 7.5.1804 64bit | 3.10.0-862.3.3.el7.x86\_64 | ext4 | - | 10.0.1.6 | CentOS 7.5.1804 64bit | 3.10.0-862.3.3.el7.x86\_64 | ext4 | - | 10.0.1.7 | CentOS 7.5.1804 64bit | 3.10.0-862.3.3.el7.x86\_64 | ext4 | - | 10.0.1.8 | CentOS 7.5.1804 64bit | 3.10.0-862.3.3.el7.x86\_64 | ext4 | - | 10.0.1.9 | CentOS 7.5.1804 64bit | 3.10.0-862.3.3.el7.x86\_64 | ext4 | - -2. 硬件信息 - - | 类别 | 10.0.1.4 | 10.0.1.5, 10.0.1.6, 10.0.1.7, 10.0.1.8, 10.0.1.9 | - |------------|------------------------------------------------------|------------------------------------------------------| - | CPU | 16 vCPUs, Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz | 8 vCPUs, Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz | - | 内存 | 110G | 55G | - | 磁盘 | 221G SSD | 111G SSD | - | 网卡 | 万兆网卡, 10000Mb/s | 万兆网卡, 10000Mb/s | - -### TPC-H - -[tidb-bench/tpch](https://github.com/pingcap/tidb-bench/tree/master/tpch) - -### 集群拓扑 - -| 机器 IP | 部署的实例 | -|----------|------------| -| 10.0.1.5 | TiKV \* 1 | -| 10.0.1.6 | TiKV \* 1 | -| 10.0.1.7 | TiKV \* 1 | -| 10.0.1.8 | TiKV \* 1 | -| 10.0.1.9 | TiKV \* 1 | -| 10.0.1.4 | PD \* 1 | -| 10.0.1.4 | TiDB \* 1 | - -### TiDB 版本信息 - -TiDB 2.0: - -| 组件名 | 版本号 | commit hash | -|--------|-------------|--------------------------------------------| -| TiDB | v2.0.7 | 29ec059cb3b7d14b6f52c2f219f94a89570162bc | -| TiKV | v2.0.7 | d0b8cd7c7f62f06e7ef456837bd32a47da1ca4cd | -| PD | v2.0.5 | b64716707b7279a4ae822be767085ff17b5f3fea | - -TiDB 2.1: - -| 组件名 | 版本号 | commit hash | -|--------|-------------|--------------------------------------------| -| TiDB | v2.1.0-rc.2 | 16864f95b47f859ed6104555ccff0387abdc2429 | -| TiKV | v2.1.0-rc.2 | 8458ce53ebbd434c48baac6373fe0f0a43a54005 | -| PD | v2.1.0-rc.2 | 55db505e8f35e8ab4e00efd202beb27a8ecc40fb | - -## 测试结果 - -| Query ID | TiDB 2.0 | TiDB 2.1 | -|-----------|----------------|----------------| -| 1 | 121.550595999s | 91.4755480289s | -| 2 | 53.0638680458s | 23.1186130047s | -| 3 | 75.7236940861s | 61.790802002s | -| 4 | 30.2647120953s | 26.3483440876s | -| 6 | 51.4850790501s | 34.6432199478s | -| 7 | 216.787364006s | 94.9856910706s | -| 8 | 188.717588902s | 181.852752209s | -| 9 | 546.438174009s | 414.462754965s | -| 10 | 109.978317022s | 37.0369961262s | -| 11 | 42.9398438931s | 37.6951580048s | -| 12 | 60.455039978s | 40.2236878872s | -| 13 | 230.278712988s | 70.2887151241s | -| 14 | 61.2673521042s | 35.8372960091s | -| 16 | 30.2539310455s | 18.5897550583s | -| 17 | 3200.70173788s | 263.095014811s | -| 18 | 1035.59847498s | 296.360667944s | -| 19 | 54.3732938766s | 40.4523630142s | -| 20 | 105.094577074s | 53.2429068089s | -| 21 | 389.883709908s | 361.034544945s | -| 22 | 64.0494630337s | 65.7153418064s | - -![TPC-H Query Result](/media/tpch-query-result-v2.png) - -说明: - -- 图中橙色为 Release 2.1,蓝色为 Release 2.0,纵坐标是 Query 的处理时间,越低越好 -- Query 15 因为 2.1 和 2.0 都还未支持视图,所以未列出结果 -- Query 5 因为 Join Order 问题长时间未跑出结果来,所以未列出结果 diff --git a/benchmark/tpch.md b/benchmark/tpch.md deleted file mode 100644 index 3852e4774adc..000000000000 --- a/benchmark/tpch.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: TiDB TPC-H 50G 性能测试报告 -category: benchmark ---- - -# TiDB TPC-H 50G 性能测试报告 - -## 测试目的 - -测试 TiDB 在 OLAP 场景下 1.0 和 2.0 版本的性能对比。 - -> **注意:** -> -> 不同的测试环境可能使测试结果发生改变。 - -## 测试环境 - -### 测试机器信息 - -1. 系统信息 - - | 机器 IP | 操作系统 | 内核版本 | 文件系统类型 | - |--------------|------------------------|------------------------------|--------------| - | 172.16.31.2 | Ubuntu 17.10 64bit | 4.13.0-16-generic | ext4 | - | 172.16.31.3 | Ubuntu 17.10 64bit | 4.13.0-16-generic | ext4 | - | 172.16.31.4 | Ubuntu 17.10 64bit | 4.13.0-16-generic | ext4 | - | 172.16.31.6 | CentOS 7.4.1708 64bit | 3.10.0-693.11.6.el7.x86\_64 | ext4 | - | 172.16.31.8 | CentOS 7.4.1708 64bit | 3.10.0-693.11.6.el7.x86\_64 | ext4 | - | 172.16.31.10 | CentOS 7.4.1708 64bit | 3.10.0-693.11.6.el7.x86\_64 | ext4 | - -2. 硬件信息 - - | 类别 | 名称 | - |------------|------------------------------------------------------| - | CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | - | 内存 | 128GB, 8条16GB RDIMM, 2400MT/s, 双列, x8 带宽 | - | 磁盘 | 2 块 Intel P4500 系列 4T SSD 硬盘 | - | 网卡 | 万兆网卡 | - -### TPC-H - -[tidb-bench/tpch](https://github.com/pingcap/tidb-bench/tree/master/tpch) - -### 集群拓扑 - -| 机器 IP | 部署的实例 | -|--------------|------------| -| 172.16.31.2 | TiKV \* 2 | -| 172.16.31.3 | TiKV \* 2 | -| 172.16.31.6 | TiKV \* 2 | -| 172.16.31.8 | TiKV \* 2 | -| 172.16.31.10 | TiKV \* 2 | -| 172.16.31.10 | PD \* 1 | -| 172.16.31.4 | TiDB \* 1 | - -### TiDB 版本信息 - -TiDB 1.0: - -| 组件名 | 版本号 | commit hash | -|--------|-------------|--------------------------------------------| -| TiDB | v1.0.9 | 4c7ee3580cd0a69319b2c0c08abdc59900df7344 | -| TiKV | v1.0.8 | 2bb923a4cd23dbf68f0d16169fd526dc5c1a9f4a | -| PD | v1.0.8 | 137fa734472a76c509fbfd9cb9bc6d0dc804a3b7 | - -TiDB 2.0: - -| 组件名 | 版本号 | commit hash | -|--------|-------------|--------------------------------------------| -| TiDB | v2.0.0-rc.6 | 82d35f1b7f9047c478f4e1e82aa0002abc8107e7 | -| TiKV | v2.0.0-rc.6 | 8bd5c54966c6ef42578a27519bce4915c5b0c81f | -| PD | v2.0.0-rc.6 | 9b824d288126173a61ce7d51a71fc4cb12360201 | - -## 测试结果 - -| Query ID | TiDB 2.0 | TiDB 1.0 | -|-----------|--------------------|------------------| -| 1 | 33.915s | 215.305s | -| 2 | 25.575s | NaN | -| 3 | 59.631s | 196.003s | -| 4 | 30.234s | 249.919s | -| 5 | 31.666s | OOM | -| 6 | 13.111s | 118.709s | -| 7 | 31.710s | OOM | -| 8 | 31.734s | 800.546s | -| 9 | 34.211s | 630.639s | -| 10 | 30.774s | 133.547s | -| 11 | 27.692s | 78.026s | -| 12 | 27.962s | 124.641s | -| 13 | 27.676s | 174.695s | -| 14 | 19.676s | 110.602s | -| 15 | View Required | View Required | -| 16 | 24.890s | 40.529s | -| 17 | 245.796s | NaN | -| 18 | 91.256s | OOM | -| 19 | 37.615s | NaN | -| 20 | 44.167s | 212.201s | -| 21 | 31.466s | OOM | -| 22 | 31.539s | 125.471s | - -![TPC-H Query Result](/media/tpch-query-result.png) - -说明: - -- 图中橙色为 Release 1.0,蓝色为 Release 2.0,纵坐标是 Query 的处理时间,越低越好 -- Query 15 因为 1.0 和 2.0 都还未支持视图,所以结果标记为 "View Required" -- Query 2, 17, 19 因为 TiDB 1.0 长时间未跑出结果,所以结果标记为 "Nan" -- Query 5, 7, 18, 21 因为 TiDB 1.0 在跑的过程中内存占用过多被 oom-killer 杀死,所以结果标记为 "OOM" diff --git a/benchmark/v3.0-performance-benchmarking-with-sysbench.md b/benchmark/v3.0-performance-benchmarking-with-sysbench.md new file mode 100644 index 000000000000..a46c0c6392de --- /dev/null +++ b/benchmark/v3.0-performance-benchmarking-with-sysbench.md @@ -0,0 +1,279 @@ +--- +title: TiDB Sysbench 性能对比测试报告 - v3.0 对比 v2.1 +category: benchmark +aliases: ['/docs-cn/stable/benchmark/sysbench-v4/'] +--- + +# TiDB Sysbench 性能对比测试报告 - v3.0 对比 v2.1 + +## 测试目的 + +对比 TiDB 3.0 版本和 2.1 版本在 OLTP 场景下的性能。 + +## 测试版本、时间、地点 + +TiDB 版本:v3.0.0 vs. v2.1.13 + +时间:2019 年 6 月 + +地点:北京 + +## 测试环境 + +测试在 AWS EC2 上进行,使用 CentOS-7.6.1810-Nitro (ami-028946f4cffc8b916) 镜像,各组件实例类型如下: + +| 组件 | 实例类型 | +| :--- | :--------- | +| PD | r5d.xlarge | +| TiKV | c5d.4xlarge | +| TiDB | c5.4xlarge | + +Sysbench 版本:1.0.17 + +## 测试方案 + +使用 Sysbench 向集群导入 **16 张表,每张数据 1000 万**。起 3 个 sysbench 分别向 3 个 TiDB 发压,请求并发数逐步增加,单次测试时间 5 分钟。 + +准备数据命令: + +{{< copyable "shell-regular" >}} + +```sh +sysbench oltp_common \ + --threads=16 \ + --rand-type=uniform \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=$tidb_host \ + --mysql-port=$tidb_port \ + --mysql-user=root \ + --mysql-password=password \ + prepare --tables=16 --table-size=10000000 +``` + +执行测试命令: + +{{< copyable "shell-regular" >}} + +```sh +sysbench $testname \ + --threads=$threads \ + --time=300 \ + --report-interval=15 \ + --rand-type=uniform \ + --rand-seed=$RANDOM \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=$tidb_host \ + --mysql-port=$tidb_port \ + --mysql-user=root \ + --mysql-password=password \ + run --tables=16 --table-size=10000000 +``` + +### TiDB 版本信息 + +### v3.0.0 + +| 组件 | GitHash | +| :--- | :---------------------------------------- | +| TiDB | `8efbe62313e2c1c42fd76d35c6f020087eef22c2` | +| TiKV | `a467f410d235fa9c5b3c355e3b620f81d3ac0e0c` | +| PD | `70aaa5eee830e21068f1ba2d4c9bae59153e5ca3` | + +### v2.1.13 + +| 组件 | GitHash | +| :--- | :---------------------------------------- | +| TiDB | `6b5b1a6802f9b8f5a22d8aab24ac80729331e1bc` | +| TiKV | `b3cf3c8d642534ea6fa93d475a46da285cc6acbf` | +| PD | `886362ebfb26ef0834935afc57bcee8a39c88e54` | + +### TiDB 参数配置 + +2.1 和 3.0 中开启 prepared plan cache (出于优化考虑,2.1 的 point select 与 read write 并未开启): + +```toml +[prepared-plan-cache] +enabled = true +``` + +并设置全局变量: + +{{< copyable "sql" >}} + +```sql +set global tidb_hashagg_final_concurrency=1; +set global tidb_hashagg_partial_concurrency=1; +set global tidb_disable_txn_auto_retry=0; +``` + +此外 3.0 还做了如下配置: + +```toml +[tikv-client] +max-batch-wait-time = 2000000 +``` + +### TiKV 参数配置 + +2.1 和 3.0 使用如下配置: + +```toml +log-level = "error" +[readpool.storage] +normal-concurrency = 10 +[server] +grpc-concurrency = 6 +[rocksdb.defaultcf] +block-cache-size = "14GB" +[rocksdb.writecf] +block-cache-size = "8GB" +[rocksdb.lockcf] +block-cache-size = "1GB" +``` + +3.0 还做了如下配置: + +```toml +[raftstore] +apply-pool-size = 3 +store-pool-size = 3 +``` + +### 集群拓扑 + +| 机器 IP | 部署实例 | +| :-------------------------------------- | :----------| +| 172.31.8.8 | 3 * Sysbench | +| 172.31.7.80, 172.31.5.163, 172.31.11.123 | PD | +| 172.31.4.172, 172.31.1.155, 172.31.9.210 | TiKV | +| 172.31.7.80, 172.31.5.163, 172.31.11.123 | TiDB | + +## 测试结果 + +### Point Select 测试 + +**v2.1** + +| Threads | QPS | 95% latency(ms) | +| :------- | :-------- | :------------- | +| 150 | 240304.06 | 1.61 | +| 300 | 276635.75 | 2.97 | +| 600 | 307838.06 | 5.18 | +| 900 | 323667.93 | 7.30 | +| 1200 | 330925.73 | 9.39 | +| 1500 | 336250.38 | 11.65 | + + + +**v3.0** + +| Threads | QPS | 95% latency(ms) | +| :------- | :-------- | :-------------- | +| 150 | 334219.04 | 0.64 | +| 300 | 456444.86 | 1.10 | +| 600 | 512177.48 | 2.11 | +| 900 | 525945.13 | 3.13 | +| 1200 | 534577.36 | 4.18 | +| 1500 | 533944.64 | 5.28 | + +![point select](/media/sysbench_v4_point_select.png) + +### Update Non-Index 测试 + +**v2.1** + +| threads | qps | 95% latency(ms) | +| ------- | -------: | --------------: | +| 150 | 21785.37 | 8.58 | +| 300 | 28979.27 | 13.70 | +| 600 | 34629.72 | 24.83 | +| 900 | 36410.06 | 43.39 | +| 1200 | 37174.15 | 62.19 | +| 1500 | 37408.88 | 87.56 | + +**v3.0** + +| threads | qps | 95% latency(ms) | +| ------- | -------: | --------------: | +| 150 | 28045.75 | 6.67 | +| 300 | 39237.77 | 9.91 | +| 600 | 49536.56 | 16.71 | +| 900 | 55963.73 | 22.69 | +| 1200 | 59904.02 | 29.72 | +| 1500 | 62247.95 | 42.61 | + +![update non-index](/media/sysbench_v4_update_non_index.png) + +### Update Index 测试 + +**v2.1** + +| Threads | QPS | 95% latency(ms) | +| :------- | :------- | :-------------- | +| 150 | 14378.24 | 13.22 | +| 300 | 16916.43 | 24.38 | +| 600 | 17636.11 | 57.87 | +| 900 | 17740.92 | 95.81 | +| 1200 | 17929.24 | 130.13 | +| 1500 | 18012.80 | 161.51 | + +**v3.0** + +| Threads | QPS | 95% latency(ms) | +| :------- | :------- | :-------------| +| 150 | 19047.32 | 10.09 | +| 300 | 24467.64 | 16.71 | +| 600 | 28882.66 | 31.94 | +| 900 | 30298.41 | 57.87 | +| 1200 | 30419.40 | 92.42 | +| 1500 | 30643.55 | 125.52 | + +![update index](/media/sysbench_v4_update_index.png) + +### Read Write 测试 + +**v2.1** + +| Threads | QPS | 95% latency(ms) | +| :------- | :-------- | :-------------- | +| 150 | 85140.60 | 44.98 | +| 300 | 96773.01 | 82.96 | +| 600 | 105139.81 | 153.02 | +| 900 | 110041.83 | 215.44 | +| 1200 | 113242.70 | 277.21 | +| 1500 | 114542.19 | 337.94 | + + + +**v3.0** + +| Threads | QPS | 95% latency(ms) | +| :------- | :-------- | :-------------- | +| 150 | 105692.08 | 35.59 | +| 300 | 129769.69 | 58.92 | +| 600 | 141430.86 | 114.72 | +| 900 | 144371.76 | 170.48 | +| 1200 | 143344.37 | 223.34 | +| 1500 | 144567.91 | 277.21 | + +![read write](/media/sysbench_v4_read_write.png) diff --git a/benchmark/v3.0-performance-benchmarking-with-tpcc.md b/benchmark/v3.0-performance-benchmarking-with-tpcc.md new file mode 100644 index 000000000000..52c055a6081a --- /dev/null +++ b/benchmark/v3.0-performance-benchmarking-with-tpcc.md @@ -0,0 +1,98 @@ +--- +title: TiDB TPC-C 性能对比测试报告 - v3.0 对比 v2.1 +category: benchmark +aliases: ['/docs-cn/stable/benchmark/tpcc/'] +--- + +# TiDB TPC-C 性能对比测试报告 - v3.0 对比 v2.1 + +## 测试目的 + +对比 TiDB 3.0 版本和 2.1 版本的 TPC-C 性能表现。 + +## 测试版本、时间、地点 + +TiDB 版本:v3.0.0 vs. v2.1.13 + +时间:2019 年 6 月 + +地点:北京 + +## 测试环境 + +IDC 机器: + +| 类别 | 名称 | +| :-: | :-: | +| OS | Linux (CentOS 7.3.1611) | +| CPU | 40 vCPUs, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz | +| RAM | 128GB | +| DISK | 1.5TB SSD \* 2 | + +本文使用开源的 BenchmarkSQL 5.0 作为 TPC-C 测试工具并添加对 MySQL 协议支持, 可以通过以下命令下载测试程序: + +{{< copyable "shell-regular" >}} + +```shell +git clone -b 5.0-mysql-support-opt https://github.com/pingcap/benchmarksql.git +``` + +## 测试方案 + +使用 BenchmarkSQL 向集群导入 **1000 warehouse** 的数据。通过 HAProxy 代理,分别以递增并发数向集群发送请求,单次并发测试时间 10 分钟。 + +### TiDB 版本信息 + +### v3.0.0 + +| 组件 | GitHash | +| :-: | :-: | +| TiDB | 46c38e15eba43346fb3001280c5034385171ee20 | +| TiKV | a467f410d235fa9c5b3c355e3b620f81d3ac0e0c | +| PD | 70aaa5eee830e21068f1ba2d4c9bae59153e5ca3 | + +### v2.1.13 + +| 组件 | GitHash | +| :-: | :-: | +| TiDB | 6b5b1a6802f9b8f5a22d8aab24ac80729331e1bc | +| TiKV | b3cf3c8d642534ea6fa93d475a46da285cc6acbf | +| PD | 886362ebfb26ef0834935afc57bcee8a39c88e54 | + +### TiDB 参数配置 + +```toml +[log] +level = "error" +[performance] +max-procs = 20 +[prepared_plan_cache] +enabled = true +``` + +### TiKV 参数配置 + +默认配置 + +### 集群拓扑 + +| 机器 IP | 部署实例 | +| :-: | :-: | +| 172.16.4.75 | 2\*TiDB 2\*TiKV 1\*pd | +| 172.16.4.76 | 2\*TiDB 2\*TiKV 1\*pd | +| 172.16.4.77 | 2\*TiDB 2\*TiKV 1\*pd | + +## 测试结果 + +| 版本 | threads | tpmC | +| :-: | :-: | :-: | +| v3.0 | 128 | 44068.55 | +| v3.0 | 256 | 47094.06 | +| v3.0 | 512 | 48808.65 | +| v2.1 | 128 | 10641.71 | +| v2.1 | 256 | 10861.62 | +| v2.1 | 512 | 10965.39 | + +![tpcc](/media/tpcc-2.1-3.0.png) + +v3.0 比 v2.1 在 TPC-C 性能上,**提升了 450%**。 diff --git a/benchmark/v4.0-performance-benchmarking-with-tpcc.md b/benchmark/v4.0-performance-benchmarking-with-tpcc.md new file mode 100644 index 000000000000..0abe46392c25 --- /dev/null +++ b/benchmark/v4.0-performance-benchmarking-with-tpcc.md @@ -0,0 +1,133 @@ +--- +title: TiDB TPC-C 性能对比测试报告 - v4.0 对比 v3.0 +category: benchmark +aliases: ['/docs-cn/stable/benchmark/tpcc-v2/'] +--- + +# TiDB TPC-C 性能对比测试报告 - v4.0 对比 v3.0 + +## 测试目的 + +测试对比 TiDB v4.0 和 v3.0 OLTP 场景下的性能。 + +## 测试环境 (AWS EC2) + +### 硬件配置 + +| 服务类型 | EC2 类型 | 实例数 | +|:----------|:----------|:----------| +| PD | m5.xlarge | 3 | +| TiKV | i3.4xlarge| 3 | +| TiDB | c5.4xlarge| 3 | +| Sysbench | m5.4xlarge| 1 | + +### 软件版本 + +| 服务类型 | 软件版本 | +|:----------|:-----------| +| PD | 3.0、4.0 | +| TiDB | 3.0、4.0 | +| TiKV | 3.0、4.0 | +| BenchmarkSQL | 无 | + +### 配置参数 + +#### TiDB v3.0 参数配置 + +{{< copyable "" >}} + +```yaml +log.level: "error" +performance.max-procs: 20 +prepared-plan-cache.enabled: true +tikv-client.max-batch-wait-time: 2000000 +``` + +#### TiKV v3.0 参数配置 + +{{< copyable "" >}} + +```yaml +storage.scheduler-worker-pool-size: 5 +raftstore.store-pool-size: 3 +raftstore.apply-pool-size: 3 +rocksdb.max-background-jobs: 3 +raftdb.max-background-jobs: 3 +raftdb.allow-concurrent-memtable-write: true +server.grpc-concurrency: 6 +readpool.storage.normal-concurrency: 10 +readpool.coprocessor.normal-concurrency: 5 +``` + +#### TiDB v4.0 参数配置 + +{{< copyable "" >}} + +```yaml +log.level: "error" +performance.max-procs: 20 +prepared-plan-cache.enabled: true +tikv-client.max-batch-wait-time: 2000000 +``` + +#### TiKV v4.0 参数配置 + +{{< copyable "" >}} + +```yaml +storage.scheduler-worker-pool-size: 5 +raftstore.store-pool-size: 3 +raftstore.apply-pool-size: 3 +rocksdb.max-background-jobs: 3 +raftdb.max-background-jobs: 3 +raftdb.allow-concurrent-memtable-write: true +server.request-batch-enable-cross-command: false +server.grpc-concurrency: 6 +readpool.unifiy-read-pool: true +readpool.unified.min-thread-count: 5 +readpool.unified.max-thread-count: 20 +readpool.storage.normal-concurrency: 10 +pessimistic-txn.pipelined: true +``` + +#### 全局变量配置 + +{{< copyable "sql" >}} + +```sql +set global tidb_hashagg_final_concurrency=1; +set global tidb_hashagg_partial_concurrency=1; +set global tidb_disable_txn_auto_retry=0; +``` + +### 测试方案 + +1. 通过 TiUP 部署 TiDB v4.0 和 v3.0。 + +2. 通过 BenchmarkSQL 导入 TPC-C 5000 Warehouse 数据。 + + 1. 编译 BenchmarkSQL: + + {{< copyable "bash" >}} + + ```bash + git clone https://github.com/pingcap/benchmarksql && cd benchmarksql && ant + ``` + + 2. 进入 `run` 目录,根据实际情况编辑 `props.mysql` 文件,调整 `conn`、`warehouses`、`loadWorkers`、`terminals`、`runMins` 配置项。 + + 3. 运行 `runSQL.sh ./props.mysql sql.mysql/tableCreates.sql` 命令。 + + 4. 运行 `runSQL.sh ./props.mysql sql.mysql/indexCreates.sql` 命令。 + + 5. 运行 MySQL client 并对每个表执行 `analyze table` 语句。 + +3. 运行 `runBenchmark.sh ./props.mysql` 命令。 + +4. 从结果中提取 New Order 的 tpmC 的数据。 + +### 测试结果 + +v4.0 比 v3.0 在 TPC-C 性能上**提升了 50%**。 + +![TPC-C](/media/tpcc_v4vsv3.png) diff --git a/benchmark/v4.0-performance-benchmarking-with-tpch.md b/benchmark/v4.0-performance-benchmarking-with-tpch.md new file mode 100644 index 000000000000..3c73c4a55e90 --- /dev/null +++ b/benchmark/v4.0-performance-benchmarking-with-tpch.md @@ -0,0 +1,191 @@ +--- +title: TiDB TPC-H 性能对比测试报告 - v4.0 对比 v3.0 +category: benchmark +--- + +# TiDB TPC-H 性能对比测试报告 - v4.0 对比 v3.0 + +## 测试目的 + +对比 TiDB v4.0 和 v3.0 OLAP 场景下的性能。 + +因为 TiDB v4.0 中新引入了 [TiFlash](/tiflash/tiflash-overview.md) 组件增强 TiDB HTAP 形态,本文的测试对象如下: + ++ v3.0 仅从 TiKV 读取数据。 ++ v4.0 仅从 TiKV 读取数据。 ++ v4.0 通过智能选择混合读取 TiKV、TiFlash 的数据。 + +## 测试环境 (AWS EC2) + +### 硬件配置 + +| 服务类型 | EC2 类型 | 实例数 | +|:----------------|:------------|:----| +| PD | m5.xlarge | 3 | +| TiDB | c5.4xlarge | 2 | +| TiKV & TiFlash | i3.4xlarge | 3 | +| TPC-H | m5.xlarge | 1 | + +### 软件版本 + +| 服务类型 | 软件版本 | +|:----------|:-----------| +| PD | 3.0、4.0 | +| TiDB | 3.0、4.0 | +| TiKV | 3.0、4.0 | +| TiFlash | 4.0 | +| tiup-bench | 0.2 | + +### 配置参数 + +#### v3.0 + +v3.0 的 TiDB 和 TiKV 均为默认参数配置。 + +##### 全局变量配置 + +{{< copyable "sql" >}} + +```sql +set global tidb_distsql_scan_concurrency = 30; +set global tidb_projection_concurrency = 16; +set global tidb_hashagg_partial_concurrency = 16; +set global tidb_hashagg_final_concurrency = 16; +set global tidb_hash_join_concurrency = 16; +set global tidb_index_lookup_concurrency = 16; +set global tidb_index_lookup_join_concurrency = 16; +``` + +#### v4.0 + +v4.0 的 TiDB 为默认参数配置。 + +##### TiKV 配置 + +{{< copyable "" >}} + +```yaml +readpool.storage.use-unified-pool: false +readpool.coprocessor.use-unified-pool: true +``` + +##### PD 配置 + +{{< copyable "" >}} + +```yaml +replication.enable-placement-rules: true +``` + +##### TiFlash 配置 + +{{< copyable "" >}} + +```yaml +logger.level: "info" +learner_config.log-level: "info" +``` + +##### 全局变量配置 + +{{< copyable "sql" >}} + +```sql +set global tidb_allow_batch_cop = 1; +set global tidb_opt_distinct_agg_push_down = 1; +set global tidb_distsql_scan_concurrency = 30; +set global tidb_projection_concurrency = 16; +set global tidb_hashagg_partial_concurrency = 16; +set global tidb_hashagg_final_concurrency = 16; +set global tidb_hash_join_concurrency = 16; +set global tidb_index_lookup_concurrency = 16; +set global tidb_index_lookup_join_concurrency = 16; +``` + +### 测试方案 + +#### 硬件准备 + +为了避免 TiKV 和 TiFlash 争抢磁盘和 I/O 资源,把 EC2 配置的两个 NVMe SSD 盘分别挂载为 `/data1` 及 `/data2`,把 TiKV 的部署至 `/data1`,TiFlash 部署至 `/data2`。 + +#### 测试过程 + +1. 通过 TiUP 部署 TiDB v4.0 和 v3.0。 + +2. 通过 TiUP 的 bench 工具导入 TPC-H 10 数据。 + + * 执行以下命令将数据导入 v3.0: + + {{< copyable "bash" >}} + + ```bash + tiup bench tpch prepare \ + --host ${tidb_v3_host} --port ${tidb_v3_port} --db tpch_10 \ + --sf 10 \ + --analyze --tidb_build_stats_concurrency 8 --tidb_distsql_scan_concurrency 30 + ``` + + * 执行以下命令将数据导入 v4.0: + + {{< copyable "bash" >}} + + ```bash + tiup bench tpch prepare \ + --host ${tidb_v4_host} --port ${tidb_v4_port} --db tpch_10 --password ${password} \ + --sf 10 \ + --tiflash \ + --analyze --tidb_build_stats_concurrency 8 --tidb_distsql_scan_concurrency 30 + ``` + +3. 运行 TPC-H 的查询。 + + 1. 下载 TPC-H 的 SQL 查询文件: + + {{< copyable "" >}} + + ```bash + git clone https://github.com/pingcap/tidb-bench.git && cd tpch/queries + ``` + + 2. 查询并记录耗时。 + + * 对于 TiDB v3.0,使用 MySQL 客户端连接到 TiDB,然后执行查询,记录 v3.0 查询耗时。 + * 对于 TiDB v4.0,使用 MySQL 客户端连接到 TiDB,再根据测试的形态,选择其中一种操作: + * 设置 `set @@session.tidb_isolation_read_engines = 'tikv,tidb';` 后,再执行查询,记录 v4.0 仅从 TiKV 读取数据的查询耗时。 + * 设置 `set @@session.tidb_isolation_read_engines = 'tikv,tiflash,tidb';` 后,再执行查询,记录 v4.0 通过智能选择从 TiKV 和 TiFlash 混合读取数据的查询耗时。 + +4. 提取整理耗时数据。 + +### 测试结果 + +| Query ID | v3.0 | v4.0 TiKV Only | v4.0 TiKV / TiFlash Automatically | +| :-------- | :----------- | :------------ | :-------------- | +| 1 | 7.78s | 7.45s | 2.09s | +| 2 | 3.15s | 1.71s | 1.71s | +| 3 | 6.61s | 4.10s | 4.05s | +| 4 | 2.98s | 2.56s | 1.87s | +| 5 | 20.35s | 5.71s | 8.53s | +| 6 | 4.75s | 2.44s | 0.39s | +| 7 | 7.97s | 3.72s | 3.59s | +| 8 | 5.89s | 3.22s | 8.59s | +| 9 | 34.08s | 11.87s | 15.41s | +| 10 | 4.83s | 2.75s | 3.35s | +| 11 | 3.98s | 1.60s | 1.59s | +| 12 | 5.63s | 3.40s | 1.03s | +| 13 | 5.41s | 4.56s | 4.02s | +| 14 | 5.19s | 3.10s | 0.78s | +| 15 | 10.25s | 1.82s | 1.26s | +| 16 | 2.46s | 1.51s | 1.58s | +| 17 | 23.76s | 12.38s | 8.52s | +| 18 | 17.14s | 16.38s | 16.06s | +| 19 | 5.70s | 4.59s | 3.20s | +| 20 | 4.98s | 1.89s | 1.29s | +| 21 | 11.12s | 6.23s | 6.26s | +| 22 | 4.49s | 3.05s | 2.31s | + +![TPC-H](/media/tpch_v4vsv3.png) + +以上性能图中蓝色为 v3.0,红色为 v4.0(仅从 TiKV 读),黄色为 v4.0(从 TiKV、TiFlash 智能选取),纵坐标是查询的处理时间。纵坐标越低,表示性能越好。 + +- v4.0(仅从 TiKV 读取数据),即 TiDB 仅会从 TiKV 中读取数据。将该结果与 v3.0 的结果对比可得知,TiDB、TiKV 升级至 4.0 版本后,TPC-H 性能得到的提升幅度。 +- v4.0(从 TiKV、TiFlash 智能选取),即 TiDB 优化器会自动根据代价估算选择是否使用 TiFlash 副本。将该结果与 v3.0 的结果对比可得知,在 v4.0 完整的 HTAP 形态下,TPC-H 性能得到的提升幅度。 diff --git a/best-practices/grafana-monitor-best-practices.md b/best-practices/grafana-monitor-best-practices.md new file mode 100644 index 000000000000..4affca0ee729 --- /dev/null +++ b/best-practices/grafana-monitor-best-practices.md @@ -0,0 +1,207 @@ +--- +title: 使用 Grafana 监控 TiDB 的最佳实践 +summary: 了解高效利用 Grafana 监控 TiDB 的七个技巧。 +category: reference +aliases: ['/docs-cn/stable/reference/best-practices/grafana-monitor/'] +--- + +# 使用 Grafana 监控 TiDB 的最佳实践 + +[使用 TiDB Ansible 部署 TiDB 集群](/online-deployment-using-ansible.md)时,会同时部署一套 [Grafana + Prometheus 的监控平台](/tidb-monitoring-framework.md),用于收集和展示 TiDB 集群各个组件和机器的 metric 信息。本文主要介绍使用 TiDB 监控的最佳实践,旨在帮助 TiDB 用户高效利用丰富的 metric 信息来分析 TiDB 的集群状态或进行故障诊断。 + +## 监控架构 + +Prometheus 是一个拥有多维度数据模型和灵活查询语句的时序数据库。Grafana 是一个开源的 metric 分析及可视化系统。 + +![TiDB 监控整体架构](/media/prometheus-in-tidb.png) + +从 TiDB 2.1.3 版本开始,监控可以支持 pull,这是一个非常好的调整,它有以下几个优点: + +- 如果 Prometheus 需要迁移,无需重启整个 TiDB 集群。调整前,因为组件要调整 push 的目标地址,迁移 Prometheus 需要重启整个集群。 +- 支持部署 2 套独立的 Grafana + Prometheus 的监控平台(非 HA),防止监控的单点。方法是使用 TiDB Ansible 用不同的 IP 各执行一次部署命令。 +- 去掉了 Pushgateway 这个单点组件。 + +## 监控数据的来源与展示 + +TiDB 的 3 个核心组件(TiDB server、TiKV server 和 PD server)可以通过 HTTP 接口来获取 metric 数据。这些 metric 均是从程序代码中上传的,默认端口如下: + +| 组件 | 端口 | +|:------------|:-------| +| TiDB server | 10080 | +| TiKV server | 20181 | +| PD server | 2379 | + +下面以 TiDB server 为例,展示如何通过 HTTP 接口查看一个语句的 QPS 数据: + +{{< copyable "shell-regular" >}} + +```bash +curl http://__tidb_ip__:10080/metrics |grep tidb_executor_statement_total +``` + +``` +# 可以看到实时 QPS 数据,并根据不同 type 对 SQL 语句进行了区分,value 是 counter 类型的累计值(科学计数法)。 +tidb_executor_statement_total{type="Delete"} 520197 +tidb_executor_statement_total{type="Explain"} 1 +tidb_executor_statement_total{type="Insert"} 7.20799402e+08 +tidb_executor_statement_total{type="Select"} 2.64983586e+08 +tidb_executor_statement_total{type="Set"} 2.399075e+06 +tidb_executor_statement_total{type="Show"} 500531 +tidb_executor_statement_total{type="Use"} 466016 +``` + +这些数据会存储在 Prometheus 中,然后在 Grafana 上进行展示。在面板上点击鼠标右键会出现 **Edit** 按钮(或直接按 E 键),如下图所示: + +![Metrics 面板的编辑入口](/media/best-practices/metric-board-edit-entry.png) + +点击 **Edit** 按钮之后,在 Metrics 面板上可以看到利用该 metric 的 query 表达式。面板上一些细节的含义如下: + +- `rate[1m]`:表示 1 分钟的增长速率,只能用于 counter 类型的数据。 +- `sum`:表示 value 求和。 +- `by type`:表示将求和后的数据按 metric 原始值中的 type 进行分组。 +- `Legend format`:表示指标名称的格式。 +- `Resolution`:默认打点步长是 15s,Resolution 表示是否将多个样本数据合并成一个点。 + +Metrics 面板中的表达式如下: + +![Metric 面板中的表达式](/media/best-practices/metric-board-expression.jpeg) + +Prometheus 支持很多表达式与函数,更多表达式请参考 [Prometheus 官网页面](https://prometheus.io/docs/prometheus/latest/querying)。 + +## Grafana 使用技巧 + +本小节介绍高效利用 Grafana 监控分析 TiDB 指标的七个技巧。 + +### 技巧 1:查看所有维度并编辑表达式 + +在[监控数据的来源与展示](#监控数据的来源与展示)一节的示例中,数据是按照 type 进行分组的。如果你想知道是否还能按其它维度分组,并快速查看还有哪些维度,可采用以下技巧:**在 query 的表达式上只保留指标名称,不做任何计算,`Legend format` 也留空**。这样就能显示出原始的 metric 数据。比如,下图能看到有 3 个维度(`instance`、`job` 和 `type`): + +![编辑表达式并查看所有维度](/media/best-practices/edit-expression-check-dimensions.jpg) + +然后调整表达式,在原有的 `type` 后面加上 `instance` 这个维度,在 `Legend format` 处增加 `{{instance}}`,就可以看到每个 TiDB server 上执行的不同类型 SQL 语句的 QPS 了。如下图所示: + +![给表达式增加一个 instance 维度](/media/best-practices/add-instance-dimension.jpeg) + +### 技巧 2:调整 Y 轴标尺的计算方式 + +以 Query Duration 指标为例,默认的比例尺采用 2 的对数计算,显示上会将差距缩小。为了观察到明显的变化,可以将比例尺改为线性,从下面两张图中可以看到显示上的区别,明显发现那个时刻有个 SQL 语句运行较慢。 + +当然也不是所有场景都适合用线性,比如观察 1 个月的性能趋势,用线性可能就会有很多噪点,不好观察。 + +标尺默认的比例尺为 2 的对数: + +![标尺默认的比例尺为 2 的对数](/media/best-practices/default-axes-scale.jpg) + +将标尺的比例尺调整为线性: + +![调整标尺的比例尺为线性](/media/best-practices/axes-scale-linear.jpg) + +> **建议:** +> +> 结合技巧 1,会发现这里还有一个 `sql_type` 的维度,可以立刻分析出是 `SELECT` 慢还是 `UPDATE` 慢;并且可以分析出是哪个 instance 上的语句慢。 + +### 技巧 3:调整 Y 轴基线,放大变化 + +有时已经用了线性比例尺,却还是看不出变化趋势。比如下图中,在扩容后想观察 `Store size` 的实时变化效果,但由于基数较大,观察不到微弱的变化。这时可以将 Y 轴最小值从 `0` 改为 `auto`,将上部放大。观察下面两张图的区别,可以看出数据已开始迁移了。 + +基线默认为 `0`: + +![基线默认为 0](/media/best-practices/default-y-min.jpeg) + +将基线调整为 `auto`: + +![调整基线为 auto](/media/best-practices/y-min-auto.jpg) + +### 技巧 4:标尺联动 + +在 **Settings** 面板中,有一个 **Graph Tooltip** 设置项,默认使用 **Default**。 + +![图形展示工具](/media/best-practices/graph-tooltip.jpeg) + +下面将图形展示工具分别调整为 **Shared crosshair** 和 **Shared Tooltip** 看看效果。可以看到标尺能联动展示了,方便排查问题时确认 2 个指标的关联性。 + +将图形展示工具调整为 **Shared crosshair**: + +![调整图形展示工具为 Shared crosshair](/media/best-practices/graph-tooltip-shared-crosshair.jpeg) + +将图形展示工具调整为 **Shared Tooltip**: + +![调整图形展示工具为 Shared Tooltip](/media/best-practices/graph-tooltip-shared-tooltip.jpg) + +### 技巧 5:手动输入 `ip:端口号` 查看历史信息 + +PD 的 dashboard 只展示当前 leader 的 metric 信息,而有时想看历史上 PD leader 当时的状况,但是 `instance` 下拉列表中已不存在这个成员了。此时,可以手动输入 `ip:2379` 来查看当时的数据。 + +![查看历史 metric 信息](/media/best-practices/manually-input-check-metric.jpeg) + +### 技巧 6:巧用 `Avg` 函数 + +通常默认图例中只有 `Max` 和 `Current` 函数。当指标波动较大时,可以增加 `Avg` 等其它汇总函数的图例,来看一段时间的整体趋势。 + +增加 `Avg` 等汇总函数: + +![增加 Avg 等汇总函数](/media/best-practices/add-avg-function.jpeg) + +然后查看整体趋势: + +![增加 Avg 函数查看整体趋势](/media/best-practices/add-avg-function-check-trend.jpg) + +### 技巧 7:使用 Prometheus 的 API 接口获得表达式的结果 + +Grafana 通过 Prometheus 的接口获取数据,你也可以用该接口来获取数据,这个用法还可以衍生出许多功能: + +- 自动获取集群规模、状态等信息。 +- 对表达式稍加改动给报表提供数据,如统计每天的 QPS 总量、每天的 QPS 峰值和每天的响应时间。 +- 将重要的指标进行定期健康巡检。 + +Prometheus 的 API 接口如下: + +![Prometheus 的 API 接口](/media/best-practices/prometheus-api-interface.jpg) + +{{< copyable "shell-regular" >}} + +```bash +curl -u user:pass 'http://__grafana_ip__:3000/api/datasources/proxy/1/api/v1/query_range?query=sum(tikv_engine_size_bytes%7Binstancexxxxxxxxx20181%22%7D)%20by%20(instance)&start=1565879269&end=1565882869&step=30' |python -m json.tool +``` + +``` +{ + "data": { + "result": [ + { + "metric": { + "instance": "xxxxxxxxxx:20181" + }, + "values": [ + [ + 1565879269, + "1006046235280" + ], + [ + 1565879299, + "1006057877794" + ], + [ + 1565879329, + "1006021550039" + ], + [ + 1565879359, + "1006021550039" + ], + [ + 1565882869, + "1006132630123" + ] + ] + } + ], + "resultType": "matrix" + }, + "status": "success" +} +``` + +## 总结 + +Grafana + Prometheus 监控平台是一套非常强大的组合工具,用好这套工具可以为分析节省很多时间,提高效率,更重要的是,我们可以更容易发现问题。在运维 TiDB 集群,尤其是数据量大的情况下,这套工具能派上大用场。 diff --git a/best-practices/haproxy-best-practices.md b/best-practices/haproxy-best-practices.md new file mode 100644 index 000000000000..deff4a6d751c --- /dev/null +++ b/best-practices/haproxy-best-practices.md @@ -0,0 +1,228 @@ +--- +title: HAProxy 在 TiDB 中的最佳实践 +category: reference +aliases: ['/docs-cn/stable/reference/best-practices/haproxy/'] +--- + +# HAProxy 在 TiDB 中的最佳实践 + +本文介绍 [HAProxy](https://github.com/haproxy/haproxy) 在 TiDB 中的最佳配置和使用方法。HAProxy 提供 TCP 协议下的负载均衡能力,TiDB 客户端通过连接 HAProxy 提供的浮动 IP 即可对数据进行操作,实现 TiDB Server 层的负载均衡。 + +![HAProxy 在 TiDB 中的最佳实践](/media/haproxy.jpg) + +## HAProxy 简介 + +HAProxy 是由 C 语言编写的自由开放源码的软件,为基于 TCP 和 HTTP 协议的应用程序提供高可用性、负载均衡和代理服务。因为 HAProxy 能够快速、高效使用 CPU 和内存,所以目前使用非常广泛,许多知名网站诸如 GitHub、Bitbucket、Stack Overflow、Reddit、Tumblr、Twitter 和 Tuenti 以及亚马逊网络服务系统都在使用 HAProxy。 + +HAProxy 由 Linux 内核的核心贡献者 Willy Tarreau 于 2000 年编写,他现在仍然负责该项目的维护,并在开源社区免费提供版本迭代。最新的稳定版本 2.0.0 于 2019 年 8 月 16 日发布,带来更多[优秀的特性](https://www.haproxy.com/blog/haproxy-2-0-and-beyond/)。 + +## HAProxy 部分核心功能介绍 + +- [高可用性](http://cbonte.github.io/haproxy-dconv/1.9/intro.html#3.3.4):HAProxy 提供优雅关闭服务和无缝切换的高可用功能; +- [负载均衡](http://cbonte.github.io/haproxy-dconv/1.9/configuration.html#4.2-balance):L4 (TCP) 和 L7 (HTTP) 两种负载均衡模式,至少 9 类均衡算法,比如 roundrobin,leastconn,random 等; +- [健康检查](http://cbonte.github.io/haproxy-dconv/1.9/configuration.html#5.2-check):对 HAProxy 配置的 HTTP 或者 TCP 模式状态进行检查; +- [会话保持](http://cbonte.github.io/haproxy-dconv/1.9/intro.html#3.3.6):在应用程序没有提供会话保持功能的情况下,HAProxy 可以提供该项功能; +- [SSL](http://cbonte.github.io/haproxy-dconv/1.9/intro.html#3.3.2):支持 HTTPS 通信和解析; +- [监控与统计](http://cbonte.github.io/haproxy-dconv/1.9/intro.html#3.3.3):通过 web 页面可以实时监控服务状态以及具体的流量信息。 + +## 准备环境 + +在部署 HAProxy 之前,需准备好以下环境。 + +### 硬件要求 + +根据官方文档,对 HAProxy 的服务器硬件配置有以下建议,也可以根据负载均衡环境进行推算,在此基础上提高服务器配置。 + +|硬件资源|最低配置| +|:---|:---| +|CPU|2 核,3.5 GHz| +|内存|16 GB| +|存储容量|50 GB(SATA 盘)| +|网卡|万兆网卡| + +### 依赖软件 + +根据官方文档,对操作系统和依赖包有以下建议,如果通过 yum 源部署安装 HAProxy 软件,依赖包无需单独安装。 + +#### 操作系统 + +| 操作系统版本 | 架构 | +|:-------------------------|:------------------------------------------| +| Linux 2.4 | x86、x86_64、Alpha、SPARC、MIPS 和 PA-RISC | +| Linux 2.6 或 3.x | x86、x86_64、ARM、SPARC 和 PPC64 | +| Solaris 8 或 9 | UltraSPARC II 和 UltraSPARC III | +| Solaris 10 | Opteron 和 UltraSPARC | +| FreeBSD 4.10 ~ 10 | x86 | +| OpenBSD 3.1 及以上版本 | i386、AMD64、macppc、Alpha 和 SPARC64 | +| AIX 5.1 ~ 5.3 | Power™ | + +#### 依赖包 + +- epel-release +- gcc +- systemd-devel + +执行如下命令安装依赖包: + +{{< copyable "shell-regular" >}} + +```bash +yum -y install epel-release gcc systemd-devel +``` + +## 部署 HAProxy + +HAProxy 配置 Database 负载均衡场景操作简单,以下部署操作具有普遍性,不具有特殊性,建议根据实际场景,个性化配置相关的[配置文件](http://cbonte.github.io/haproxy-dconv/1.9/configuration.html)。 + +### 安装 HAProxy + +1. 使用 yum 安装 HAProxy: + + {{< copyable "shell-regular" >}} + + ```bash + yum -y install haproxy + ``` + +2. 验证 HAProxy 安装是否成功: + + {{< copyable "shell-regular" >}} + + ```bash + which haproxy + ``` + + ``` + /usr/sbin/haproxy + ``` + +#### HAProxy 命令介绍 + +执行如下命令查看命令行参数及基本用法: + +{{< copyable "shell-regular" >}} + +```bash +haproxy --help +``` + +| 参数 | 说明 | +| :------- | :--------- | +| `-v` | 显示简略的版本信息。 | +| `-vv` | 显示详细的版本信息。 | +| `-d` | 开启 debug 模式。 | +| `-db` | 禁用后台模式和多进程模式。 | +| `-dM []` | 执行分配内存。| +| `-V` | 启动过程显示配置和轮询信息。 | +| `-D` | 开启守护进程模式。 | +| `-C ` | 在加载配置文件之前更改目录位置至 ``。 | +| `-W` | 主从模式。 | +| `-q` | 静默模式,不输出信息。 | +| `-c` | 只检查配置文件并在尝试绑定之前退出。 | +| `-n ` | 设置每个进程的最大总连接数为 ``。 | +| `-m ` | 设置所有进程的最大可用内存为 ``(单位:MB)。 | +| `-N ` | 设置单点最大连接数为 ``,默认为 2000。 | +| `-L ` | 将本地实例对等名称改为 ``,默认为本地主机名。 | +| `-p ` | 将 HAProxy 所有子进程的 PID 信息写入 ``。 | +| `-de` | 禁止使用 epoll(7),epoll(7) 仅在 Linux 2.6 和某些定制的 Linux 2.4 系统上可用。 | +| `-dp` | 禁止使用 epoll(2),可改用 select(2)。 | +| `-dS` | 禁止使用 splice(2),splice(2) 在一些旧版 Linux 内核上不可用。 | +| `-dR` | 禁止使用 SO_REUSEPORT。 | +| `-dr` | 忽略服务器地址解析失败。 | +| `-dV` | 禁止在服务器端使用 SSL。 | +| `-sf ` | 启动后,向 pidlist 中的 PID 发送 `finish` 信号,收到此信号的进程在退出之前将等待所有会话完成,即优雅停止服务。此选项必须最后指定,后跟任意数量的 PID。从技术上讲,SIGTTOU 和 SIGUSR1 都被发送。 | +| `-st ` | 启动后,向 pidlist 中的 PID 发送 `terminate` 信号,收到此信号的进程将立即终止,关闭所有活动会话。此选项必须最后指定,后跟任意数量的 PID。从技术上讲,SIGTTOU 和 SIGTERM 都被发送。 | +| `-x ` | 连接指定的 socket 并从旧进程中获取所有 listening socket,然后,使用这些 socket 而不是绑定新的。 | +| `-S [,...]` | 主从模式下,创建绑定到主进程的 socket,此 socket 可访问每个子进程的 socket。 | + +更多有关 HAProxy 命令参数的信息,可参阅 [Management Guide of HAProxy](http://cbonte.github.io/haproxy-dconv/1.9/management.html) 和 [General Commands Manual of HAProxy](https://manpages.debian.org/buster-backports/haproxy/haproxy.1.en.html)。 + +### 配置 HAProxy + +yum 安装过程中会生成配置模版,你也可以根据实际场景自定义配置如下配置项。 + +```yaml +global # 全局配置。 + log 127.0.0.1 local2 # 定义全局的 syslog 服务器,最多可以定义两个。 + chroot /var/lib/haproxy # 更改当前目录并为启动进程设置超级用户权限,从而提高安全性。 + pidfile /var/run/haproxy.pid # 将 HAProxy 进程的 PID 写入 pidfile。 + maxconn 4000 # 每个 HAProxy 进程所接受的最大并发连接数。 + user haproxy # 同 UID 参数。 + group haproxy # 同 GID 参数,建议使用专用用户组。 + nbproc 40 # 在后台运行时创建的进程数。在启动多个进程转发请求时,确保该值足够大,保证 HAProxy 不会成为瓶颈。 + daemon # 让 HAProxy 以守护进程的方式工作于后台,等同于命令行参数“-D”的功能。当然,也可以在命令行中用“-db”参数将其禁用。 + stats socket /var/lib/haproxy/stats # 统计信息保存位置。 + +defaults # 默认配置。 + log global # 日志继承全局配置段的设置。 + retries 2 # 向上游服务器尝试连接的最大次数,超过此值便认为后端服务器不可用。 + timeout connect 2s # HAProxy 与后端服务器连接超时时间。如果在同一个局域网内,可设置成较短的时间。 + timeout client 30000s # 客户端与 HAProxy 连接后,数据传输完毕,即非活动连接的超时时间。 + timeout server 30000s # 服务器端非活动连接的超时时间。 + +listen admin_stats # frontend 和 backend 的组合体,此监控组的名称可按需进行自定义。 + bind 0.0.0.0:8080 # 监听端口。 + mode http # 监控运行的模式,此处为 `http` 模式。 + option httplog # 开始启用记录 HTTP 请求的日志功能。 + maxconn 10 # 最大并发连接数。 + stats refresh 30s # 每隔 30 秒自动刷新监控页面。 + stats uri /haproxy # 监控页面的 URL。 + stats realm HAProxy # 监控页面的提示信息。 + stats auth admin:pingcap123 # 监控页面的用户和密码,可设置多个用户名。 + stats hide-version # 隐藏监控页面上的 HAProxy 版本信息。 + stats admin if TRUE # 手工启用或禁用后端服务器(HAProxy 1.4.9 及之后版本开始支持)。 + +listen tidb-cluster # 配置 database 负载均衡。 + bind 0.0.0.0:3390 # 浮动 IP 和 监听端口。 + mode tcp # HAProxy 要使用第 4 层的传输层。 + balance leastconn # 连接数最少的服务器优先接收连接。`leastconn` 建议用于长会话服务,例如 LDAP、SQL、TSE 等,而不是短会话协议,如 HTTP。该算法是动态的,对于启动慢的服务器,服务器权重会在运行中作调整。 + server tidb-1 10.9.18.229:4000 check inter 2000 rise 2 fall 3 # 检测 4000 端口,检测频率为每 2000 毫秒一次。如果 2 次检测为成功,则认为服务器可用;如果 3 次检测为失败,则认为服务器不可用。 + server tidb-2 10.9.39.208:4000 check inter 2000 rise 2 fall 3 + server tidb-3 10.9.64.166:4000 check inter 2000 rise 2 fall 3 +``` + +### 启动 HAProxy + +- 方法一:执行 `haproxy`,默认读取 `/etc/haproxy/haproxy.cfg`(推荐)。 + + {{< copyable "shell-regular" >}} + + ```bash + haproxy -f /etc/haproxy/haproxy.cfg + ``` + +- 方法二:使用 `systemd` 启动 HAProxy。 + + {{< copyable "shell-regular" >}} + + ```bash + systemctl start haproxy.service + ``` + +### 停止 HAProxy + +- 方法一:使用 `kill -9`。 + + 1. 执行如下命令: + + {{< copyable "shell-regular" >}} + + ```bash + ps -ef | grep haproxy + ``` + + 2. 终止 HAProxy 相关的 PID 进程: + + {{< copyable "shell-regular" >}} + + ```bash + kill -9 ${haproxy.pid} + ``` + +- 方法二:使用 `systemd`。 + + {{< copyable "shell-regular" >}} + + ```bash + systemctl stop haproxy.service + ``` diff --git a/best-practices/high-concurrency-best-practices.md b/best-practices/high-concurrency-best-practices.md new file mode 100644 index 000000000000..54e08b0f189f --- /dev/null +++ b/best-practices/high-concurrency-best-practices.md @@ -0,0 +1,212 @@ +--- +title: TiDB 高并发写入场景最佳实践 +summary: 了解 TiDB 在高并发写入场景下的最佳实践。 +category: reference +aliases: ['/docs-cn/stable/reference/best-practices/high-concurrency/'] +--- + +# TiDB 高并发写入场景最佳实践 + +在 TiDB 的使用过程中,一个典型场景是高并发批量写入数据到 TiDB。本文阐述了该场景中的常见问题,旨在给出一个业务的最佳实践,帮助读者避免因使用 TiDB 不当而影响业务开发。 + +## 目标读者 + +本文假设你已对 TiDB 有一定的了解,推荐先阅读 TiDB 原理相关的三篇文章([讲存储](https://pingcap.com/blog-cn/tidb-internal-1/),[说计算](https://pingcap.com/blog-cn/tidb-internal-2/),[谈调度](https://pingcap.com/blog-cn/tidb-internal-3/)),以及 [TiDB Best Practice](https://pingcap.com/blog-cn/tidb-best-practice/)。 + +## 高并发批量插入场景 + +高并发批量插入的场景通常出现在业务系统的批量任务中,例如清算以及结算等业务。此类场景存在以下特点: + +- 数据量大 +- 需要短时间内将历史数据入库 +- 需要短时间内读取大量数据 + +这就对 TiDB 提出了以下挑战: + +- 写入/读取能力是否可以线性水平扩展 +- 随着数据持续大并发写入,数据库性能是否稳定不衰减 + +对于分布式数据库来说,除了本身的基础性能外,最重要的就是充分利用所有节点能力,避免让单个节点成为瓶颈。 + +## TiDB 数据分布原理 + +如果要解决以上挑战,需要从 TiDB 数据切分以及调度的原理开始讲起。这里只作简单说明,详情可参阅[谈调度](https://pingcap.com/blog-cn/tidb-internal-3/)。 + +TiDB 以 Region 为单位对数据进行切分,每个 Region 有大小限制(默认 96M)。Region 的切分方式是范围切分。每个 Region 会有多副本,每一组副本,称为一个 Raft Group。每个 Raft Group 中由 Leader 负责执行这块数据的读 & 写(TiDB 即将支持 [Follower-Read](https://zhuanlan.zhihu.com/p/78164196))。Leader 会自动地被 PD 组件均匀调度在不同的物理节点上,用以均分读写压力。 + +![TiDB 数据概览](/media/best-practices/tidb-data-overview.png) + +只要业务的写入没有 `AUTO_INCREMENT` 的主键,或没有单调递增的索引(即没有业务上的写入热点,更多细节可参阅 [TiDB 正确使用方式](https://zhuanlan.zhihu.com/p/25574778)),从原理上来说,TiDB 依靠这个架构可具备线性扩展的读写能力,并且可以充分利用分布式资源。从这一点看,TiDB 尤其适合高并发批量写入场景的业务。 + +但理论场景和实际情况往往存在不同。以下实例说明了热点是如何产生的。 + +## 热点产生的实例 + +以下为一张示例表: + +```sql +CREATE TABLE IF NOT EXISTS TEST_HOTSPOT( + id BIGINT PRIMARY KEY, + age INT, + user_name VARCHAR(32), + email VARCHAR(128) +) +``` + +这个表的结构非常简单,除了 `id` 为主键以外,没有额外的二级索引。将数据写入该表的语句如下,`id` 通过随机数离散生成: + +{{< copyable "sql" >}} + +```sql +INSERT INTO TEST_HOTSPOT(id, age, user_name, email) values(%v, %v, '%v', '%v'); +``` + +负载是短时间内密集地执行以上写入语句。 + +以上操作看似符合理论场景中的 TiDB 最佳实践,业务上没有热点产生。只要有足够的机器,就可以充分利用 TiDB 的分布式能力。要验证是否真的符合最佳实践,可以在实验环境中进行测试。 + +部署拓扑 2 个 TiDB 节点,3 个 PD 节点,6 个 TiKV 节点。请忽略 QPS,因为测试只是为了阐述原理,并非 benchmark。 + +![QPS1](/media/best-practices/QPS1.png) + +客户端在短时间内发起了“密集”的写入,TiDB 收到的请求是 3K QPS。理论上,压力应该均摊给 6 个 TiKV 节点。但是从 TiKV 节点的 CPU 使用情况上看,存在明显的写入倾斜(tikv - 3 节点是写入热点): + +![QPS2](/media/best-practices/QPS2.png) + +![QPS3](/media/best-practices/QPS3.png) + +[Raft store CPU](/grafana-tikv-dashboard.md) 为 `raftstore` 线程的 CPU 使用率,通常代表写入的负载。在这个场景下 tikv-3 为 Raft Leader,tikv-0 和 tikv-1 是 Raft 的 Follower,其他的 TiKV 节点的负载几乎为空。 + +从 PD 的监控中也可以证明热点的产生: + +![QPS4](/media/best-practices/QPS4.png) + +## 热点问题产生的原因 + +以上测试并未达到理论场景中最佳实践,因为刚创建表的时候,这个表在 TiKV 中只会对应为一个 Region,范围是: + +``` +[CommonPrefix + TableID, CommonPrefix + TableID + 1) +``` + +短时间内大量数据会持续写入到同一个 Region 上。 + +![TiKV Region 分裂流程](/media/best-practices/tikv-Region-split.png) + +上图简单描述了这个过程,随着数据持续写入,TiKV 会将一个 Region 切分为多个。但因为首先发起选举的是原 Leader 所在的 Store,所以新切分好的两个 Region 的 Leader 很可能还会在原 Store 上。新切分好的 Region 2,3 上,也会重复之前发生在 Region 1 上的过程。也就是压力会密集地集中在 TiKV-Node 1 上。 + +在持续写入的过程中,PD 发现 Node 1 中产生了热点,会将 Leader 均分到其他的 Node 上。如果 TiKV 的节点数多于副本数的话,TiKV 会尽可能将 Region 迁移到空闲的节点上。这两个操作在数据插入的过程中,也能在 PD 监控中得到印证: + +![QPS5](/media/best-practices/QPS5.png) + +在持续写入一段时间后,整个集群会被 PD 自动地调度成一个压力均匀的状态,到那个时候整个集群的能力才会真正被利用起来。在大多数情况下,以上热点产生的过程是没有问题的,这个阶段属于表 Region 的预热阶段。 + +但是对于高并发批量密集写入场景来说,应该避免这个阶段。 + +## 热点问题的规避方法 + +为了达到场景理论中的最佳性能,可跳过这个预热阶段,直接将 Region 切分为预期的数量,提前调度到集群的各个节点中。 + +TiDB 在 v3.0.x 以及 v2.1.13 后支持一个叫 [Split Region](/sql-statements/sql-statement-split-region.md) 的新特性。这个特性提供了新的语法: + +{{< copyable "sql" >}} + +```sql +SPLIT TABLE table_name [INDEX index_name] BETWEEN (lower_value) AND (upper_value) REGIONS region_num +``` + +{{< copyable "sql" >}} + +```sql +SPLIT TABLE table_name [INDEX index_name] BY (value_list) [, (value_list)] +``` + +但是 TiDB 并不会自动提前完成这个切分操作。原因如下: + +![Table Region Range](/media/best-practices/table-Region-range.png) + +从上图可知,根据行数据 key 的编码规则,行 ID (rowID) 是行数据中唯一可变的部分。在 TiDB 中,rowID 是一个 Int64 整型。但是用户不一定能将 Int64 整型范围均匀切分成需要的份数,然后均匀分布在不同的节点上,还需要结合实际情况。 + +如果行 ID 的写入是完全离散的,那么上述方式是可行的。如果行 ID 或者索引有固定的范围或者前缀(例如,只在 `[2000w, 5000w)` 的范围内离散插入数据),这种写入依然在业务上不产生热点,但是如果按上面的方式进行切分,那么有可能一开始数据仍只写入到某个 Region 上。 + +作为一款通用数据库,TiDB 并不对数据的分布作假设,所以开始只用一个 Region 来对应一个表。等到真实数据插入进来以后,TiDB 自动根据数据的分布来作切分。这种方式是较通用的。 + +所以 TiDB 提供了 `Split Region` 语法,专门针对短时批量写入场景作优化。基于以上案例,下面尝试用 `Split Region` 语法提前切散 Region,再观察负载情况。 + +由于测试的写入数据在正数范围内完全离散,所以用以下语句,在 Int64 空间内提前将表切分为 128 个 Region: + +{{< copyable "sql" >}} + +```sql +SPLIT TABLE TEST_HOTSPOT BETWEEN (0) AND (9223372036854775807) REGIONS 128; +``` + +切分完成以后,可以通过 `SHOW TABLE test_hotspot REGIONS;` 语句查看打散的情况。如果 `SCATTERING` 列值全部为 `0`,代表调度成功。 + +也可以通过 [table-regions.py](https://github.com/pingcap/tidb-ansible/blob/dabf60baba5e740a4bee9faf95e77563d8084be1/scripts/table-regions.py) 脚本,查看 Region 的分布。目前分布已经比较均匀了: + +``` +[root@172.16.4.4 scripts]# python table-regions.py --host 172.16.4.3 --port 31453 test test_hotspot +[RECORD - test.test_hotspot] - Leaders Distribution: + total leader count: 127 + store: 1, num_leaders: 21, percentage: 16.54% + store: 4, num_leaders: 20, percentage: 15.75% + store: 6, num_leaders: 21, percentage: 16.54% + store: 46, num_leaders: 21, percentage: 16.54% + store: 82, num_leaders: 23, percentage: 18.11% + store: 62, num_leaders: 21, percentage: 16.54% +``` + +再重新运行写入负载: + +![QPS6](/media/best-practices/QPS6.png) + +![QPS7](/media/best-practices/QPS7.png) + +![QPS8](/media/best-practices/QPS8.png) + +可以看到已经消除了明显的热点问题了。 + +本示例仅为一个简单的表,还有索引热点的问题需要考虑。读者可参阅 [Split Region](/sql-statements/sql-statement-split-region.md) 文档来了解如何预先切散索引相关的 Region。 + +### 更复杂的热点问题 + +**问题一:** + +如果表没有主键或者主键不是整数类型,而且用户也不想自己生成一个随机分布的主键 ID 的话,TiDB 内部有一个隐式的 `_tidb_rowid` 列作为行 ID。在不使用 `SHARD_ROW_ID_BITS` 的情况下,`_tidb_rowid` 列的值基本也为单调递增,此时也会有写热点存在(参阅 [`SHARD_ROW_ID_BITS` 的详细说明](/tidb-specific-system-variables.md#shard_row_id_bits))。 + +要避免由 `_tidb_rowid` 带来的写入热点问题,可以在建表时,使用 `SHARD_ROW_ID_BITS` 和 `PRE_SPLIT_REGIONS` 这两个建表选项(参阅 [`PRE_SPLIT_REGIONS` 的详细说明](/sql-statements/sql-statement-split-region.md#pre_split_regions))。 + +`SHARD_ROW_ID_BITS` 用于将 `_tidb_rowid` 列生成的行 ID 随机打散。`pre_split_regions` 用于在建完表后预先进行 Split region。 + +> **注意:** +> +> `pre_split_regions` 必须小于或等于 `shard_row_id_bits`。 + +示例: + +{{< copyable "sql" >}} + +```sql +create table t (a int, b int) shard_row_id_bits = 4 pre_split_regions=3; +``` + +- `SHARD_ROW_ID_BITS = 4` 表示 tidb_rowid 的值会随机分布成 16 (16=2^4) 个范围区间。 +- `pre_split_regions=3` 表示建完表后提前切分出 8 (2^3) 个 Region。 + +开始写数据进表 t 后,数据会被写入提前切分好的 8 个 Region 中,这样也避免了刚开始建表完后因为只有一个 Region 而存在的写热点问题。 + +**问题二:** + +如果表的主键为整数类型,并且该表使用了 `AUTO_INCREMENT` 来保证主键唯一性(不需要连续或递增)的表而言,由于 TiDB 直接使用主键行值作为 `_tidb_rowid`,此时无法使用 `SHARD_ROW_ID_BITS` 来打散热点。 + +要解决上述热点问题,可以利用 `AUTO_RANDOM` 列属性(参阅 [`AUTO_RANDOM` 的详细说明](/auto-random.md)),将 `AUTO_INCREMENT` 改为 `AUTO_RANDOM`,插入数据时让 TiDB 自动为整型主键列分配一个值,消除行 ID 的连续性,从而达到打散热点的目的。 + +## 参数配置 + +TiDB 2.1 版本中在 SQL 层引入了 [latch 机制](/tidb-configuration-file.md#txn-local-latches),用于在写入冲突比较频繁的场景中提前发现事务冲突,减少 TiDB 和 TiKV 事务提交时写写冲突导致的重试。通常,跑批场景使用的是存量数据,所以并不存在事务的写入冲突。可以把 TiDB 的 latch 功能关闭,以减少为细小对象分配内存: + +``` +[txn-local-latches] +enabled = false +``` diff --git a/best-practices/java-app-best-practices.md b/best-practices/java-app-best-practices.md new file mode 100644 index 000000000000..4e11215a1ae6 --- /dev/null +++ b/best-practices/java-app-best-practices.md @@ -0,0 +1,333 @@ +--- +title: 开发 Java 应用使用 TiDB 的最佳实践 +category: reference +aliases: ['/docs-cn/stable/reference/best-practices/java-app/'] +--- + +# 开发 Java 应用使用 TiDB 的最佳实践 + +本文主要介绍如何开发 Java 应用程序以更好地使用 TiDB,包括开发中的常见问题与最佳实践。 + +## Java 应用中的数据库相关组件 + +通常 Java 应用中和数据库相关的常用组件有: + +- 网络协议:客户端通过标准 [MySQL 协议](https://dev.mysql.com/doc/internals/en/client-server-protocol.html)和 TiDB 进行网络交互。 +- JDBC API 及实现:Java 应用通常使用 [JDBC (Java Database Connectivity)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) 来访问数据库。JDBC 定义了访问数据库 API,而 JDBC 实现完成标准 API 到 MySQL 协议的转换,常见的 JDBC 实现是 [MySQL Connector/J](https://github.com/mysql/mysql-connector-j),此外有些用户可能使用 [MariaDB Connector/J](https://mariadb.com/kb/en/library/about-mariadb-connector-j/#about-mariadb-connectorj)。 +- 数据库连接池:为了避免每次创建连接,通常应用会选择使用数据库连接池来复用连接,JDBC [DataSource](https://docs.oracle.com/javase/8/docs/api/javax/sql/DataSource.html) 定义了连接池 API,开发者可根据实际需求选择使用某种开源连接池实现。 +- 数据访问框架:应用通常选择通过数据访问框架 ([MyBatis](http://www.mybatis.org/mybatis-3/zh/index.html), [Hibernate](https://hibernate.org/)) 的封装来进一步简化和管理数据库访问操作。 +- 业务实现:业务逻辑控制着何时发送和发送什么指令到数据库,其中有些业务会使用 [Spring Transaction](https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html) 切面来控制管理事务的开始和提交逻辑。 + +![Java Component](/media/java-practice-1.png) + +如上图所示,应用可能使用 Spring Transaction 来管理控制事务非手工启停,通过类似 MyBatis 的数据访问框架管理生成和执行 SQL,通过连接池获取已池化的长连接,最后通过 JDBC 接口调用实现通过 MySQL 协议和 TiDB 完成交互。 + +接下来将分别介绍使用各个组件时可能需要关注的问题。 + +## JDBC + +Java 应用尽管可以选择在不同的框架中封装,但在最底层一般会通过调用 JDBC 来与数据库服务器进行交互。对于 JDBC,需要关注的主要有:API 的使用选择和 API Implementer 的参数配置。 + +### JDBC API + +对于基本的 JDBC API 使用可以参考 [JDBC 官方教程](https://docs.oracle.com/javase/tutorial/jdbc/),本文主要强调几个比较重要的 API 选择。 + +#### 使用 Prepare API + +对于 OLTP 场景,程序发送给数据库的 SQL 语句在去除参数变化后都是可穷举的某几类,因此建议使用[预处理语句 (Prepared Statements)](https://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html) 代替普通的[文本执行](https://docs.oracle.com/javase/tutorial/jdbc/basics/processingsqlstatements.html#executing_queries),并复用预处理语句来直接执行,从而避免 TiDB 重复解析和生成 SQL 执行计划的开销。 + +目前多数上层框架都会调用 Prepare API 进行 SQL 执行,如果直接使用 JDBC API 进行开发,注意选择使用 Prepare API。 + +另外需要注意 MySQL Connector/J 实现中默认只会做客户端的语句预处理,会将 `?` 在客户端替换后以文本形式发送到服务端,所以除了要使用 Prepare API,还需要在 JDBC 连接参数中配置 `useServerPrepStmts = true`,才能在 TiDB 服务器端进行语句预处理(下面参数配置章节有详细介绍)。 + +#### 使用 Batch 批量插入更新 + +对于批量插入更新,如果插入记录较多,可以选择使用 [addBatch/executeBatch API](https://www.tutorialspoint.com/jdbc/jdbc-batch-processing)。通过 addBatch 的方式将多条 SQL 的插入更新记录先缓存在客户端,然后在 executeBatch 时一起发送到数据库服务器。 + +> **注意:** +> +> 对于 MySQL Connector/J 实现,默认 Batch 只是将多次 addBatch 的 SQL 发送时机延迟到调用 executeBatch 的时候,但实际网络发送还是会一条条的发送,通常不会降低与数据库服务器的网络交互次数。 +> +> 如果希望 Batch 网络发送,需要在 JDBC 连接参数中配置 `rewriteBatchedStatements = true`(下面参数配置章节有详细介绍)。 + +#### 使用 StreamingResult 流式获取执行结果 + +一般情况下,为提升执行效率,JDBC 会默认提前获取查询结果并将其保存在客户端内存中。但在查询返回超大结果集的场景中,客户端会希望数据库服务器减少向客户端一次返回的记录数,等客户端在有限内存处理完一部分后再去向服务器要下一批。 + +在 JDBC 中通常有以下两种处理方式: + +- 设置 [`FetchSize` 为 `Integer.MIN_VALUE`](https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-implementation-notes.html#ResultSet) 让客户端不缓存,客户端通过 StreamingResult 的方式从网络连接上流式读取执行结果。 +- 使用 Cursor Fetch,首先需[设置 `FetchSize`](http://makejavafaster.blogspot.com/2015/06/jdbc-fetch-size-performance.html) 为正整数,且在 JDBC URL 中配置 `useCursorFetch = true`。 + +TiDB 中同时支持两种方式,但更推荐使用第一种将 `FetchSize` 设置为 `Integer.MIN_VALUE` 的方式,比第二种功能实现更简单且执行效率更高。 + +### MySQL JDBC 参数 + +JDBC 实现通常通过 JDBC URL 参数的形式来提供实现相关的配置。这里以 MySQL 官方的 Connector/J 来介绍[参数配置](https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html)(如果使用的是 MariaDB,可以参考 [MariaDB 的类似配置](https://mariadb.com/kb/en/library/about-mariadb-connector-j/#optional-url-parameters))。因为配置项较多,这里主要关注几个可能影响到性能的参数。 + +#### Prepare 相关参数 + +##### `useServerPrepStmts` + +默认情况下,`useServerPrepStmts` 的值为 `false`,即尽管使用了 Prepare API,也只会在客户端做 “prepare”。因此为了避免服务器重复解析的开销,如果同一条 SQL 语句需要多次使用 Prepare API,则建议设置该选项为 `true`。 + +在 TiDB 监控中可以通过 **Query Summary** > **QPS By Instance** 查看请求命令类型,如果请求中 `COM_QUERY` 被 `COM_STMT_EXECUTE` 或 `COM_STMT_PREPARE` 代替即生效。 + +##### `cachePrepStmts` + +虽然 `useServerPrepStmts = true` 能让服务端执行预处理语句,但默认情况下客户端每次执行完后会 close 预处理语句,并不会复用,这样预处理的效率甚至不如文本执行。所以建议开启 `useServerPrepStmts = true` 后同时配置 `cachePrepStmts = true`,这会让客户端缓存预处理语句。 + +在 TiDB 监控中可以通过 **Query Summary** > **QPS By Instance** 查看请求命令类型,如果类似下图,请求中 `COM_STMT_EXECUTE` 数目远远多于 `COM_STMT_PREPARE` 即生效。 + +![QPS By Instance](/media/java-practice-2.png) + +另外,通过 `useConfigs = maxPerformance` 配置会同时配置多个参数,其中也包括 `cachePrepStmts = true`。 + +##### `prepStmtCacheSqlLimit` + +在配置 `cachePrepStmts` 后还需要注意 `prepStmtCacheSqlLimit` 配置(默认为 `256`),该配置控制客户端缓存预处理语句的最大长度,超过该长度将不会被缓存。 + +在一些场景 SQL 的长度可能超过该配置,导致预处理 SQL 不能复用,建议根据应用 SQL 长度情况决定是否需要调大该值。 + +在 TiDB 监控中通过 **Query Summary** > **QPS by Instance** 查看请求命令类型,如果已经配置了 `cachePrepStmts = true`,但 `COM_STMT_PREPARE` 还是和 `COM_STMT_EXECUTE` 基本相等且有 `COM_STMT_CLOSE`,需要检查这个配置项是否设置得太小。 + +##### `prepStmtCacheSize` + +`prepStmtCacheSize` 控制缓存的预处理语句数目(默认为 `25`),如果应用需要预处理的 SQL 种类很多且希望复用预处理语句,可以调大该值。 + +和上一条类似,在监控中通过 **Query Summary** > **QPS by Instance** 查看请求中 `COM_STMT_EXECUTE` 数目是否远远多于 `COM_STMT_PREPARE` 来确认是否正常。 + +#### Batch 相关参数 + +在进行 batch 写入处理时推荐配置 `rewriteBatchedStatements = true`,在已经使用 `addBatch` 或 `executeBatch` 后默认 JDBC 还是会一条条 SQL 发送,例如: + +```java +pstmt = prepare(“insert into t (a) values(?)”); +pstmt.setInt(1, 10); +pstmt.addBatch(); +pstmt.setInt(1, 11); +pstmt.addBatch(); +pstmt.setInt(1, 12); +pstmt.executeBatch(); +``` + +虽然使用了 batch 但发送到 TiDB 语句还是单独的多条 insert: + +{{< copyable "sql" >}} + +```sql +insert into t(a) values(10); +insert into t(a) values(11); +insert into t(a) values(12); +``` + +如果设置 `rewriteBatchedStatements = true`,发送到 TiDB 的 SQL 将是: + +{{< copyable "sql" >}} + +```sql +insert into t(a) values(10),(11),(12); +``` + +需要注意的是,insert 语句的改写,只能将多个 values 后的值拼接成一整条 SQL,insert 语句如果有其他差异将无法被改写。 +例如: + +{{< copyable "sql" >}} + +```sql +insert into t (a) values (10) on duplicate key update a = 10; +insert into t (a) values (11) on duplicate key update a = 11; +insert into t (a) values (12) on duplicate key update a = 12; +``` + +上述 insert 语句将无法被改写成一条语句。该例子中,如果将 SQL 改写成如下形式: + +{{< copyable "sql" >}} + +```sql +insert into t (a) values (10) on duplicate key update a = values(a); +insert into t (a) values (11) on duplicate key update a = values(a); +insert into t (a) values (12) on duplicate key update a = values(a); +``` + +即可满足改写条件,最终被改写成: + +{{< copyable "sql" >}} + +```sql +insert into t (a) values (10), (11), (12) on duplicate key update a = values(a); +``` + +批量更新时如果有 3 处或 3 处以上更新,则 SQL 语句会改写为 multiple-queries 的形式并发送,这样可以有效减少客户端到服务器的请求开销,但副作用是会产生较大的 SQL 语句,例如这样: + +{{< copyable "sql" >}} + +```sql +update t set a = 10 where id = 1; update t set a = 11 where id = 2; update t set a = 12 where id = 3; +``` + +另外,因为一个[客户端 bug](https://bugs.mysql.com/bug.php?id=96623),批量更新时如果要配置 `rewriteBatchedStatements = true` 和 `useServerPrepStmts = true`,推荐同时配置 `allowMultiQueries = true` 参数来避免这个 bug。 + +#### 执行前检查参数 + +通过监控可能会发现,虽然业务只向集群进行 insert 操作,却看到有很多多余的 select 语句。通常这是因为 JDBC 发送了一些查询设置类的 SQL 语句(例如 `select @@session.transaction_read_only`)。这些 SQL 对 TiDB 无用,推荐配置 `useConfigs = maxPerformance` 来避免额外开销。 + +`useConfigs = maxPerformance` 会包含一组配置: + +```ini +cacheServerConfiguration = true +useLocalSessionState = true +elideSetAutoCommits = true +alwaysSendSetIsolation = false +enableQueryTimeouts = false +``` + +配置后查看监控,可以看到多余语句减少。 + +## 连接池 + +TiDB (MySQL) 连接建立是比较昂贵的操作(至少对于 OLTP),除了建立 TCP 连接外还需要进行连接鉴权操作,所以客户端通常会把 TiDB (MySQL) 连接保存到连接池中进行复用。 + +Java 的连接池实现很多 ([HikariCP](https://github.com/brettwooldridge/HikariCP), [tomcat-jdbc](https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html), [durid](https://github.com/alibaba/druid), [c3p0](https://www.mchange.com/projects/c3p0/), [dbcp](https://commons.apache.org/proper/commons-dbcp/)),TiDB 不会限定使用的连接池,应用可以根据业务特点自行选择连接池实现。 + +### 连接数配置 + +比较常见的是应用需要根据自身情况配置合适的连接池大小,以 HikariCP 为例: + +- `maximumPoolSize`:连接池最大连接数,配置过大会导致 TiDB 消耗资源维护无用连接,配置过小则会导致应用获取连接变慢,所以需根据应用自身特点配置合适的值,可参考[这篇文章](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing)。 +- `minimumIdle`:连接池最小空闲连接数,主要用于在应用空闲时存留一些连接以应对突发请求,同样是需要根据业务情况进行配置。 + +应用在使用连接池时,需要注意连接使用完成后归还连接,推荐应用使用对应的连接池相关监控(如 `metricRegistry`),通过监控能及时定位连接池问题。 + +### 探活配置 + +连接池维护到 TiDB 的长连接,TiDB 默认不会主动关闭客户端连接(除非报错),但一般客户端到 TiDB 之间还会有 LVS 或 HAProxy 之类的网络代理,它们通常会在连接空闲一定时间后主动清理连接。除了注意代理的 idle 配置外,连接池还需要进行保活或探测连接。 + +如果常在 Java 应用中看到以下错误: + +``` +The last packet sent successfully to the server was 3600000 milliseconds ago. The driver has not received any packets from the server. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure +``` + +如果 `n milliseconds ago` 中的 `n` 如果是 0 或很小的值,则通常是执行的 SQL 导致 TiDB 异常退出引起的报错,推荐查看 TiDB stderr 日志;如果 n 是一个非常大的值(比如这里的 3600000),很可能是因为这个连接空闲太久然后被中间 proxy 关闭了,通常解决方式除了调大 proxy 的 idle 配置,还可以让连接池执行以下操作: + +- 每次使用连接前检查连接是否可用。 +- 使用单独线程定期检查连接是否可用。 +- 定期发送 test query 保活连接。 + +不同的连接池实现可能会支持其中一种或多种方式,可以查看所使用的连接池文档来寻找对应配置。 + +## 数据访问框架 + +业务应用通常会使用某种数据访问框架来简化数据库的访问。 + +### MyBatis + +[MyBatis](http://www.mybatis.org/mybatis-3/) 是目前比较流行的 Java 数据访问框架,主要用于管理 SQL 并完成结果集和 Java 对象的来回映射工作。MyBatis 和 TiDB 兼容性很好,从历史 issue 可以看出 MyBatis 很少出现问题。这里主要关注如下几个配置。 + +#### Mapper 参数 + +MyBatis 的 Mapper 中支持两种参数: + +- `select 1 from t where id = #{param1}` 会作为预处理语句,被转换为 `select 1 from t where id = ?` 进行预处理,并使用实际参数来复用执行,通过配合前面的 Prepare 连接参数能获得最佳性能。 +- `select 1 from t where id = ${param2}` 会做文本替换为 `select 1 from t where id = 1` 执行,如果这条语句被预处理为不同参数,可能会导致 TiDB 缓存大量的预处理语句,并且以这种方式执行 SQL 有注入安全风险。 + +#### 动态 SQL Batch + +[动态 SQL - foreach](http://www.mybatis.org/mybatis-3/dynamic-sql.html#foreach) + +要支持将多条 insert 语句自动重写为 `insert ... values(...), (...), ...` 的形式,除了前面所说的在 JDBC 配置 `rewriteBatchedStatements = true` 外,MyBatis 还可以使用动态 SQL 来半自动生成 batch insert。比如下面的 mapper: + +```xml + + insert into test + (id, v1, v2) + values + + ( + #{item.id}, #{item.v1}, #{item.v2} + ) + + on duplicate key update v2 = v1 + values(v1) + +``` + +会生成一个 `insert on duplicate key update` 语句,values 后面的 `(?, ?, ?)` 数目是根据传入的 list 个数决定,最终效果和使用 `rewriteBatchStatements = true` 类似,可以有效减少客户端和 TiDB 的网络交互次数,同样需要注意预处理后超过 `prepStmtCacheSqlLimit` 限制导致不缓存预处理语句的问题。 + +#### Streaming 结果 + +前面介绍了在 JDBC 中如何使用流式读取结果,除了 JDBC 相应的配置外,在 MyBatis 中如果希望读取超大结果集合也需要注意: + +- 可以通过在 mapper 配置中对单独一条 SQL 设置 `fetchSize`(见上一段代码段),效果等同于调用 JDBC `setFetchSize` +- 可以使用带 `ResultHandler` 的查询接口来避免一次获取整个结果集 +- 可以使用 `Cursor` 类来进行流式读取 + +对于使用 xml 配置映射,可以通过在映射 ` + select * from post; + +``` + +而使用代码配置映射,则可以使用 `@Options(fetchSize = Integer.MIN_VALUE)` 并返回 `Cursor` 从而让 SQL 结果能被流式读取。 + +```java +@Select("select * from post") +@Options(fetchSize = Integer.MIN_VALUE) +Cursor queryAllPost(); +``` + +### `ExecutorType` + +在 `openSession` 的时候可以选择 `ExecutorType`,MyBatis 支持三种 executor: + +- Simple:每次执行都会向 JDBC 进行预处理语句的调用(如果 JDBC 配置有开启 `cachePrepStmts`,重复的预处理语句会复用)。 +- Reuse:在 `executor` 中缓存预处理语句,这样不用 JDBC 的 `cachePrepStmts` 也能减少重复预处理语句的调用。 +- Batch:每次更新只有在 `addBatch` 到 query 或 commit 时才会调用 `executeBatch` 执行,如果 JDBC 层开启了 `rewriteBatchStatements`,则会尝试改写,没有开启则会一条条发送。 + +通常默认值是 `Simple`,需要在调用 `openSession` 时改变 `ExecutorType`。如果是 Batch 执行,会遇到事务中前面的 update 或 insert 都非常快,而在读数据或 commit 事务时比较慢的情况,这实际上是正常的,在排查慢 SQL 时需要注意。 + +## Spring Transaction + +在应用代码中业务可能会通过使用 [Spring Transaction](https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html) 和 AOP 切面的方式来启停事务。 + +通过在方法定义上添加 `@Transactional` 注解标记方法,AOP 将会在方法前开启事务,方法返回结果前 commit 事务。如果遇到类似业务,可以通过查找代码 `@Transactional` 来确定事务的开启和关闭时机。需要特别注意有内嵌的情况,如果发生内嵌,Spring 会根据 [Propagation](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Propagation.html) 配置使用不同的行为,因为 TiDB 未支持 savepoint,所以不支持嵌套事务。 + +## 其他 + +### 排查工具 + +在 Java 应用发生问题并且不知道业务逻辑情况下,使用 JVM 强大的排查工具会比较有用。这里简单介绍几个常用工具: + +#### jstack + +[jstack](https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstack.html) 对应于 Go 中的 pprof/goroutine,可以比较方便地排查进程卡死的问题。 + +通过执行 `jstack pid`,即可输出目标进程中所有线程的线程 id 和堆栈信息。输出中默认只有 Java 堆栈,如果希望同时输出 JVM 中的 C++ 堆栈,需要加 `-m` 选项。 + +通过多次 jstack 可以方便地发现卡死问题(比如:都通过 Mybatis BatchExecutor flush 调用 update)或死锁问题(比如:测试程序都在抢占应用中某把锁导致没发送 SQL) + +另外,`top -p $PID -H` 或者 Java swiss knife 都是常用的查看线程 ID 的方法。通过 `printf "%x\n" pid` 把线程 ID 转换成 16 进制,然后去 jstack 输出结果中找对应线程的栈信息,可以定位”某个线程占用 CPU 比较高,不知道它在执行什么”的问题。 + +#### jmap & mat + +和 Go 中的 pprof/heap 不同,[jmap](https://docs.oracle.com/javase/7/docs/technotes/tools/share/jmap.html) 会将整个进程的内存快照 dump 下来(go 是分配器的采样),然后可以通过另一个工具 [mat](https://www.eclipse.org/mat/) 做分析。 + +通过 mat 可以看到进程中所有对象的关联信息和属性,还可以观察线程运行的状态。比如:我们可以通过 mat 找到当前应用中有多少 MySQL 连接对象,每个连接对象的地址和状态信息是什么。 + +需要注意 mat 默认只会处理 reachable objects,如果要排查 young gc 问题可以在 mat 配置中设置查看 unreachable objects。另外对于调查 young gc 问题(或者大量生命周期较短的对象)的内存分配,用 Java Flight Recorder 比较方便。 + +#### trace + +线上应用通常无法修改代码,又希望在 Java 中做动态插桩来定位问题,推荐使用 btrace 或 arthas trace。它们可以在不重启进程的情况下动态插入 trace 代码。 + +#### 火焰图 + +Java 应用中获取火焰图较繁琐,可参阅 [Java Flame Graphs Introduction: Fire For Everyone!](http://psy-lob-saw.blogspot.com/2017/02/flamegraphs-intro-fire-for-everyone.html) 来手动获取。 + +## 总结 + +本文从常用的和数据库交互的 Java 组件的角度,阐述了开发 Java 应用程序使用 TiDB 的常见问题与解决办法。TiDB 是高度兼容 MySQL 协议的数据库,基于 MySQL 开发的 Java 应用的最佳实践也多适用于 TiDB。 + +欢迎大家在 [ASK TUG](https://asktug.com/) 踊跃发言,和我们一起分享讨论 Java 应用使用 TiDB 的实践技巧或遇到的问题。 diff --git a/best-practices/massive-regions-best-practices.md b/best-practices/massive-regions-best-practices.md new file mode 100644 index 000000000000..545f8877fc65 --- /dev/null +++ b/best-practices/massive-regions-best-practices.md @@ -0,0 +1,144 @@ +--- +title: 海量 Region 集群调优最佳实践 +summary: 了解海量 Region 导致性能问题的原因和优化方法。 +category: reference +aliases: ['/docs-cn/stable/reference/best-practices/massive-regions/'] +--- + +# 海量 Region 集群调优最佳实践 + +在 TiDB 的架构中,所有数据以一定 key range 被切分成若干 Region 分布在多个 TiKV 实例上。随着数据的写入,一个集群中会产生上百万个甚至千万个 Region。单个 TiKV 实例上产生过多的 Region 会给集群带来较大的负担,影响整个集群的性能表现。 + +本文将介绍 TiKV 核心模块 Raftstore 的工作流程,海量 Region 导致性能问题的原因,以及优化性能的方法。 + +## Raftstore 的工作流程 + +一个 TiKV 实例上有多个 Region。Region 消息是通过 Raftstore 模块驱动 Raft 状态机来处理的。这些消息包括 Region 上读写请求的处理、Raft log 的持久化和复制、Raft 的心跳处理等。但是,Region 数量增多会影响整个集群的性能。为了解释这一点,需要先了解 TiKV 的核心模块 Raftstore 的工作流程。 + +![图 1 Raftstore 处理流程示意图](/media/best-practices/raft-process.png) + +> **注意:** +> +> 该图仅为示意,不代表代码层面的实际结构。 + +上图是 Raftstore 处理流程的示意图。如图所示,从 TiDB 发来的请求会通过 gRPC 和 storage 模块变成最终的 KV 读写消息,并被发往相应的 Region,而这些消息并不会被立即处理而是被暂存下来。Raftstore 会轮询检查每个 Region 是否有需要处理的消息。如果 Region 有需要处理的消息,那么 Raftstore 会驱动 Raft 状态机去处理这些消息,并根据这些消息所产生的状态变更去进行后续操作。例如,在有写请求时,Raft 状态机需要将日志落盘并且将日志发送给其他 Region 副本;在达到心跳间隔时,Raft 状态机需要将心跳信息发送给其他 Region 副本。 + +## 性能问题 + +从 Raftstore 处理流程示意图可以看出,需要依次处理各个 Region 的消息。那么在 Region 数量较多的情况下,Raftstore 需要花费一些时间去处理大量 Region 的心跳,从而带来一些延迟,导致某些读写请求得不到及时处理。如果读写压力较大,Raftstore 线程的 CPU 使用率容易达到瓶颈,导致延迟进一步增加,进而影响性能表现。 + +通常在有负载的情况下,如果 Raftstore 的 CPU 使用率达到了 85% 以上,即可视为达到繁忙状态且成为了瓶颈,同时 `propose wait duration` 可能会高达百毫秒级别。 + +> **注意:** +> +> + Raftstore 的 CPU 使用率是指单线程的情况。如果是多线程 Raftstore,可等比例放大使用率。 +> + 由于 Raftstore 线程中有 I/O 操作,所以 CPU 使用率不可能达到 100%。 + +### 性能监控 + +可在 Grafana 的 TiKV 面板下查看相关的监控 metrics: + ++ Thread-CPU 下的 `Raft store CPU` + + 参考值:低于 `raftstore.store-pool-size * 85%`。 + + ![图 2 查看 Raftstore CPU](/media/best-practices/raft-store-cpu.png) + ++ Raft Propose 下的 `Propose wait duration` + + `Propose wait duration` 是从发送请求给 Raftstore,到 Raftstore 真正开始处理请求之间的延迟时间。如果该延迟时间较长,说明 Raftstore 比较繁忙或者处理 append log 比较耗时导致 Raftstore 不能及时处理请求。 + + 参考值:低于 50-100ms。 + + ![图 3 查看 Propose wait duration](/media/best-practices/propose-wait-duration.png) + +## 性能优化方法 + +找到性能问题的根源后,可从以下两个方向来解决性能问题: + ++ 减少单个 TiKV 实例的 Region 数 ++ 减少单个 Region 的消息数 + +### 方法一:增加 TiKV 实例 + +如果 I/O 资源和 CPU 资源都比较充足,可在单台机器上部署多个 TiKV 实例,以减少单个 TiKV 实例上的 Region 个数;或者增加 TiKV 集群的机器数。 + +### 方法二:调整 `raft-base-tick-interval` + +除了减少 Region 个数外,还可以通过减少 Region 单位时间内的消息数量来减小 Raftstore 的压力。例如,在 TiKV 配置中适当调大 `raft-base-tick-interval`: + +{{< copyable "" >}} + +``` +[raftstore] +raft-base-tick-interval = "2s" +``` + +`raft-base-tick-interval` 是 Raftstore 驱动每个 Region 的 Raft 状态机的时间间隔,也就是每隔该时长就需要向 Raft 状态机发送一个 tick 消息。增加该时间间隔,可以有效减少 Raftstore 的消息数量。 + +需要注意的是,该 tick 消息的间隔也决定了 `election timeout` 和 `heartbeat` 的间隔。示例如下: + +{{< copyable "" >}} + +``` +raft-election-timeout = raft-base-tick-interval * raft-election-timeout-ticks +raft-heartbeat-interval = raft-base-tick-interval * raft-heartbeat-ticks +``` + +如果 Region Follower 在 `raft-election-timeout` 间隔内未收到来自 Leader 的心跳,就会判断 Leader 出现故障而发起新的选举。`raft-heartbeat-interval` 是 Leader 向 Follower 发送心跳的间隔,因此调大 `raft-base-tick-interval` 可以减少单位时间内 Raft 发送的网络消息,但也会让 Raft 检测到 Leader 故障的时间更长。 + +### 方法三:提高 Raftstore 并发数 + +从 v3.0 版本起,Raftstore 已经扩展为多线程,极大降低了 Raftstore 线程成为瓶颈的可能性。 + +TiKV 默认将 `raftstore.store-pool-size` 配置为 `2`。如果 Raftstore 出现瓶颈,可以根据实际情况适当调高该参数值,但不建议设置过高以免引入不必要的线程切换开销。 + +### 方法四:开启 Hibernate Region 功能 + +在实际情况中,读写请求并不会均匀分布到每个 Region 上,而是集中在少数的 Region 上。那么可以尽量减少暂时空闲的 Region 的消息数量,这也就是 Hibernate Region 的功能。无必要时可不进行 `raft-base-tick`,即不驱动空闲 Region 的 Raft 状态机,那么就不会触发这些 Region 的 Raft 产生心跳信息,极大地减小了 Raftstore 的工作负担。 + +Hibernate Region 在 [TiKV master](https://github.com/tikv/tikv/tree/master) 分支上默认开启。可根据实际情况和需求来开启该功能。Hibernate Region 的配置说明请参考[配置 Hibernate Region](https://github.com/tikv/tikv/blob/master/docs/reference/configuration/raftstore-config.md#hibernate-region)。 + +### 方法五:开启 `Region Merge` + +> **注意:** +> +> 从 TiDB v3.0 开始,`Region Merge` 默认开启。 + +开启 `Region Merge` 也能减少 Region 的个数。与 `Region Split` 相反,`Region Merge` 是通过调度把相邻的小 Region 合并的过程。在集群中删除数据或者执行 `Drop Table`/`Truncate Table` 语句后,可以将小 Region 甚至空 Region 进行合并以减少资源的消耗。 + +通过 pd-ctl 设置以下参数即可开启 `Region Merge`: + +{{< copyable "" >}} + +``` +>> pd-ctl config set max-merge-region-size 20 +>> pd-ctl config set max-merge-region-keys 200000 +>> pd-ctl config set merge-schedule-limit 8 +``` + +详情请参考[如何配置 Region Merge](https://github.com/tikv/tikv/blob/master/docs/how-to/configure/region-merge.md) 和 [PD 配置文件描述](/pd-configuration-file.md#schedule)。 + +同时,默认配置的 `Region Merge` 的参数设置较为保守,可以根据需求参考 [PD 调度策略最佳实践](/best-practices/pd-scheduling-best-practices.md#region-merge-速度慢) 中提供的方法加快 `Region Merge` 过程的速度。 + +## 其他问题和解决方案 + +### 切换 PD Leader 的速度慢 + +PD 需要将 Region Meta 信息持久化在 etcd 上,以保证切换 PD Leader 节点后 PD 能快速继续提供 Region 路由服务。随着 Region 数量的增加,etcd 出现性能问题,使得 PD 在切换 Leader 时从 etcd 获取 Region Meta 信息的速度较慢。在百万 Region 量级时,从 etcd 获取信息的时间可能需要十几秒甚至几十秒。 + +因此从 v3.0 版本起,PD 默认开启配置项 `use-region-storage`,将 Region Meta 信息存在本地的 LevelDB 中,并通过其他机制同步 PD 节点间的信息。 + +### PD 路由信息更新不及时 + +在 TiKV 中,pd-worker 模块将 Region Meta 信息定期上报给 PD,在 TiKV 重启或者切换 Region Leader 时需要通过统计信息重新计算 Region 的 `approximate size/keys`。因此在 Region 数量较多的情况下,pd-worker 单线程可能成为瓶颈,造成任务得不到及时处理而堆积起来。因此 PD 不能及时获取某些 Region Meta 信息以致路由信息更新不及时。该问题不会影响实际的读写,但可能导致 PD 调度不准确以及 TiDB 更新 Region cache 时需要多几次 round-trip。 + +可在 TiKV Grafana 面板中查看 Task 下的 Worker pending tasks 来确定 pd-worker 是否有任务堆积。通常来说,pending tasks 应该维持在一个比较低的值。 + +![图 4 查看 pd-worker](/media/best-practices/pd-worker-metrics.png) + +老版本 TiDB (< v3.0.5) pd-worker 的效率有一些缺陷,如果碰到类似问题,建议升级至最新版本。 + +### Prometheus 查询 metrics 的速度慢 + +在大规模集群中,随着 TiKV 实例数的增加,Prometheus 查询 metrics 时的计算压力较大,导致 Grafana 查看 metrics 的速度较慢。从 v3.0 版本起设置了一些 metrics 的预计算,让这个问题有所缓解。 diff --git a/best-practices/pd-scheduling-best-practices.md b/best-practices/pd-scheduling-best-practices.md new file mode 100644 index 000000000000..cdff115ae2cb --- /dev/null +++ b/best-practices/pd-scheduling-best-practices.md @@ -0,0 +1,278 @@ +--- +title: PD 调度策略最佳实践 +summary: 了解 PD 调度策略的最佳实践和调优方式 +category: reference +aliases: ['/docs-cn/stable/reference/best-practices/pd-scheduling/'] +--- + +# PD 调度策略最佳实践 + +本文将详细介绍 PD 调度系统的原理,并通过几个典型场景的分析和处理方式,分享调度策略的最佳实践和调优方式,帮助大家在使用过程中快速定位问题。本文假定你对 TiDB,TiKV 以及 PD 已经有一定的了解,相关核心概念如下: + +- [Leader/Follower/Learner](/glossary.md#leaderfollowerlearner) +- [Operator](/glossary.md#operator) +- [Operator Step](/glossary.md#operator-step) +- [Pending/Down](/glossary.md#pendingdown) +- [Region/Peer/Raft Group](/glossary.md#regionpeerraft-group) +- [Region Split](/glossary.md#region-split) +- [Scheduler](/glossary.md#scheduler) +- [Store](/glossary.md#store) + +> **注意:** +> +> 本文内容基于 TiDB 3.0 版本,更早的版本(2.x)缺少部分功能的支持,但是基本原理类似,也可以以本文作为参考。 + +## PD 调度原理 + +该部分介绍调度系统涉及到的相关原理和流程。 + +### 调度流程 + +宏观上来看,调度流程大体可划分为 3 个部分: + +1. 信息收集 + + TiKV 节点周期性地向 PD 上报 `StoreHeartbeat` 和 `RegionHeartbeat` 两种心跳消息: + + * `StoreHeartbeat` 包含 Store 的基本信息、容量、剩余空间和读写流量等数据。 + * `RegionHeartbeat` 包含 Region 的范围、副本分布、副本状态、数据量和读写流量等数据。 + + PD 梳理并转存这些信息供调度进行决策。 + +2. 生成调度 + + 不同的调度器从自身的逻辑和需求出发,考虑各种限制和约束后生成待执行的 Operator。这里所说的限制和约束包括但不限于: + + - 不往断连中、下线中、繁忙、空间不足、在大量收发 snapshot 等各种异常状态的 Store 添加副本 + - Balance 时不选择状态异常的 Region + - 不尝试把 Leader 转移给 Pending Peer + - 不尝试直接移除 Leader + - 不破坏 Region 各种副本的物理隔离 + - 不破坏 Label property 等约束 + +3. 执行调度 + + 调度执行的步骤为: + + a. Operator 先进入一个由 `OperatorController` 管理的等待队列。 + + b. `OperatorController` 会根据配置以一定的并发量从等待队列中取出 Operator 并执行。执行的过程就是依次把每个 Operator Step 下发给对应 Region 的 Leader。 + + c. 标记 Operator 为 “finish” 或 “timeout” 状态,然后从执行列表中移除。 + +### 负载均衡 + +Region 负载均衡调度主要依赖 `balance-leader` 和 `balance-region` 两个调度器。二者的调度目标是将 Region 均匀地分散在集群中的所有 Store 上,但它们各有侧重:`balance-leader` 关注 Region 的 Leader,目的是分散处理客户端请求的压力;`balance-region` 关注 Region 的各个 Peer,目的是分散存储的压力,同时避免出现爆盘等状况。 + +`balance-leader` 与 `balance-region` 有着相似的调度流程: + +1. 根据不同 Store 的对应资源量的情况分别打分。 +2. 不断从得分较高的 Store 选择 Leader 或 Peer 迁移到得分较低的 Store 上。 + +两者的分数计算上也有一定差异:`balance-leader` 比较简单,使用 Store 上所有 Leader 所对应的 Region Size 加和作为得分。因为不同节点存储容量可能不一致,计算 `balance-region` 得分会分以下三种情况: + +- 当空间富余时使用数据量计算得分(使不同节点数据量基本上均衡) +- 当空间不足时由使用剩余空间计算得分(使不同节点剩余空间基本均衡) +- 处于中间态时则同时考虑两个因素做加权和当作得分 + +此外,为了应对不同节点可能在性能等方面存在差异的问题,还可为 Store 设置负载均衡的权重。`leader-weight` 和 `region-weight` 分别用于控制 Leader 权重以及 Region 权重(默认值都为 “1”)。假如把某个 Store 的 `leader-weight` 设为 “2”,调度稳定后,则该节点的 Leader 数量约为普通节点的 2 倍;假如把某个 Store 的 `region-weight` 设为 “0.5”,那么调度稳定后该节点的 Region 数量约为其他节点的一半。 + +### 热点调度 + +热点调度对应的调度器是 `hot-region-scheduler`。在 3.0 版本中,统计热点 Region 的方式为: + +1. 根据 Store 上报的信息,统计出持续一段时间读或写流量超过一定阈值的 Region。 +2. 用与负载均衡类似的方式把这些 Region 分散开来。 + +对于写热点,热点调度会同时尝试打散热点 Region 的 Peer 和 Leader;对于读热点,由于只有 Leader 承载读压力,热点调度会尝试将热点 Region 的 Leader 打散。 + +### 集群拓扑感知 + +让 PD 感知不同节点分布的拓扑是为了通过调度使不同 Region 的各个副本尽可能分散,保证高可用和容灾。PD 会在后台不断扫描所有 Region,当发现 Region 的分布不是当前的最优化状态时,会生成调度以替换 Peer,将 Region 调整至最佳状态。 + +负责这个检查的组件叫 `replicaChecker`(跟 Scheduler 类似,但是不可关闭)。它依赖于 `location-labels` 配置项来进行调度。比如配置 `[zone,rack,host]` 定义了三层的拓扑结构:集群分为多个 zone(可用区),每个 zone 下有多个 rack(机架),每个 rack 下有多个 host(主机)。PD 在调度时首先会尝试将 Region 的 Peer 放置在不同的 zone,假如无法满足(比如配置 3 副本但总共只有 2 个 zone)则保证放置在不同的 rack;假如 rack 的数量也不足以保证隔离,那么再尝试 host 级别的隔离,以此类推。 + +### 缩容及故障恢复 + +缩容是指预备将某个 Store 下线,通过命令将该 Store 标记为 “Offline“ 状态,此时 PD 通过调度将待下线节点上的 Region 迁移至其他节点。 + +故障恢复是指当有 Store 发生故障且无法恢复时,有 Peer 分布在对应 Store 上的 Region 会产生缺少副本的状况,此时 PD 需要在其他节点上为这些 Region 补副本。 + +这两种情况的处理过程基本上是一样的。`replicaChecker` 检查到 Region 存在异常状态的 Peer后,生成调度在健康的 Store 上创建新副本替换异常的副本。 + +### Region merge + +Region merge 指的是为了避免删除数据后大量小甚至空的 Region 消耗系统资源,通过调度把相邻的小 Region 合并的过程。Region merge 由 `mergeChecker` 负责,其过程与 `replicaChecker` 类似:PD 在后台遍历,发现连续的小 Region 后发起调度。 + +## 查询调度状态 + +你可以通过观察 PD 相关的 Metrics 或使用 pd-ctl 工具等方式查看调度系统状态。更具体的信息可以参考 [PD 监控](/grafana-pd-dashboard.md)和 [PD Control](/pd-control.md)。 + +### Operator 状态 + +**Grafana PD/Operator** 页面展示了 Operator 的相关统计信息。其中比较重要的有: + +- Schedule Operator Create:Operator 的创建情况 +- Operator finish duration:Operator 执行耗时的情况 +- Operator Step duration:不同 Operator Step 执行耗时的情况 + +查询 Operator 的 pd-ctl 命令有: + +- `operator show`:查询当前调度生成的所有 Operator +- `operator show [admin | leader | region]`:按照类型查询 Operator + +### Balance 状态 + +**Grafana PD/Statistics - Balance** 页面展示了负载均衡的相关统计信息,其中比较重要的有: + +- Store Leader/Region score:每个 Store 的得分 +- Store Leader/Region count:每个 Store 的 Leader/Region 数量 +- Store available:每个 Store 的剩余空间 + +使用 pd-ctl 的 `store` 命令可以查询 Store 的得分、数量、剩余空间和 weight 等信息。 + +### 热点调度状态 + +**Grafana PD/Statistics - hotspot** 页面展示了热点 Region 的相关统计信息,其中比较重要的有: + +- Hot write Region’s leader/peer distribution:写热点 Region 的 Leader/Peer 分布情况 +- Hot read Region’s leader distribution:读热点 Region 的 Leader 分布情况 + +使用 pd-ctl 同样可以查询上述信息,可以使用的命令有: + +- `hot read`:查询读热点 Region 信息 +- `hot write`:查询写热点 Region 信息 +- `hot store`:按 Store 统计热点分布情况 +- `region topread [limit]`:查询当前读流量最大的 Region +- `region topwrite [limit]`:查询当前写流量最大的 Region + +### Region 健康度 + +**Grafana PD/Cluster/Region health** 面板展示了异常 Region 的相关统计信息,包括 Pending Peer、Down Peer、Offline Peer,以及副本数过多或过少的 Region。 + +通过 pd-ctl 的 `region check` 命令可以查看具体异常的 Region 列表: + +- `region check miss-peer`:缺副本的 Region +- `region check extra-peer`:多副本的 Region +- `region check down-peer`:有副本状态为 Down 的 Region +- `region check pending-peer`:有副本状态为 Pending 的 Region + +## 调度策略控制 + +使用 pd-ctl 可以从以下三个方面来调整 PD 的调度策略。更具体的信息可以参考 [PD Control](/pd-control.md)。 + +### 启停调度器 + +pd-ctl 支持动态创建和删除 Scheduler,你可以通过这些操作来控制 PD 的调度行为,如: + +- `scheduler show`:显示当前系统中的 Scheduler +- `scheduler remove balance-leader-scheduler`:删除(停用)balance region 调度器 +- `scheduler add evict-leader-scheduler-1`:添加移除 Store 1 的所有 Leader 的调度器 + +### 手动添加 Operator + +PD 支持直接通过 pd-ctl 来创建或删除 Operator,如: + +- `operator add add-peer 2 5`:在 Store 5 上为 Region 2 添加 Peer +- `operator add transfer-leader 2 5`:将 Region 2 的 Leader 迁移至 Store 5 +- `operator add split-region 2`:将 Region 2 拆分为 2 个大小相当的 Region +- `operator remove 2`:取消 Region 2 当前待执行的 Operator + +### 调度参数调整 + +使用 pd-ctl 执行 `config show` 命令可以查看所有的调度参数,执行 `config set {key} {value}` 可以调整对应参数的值。常见调整如下: + +- `leader-schedule-limit`:控制 Transfer Leader 调度的并发数 +- `region-schedule-limit`:控制增删 Peer 调度的并发数 +- `disable-replace-offline-replica`:停止处理节点下线的调度 +- `disable-location-replacement`:停止处理调整 Region 隔离级别相关的调度 +- `max-snapshot-count`:每个 Store 允许的最大收发 Snapshot 的并发数 + +## 典型场景分析与处理 + +该部分通过几个典型场景及其应对方式说明 PD 调度策略的最佳实践。 + +### Leader/Region 分布不均衡 + +PD 的打分机制决定了一般情况下,不同 Store 的 Leader Count 和 Region Count 不能完全说明负载均衡状态,所以需要从 TiKV 的实际负载或者存储空间占用来判断是否有负载不均衡的状况。 + +确认 Leader/Region 分布不均衡后,首先观察不同 Store 的打分情况。 + +如果不同 Store 的打分是接近的,说明 PD 认为此时已经是均衡状态了,可能的原因有: + +- 存在热点导致负载不均衡。可以参考[热点分布不均匀](#热点分布不均匀)中的解决办法进行分析处理。 +- 存在大量空 Region 或小 Region,因此不同 Store 的 Leader 数量差别特别大,导致 Raftstore 负担过重。此时需要开启 [Region Merge](#region-merge) 并尽可能加速合并。 +- 不同 Store 的软硬件环境存在差异。可以酌情调整 `leader-weight` 和 `region-weight` 来控制 Leader/Region 的分布。 +- 其他不明原因。仍可以通过调整 `leader-weight` 和 `region-weight` 来控制 Leader/Region 的分布。 + +如果不同 Store 的分数差异较大,需要进一步检查 Operator 的相关 Metrics,特别关注 Operator 的生成和执行情况,这时大体上又分两种情况: + +- 生成的调度是正常的,但是调度的速度很慢。可能的原因有: + + - 调度速度受限于 limit 配置。PD 默认配置的 limit 比较保守,在不对正常业务造成显著影响的前提下,可以酌情将 `leader-schedule-limit` 或 `region-schedule-limit` 调大一些。此外, `max-pending-peer-count` 以及 `max-snapshot-count` 限制也可以放宽。 + - 系统中同时运行有其他的调度任务产生竞争,导致 balance 速度上不去。这种情况下如果 balance 调度的优先级更高,可以先停掉其他的调度或者限制其他调度的速度。例如 Region 没均衡的情况下做下线节点操作,下线的调度与 Region Balance 会抢占 `region-schedule-limit` 配额,此时你可以调小 `replica-schedule-limit` 以限制下线调度的速度,或者设置 `disable-replace-offline-replica = true` 来暂时关闭下线流程。 + - 调度执行得太慢。可以通过 **Operator step duration** 进行判断。通常不涉及到收发 Snapshot 的 Step(比如 `TransferLeader`,`RemovePeer`,`PromoteLearner` 等)的完成时间应该在毫秒级,涉及到 Snapshot 的 Step(如 `AddLearner`,`AddPeer` 等)的完成时间为数十秒。如果耗时明显过高,可能是 TiKV 压力过大或者网络等方面的瓶颈导致的,需要具体情况具体分析。 + +- 没能生成对应的 balance 调度。可能的原因有: + + - 调度器未被启用。比如对应的 Scheduler 被删除了,或者 limit 被设置为 “0”。 + - 由于其他约束无法进行调度。比如系统中有 `evict-leader-scheduler`,此时无法把 Leader 迁移至对应的 Store。再比如设置了 Label property,也会导致部分 Store 不接受 Leader。 + - 集群拓扑的限制导致无法均衡。比如 3 副本 3 数据中心的集群,由于副本隔离的限制,每个 Region 的 3 个副本都分别分布在不同的数据中心,假如这 3 个数据中心的 Store 数不一样,最后调度就会收敛在每个数据中心均衡,但是全局不均衡的状态。 + +### 节点下线速度慢 + +这个场景需要从 Operator 相关的 Metrics 入手,分析 Operator 的生成执行情况。 + +如果调度在正常生成,只是速度很慢,可能的原因有: + +- 调度速度受限于 limit 配置。可以适当调大 `replica-schedule-limit`,`max-pending-peer-count` 以及 `max-snapshot-count` 限制也可以放宽。 +- 系统中同时运行有其他的调度任务产生竞争。处理方法参考[Leader/Region 分布不均衡](#leaderregion-分布不均衡)。 +- 下线单个节点时,由于待操作的 Region 有很大一部分(3 副本配置下约 1/3)的 Leader 都集中在下线的节点上,下线速度会受限于这个单点生成 Snapshot 的速度。你可以通过手动给该节点添加一个 `evict-leader-scheduler` 调度器迁走 Leader 来加速。 + +如果没有对应的 Operator 调度生成,可能的原因有: + +- 下线调度被关闭,或者 `replica-schedule-limit` 被设为 “0”。 +- 找不到节点来转移 Region。例如相同 Label 的替代节点可用容量都不足 20%,PD 为了避免爆盘的风险会停止调度。这种情况需要添加更多节点,或者删除一些数据释放空间。 + +### 节点上线速度慢 + +目前 PD 没有对节点上线特殊处理。节点上线实际上是依靠 balance region 机制来调度的,所以参考[Leader/Region 分布不均衡](#leaderregion-分布不均衡) 中的排查步骤即可。 + +### 热点分布不均匀 + +热点调度的问题大体上可以分为以下几种情况: + +- 从 PD 的 Metrics 能看出来有不少 hot Region,但是调度速度跟不上,不能及时地把热点 Region 分散开来。 + + **解决方法**:调大 `hot-region-schedule-limit` 并减少其他调度器的 limit 配额,从而加快热点调度的速度。还可调小 `hot-region-cache-hits-threshold` 使 PD 对更快响应流量的变化。 + +- 单一 Region 形成热点,比如大量请求频繁 scan 一个小表,这个可以从业务角度或者 Metrics 统计的热点信息看出来。由于单 Region 热点现阶段无法使用打散的手段来消除,需要确认热点 Region 后手动添加 `split-region` 调度将这样的 Region 拆开。 + +- 从 PD 的统计来看没有热点,但是从 TiKV 的相关 Metrics 可以看出部分节点负载明显高于其他节点,成为整个系统的瓶颈。这是因为目前 PD 统计热点 Region 的维度比较单一,仅针对流量进行分析,在某些场景下无法准确定位热点。例如部分 Region 有大量的点查请求,从流量上来看并不显著,但是过高的 QPS 导致关键模块达到瓶颈。 + + **解决方法**:首先从业务层面确定形成热点的 table,然后添加 `scatter-range-scheduler` 调度器使这个 table 的所有 Region 均匀分布。TiDB 也在其 HTTP API 中提供了相关接口来简化这个操作,具体可以参考 [TiDB HTTP API](https://github.com/pingcap/tidb/blob/master/docs/tidb_http_api.md) 文档。 + +### Region Merge 速度慢 + +Region Merge 速度慢也很有可能是受到 limit 配置的限制(`merge-schedule-limit` 及 `region-schedule-limit`),或者是与其他调度器产生了竞争。具体来说,可有如下处理方式: + +- 假如已经从相关 Metrics 得知系统中有大量的空 Region,这时可以通过把 `max-merge-region-size` 和 `max-merge-region-keys` 调整为较小值来加快 Merge 速度。这是因为 Merge 的过程涉及到副本迁移,所以 Merge 的 Region 越小,速度就越快。如果生成 Merge Operator 的速度很快,想进一步加快 Region Merge 过程,还可以把 `patrol-region-interval` 调整为 "10ms" ,这个能加快巡检 Region 的速度,但是会消耗更多的 CPU 资源。 + +- 创建过大量表后(包括执行 `Truncate Table` 操作)又清空了。此时如果开启了 split table 特性,这些空 Region 是无法合并的,此时需要调整以下参数关闭这个特性: + + - TiKV: `split-region-on-table` 设为 `false`,该参数不支持动态修改。 + - PD: + + `key-type` 设为 `txn` 或者 `raw`,该参数支持动态修改。 + + `key-type` 保持 `table`,同时设置 `enable-cross-table-merge`为 `true`,该参数支持动态修改。 + + > **注意:** + > + > 在开启 `placement-rules`后,请合理切换 `txn`和 `raw`,避免无法正常解码 key。 + +- 对于 3.0.4 和 2.1.16 以前的版本,Region 中 Key 的个数(`approximate_keys`)在特定情况下(大部分发生在删表之后)统计不准确,造成 keys 的统计值很大,无法满足 `max-merge-region-keys` 的约束。你可以通过调大 `max-merge-region-keys` 来避免这个问题。 + +### TiKV 节点故障处理策略 + +没有人工介入时,PD 处理 TiKV 节点故障的默认行为是,等待半小时之后(可通过 `max-store-down-time` 配置调整),将此节点设置为 Down 状态,并开始为涉及到的 Region 补充副本。 + +实践中,如果能确定这个节点的故障是不可恢复的,可以立即做下线处理,这样 PD 能尽快补齐副本,降低数据丢失的风险。与之相对,如果确定这个节点是能恢复的,但可能半小时之内来不及,则可以把 `max-store-down-time` 临时调整为比较大的值,这样能避免超时之后产生不必要的副本补充,造成资源浪费。 diff --git a/best-practices/tidb-best-practices.md b/best-practices/tidb-best-practices.md new file mode 100644 index 000000000000..01eb8d85410d --- /dev/null +++ b/best-practices/tidb-best-practices.md @@ -0,0 +1,200 @@ +--- +title: TiDB 最佳实践 +category: reference +--- + +# TiDB 最佳实践 + +本文档总结使用 TiDB 时的一些最佳实践,主要涉及 SQL 使用和 OLAP/OLTP 优化技巧,特别是一些 TiDB 专有的优化开关。 + +建议先阅读讲解 TiDB 原理的三篇文章([讲存储](https://pingcap.com/blog-cn/tidb-internal-1/),[说计算](https://pingcap.com/blog-cn/tidb-internal-2/),[谈调度](https://pingcap.com/blog-cn/tidb-internal-3/)),再来看这篇文章。 + +## 前言 + +数据库是一个通用的基础组件,在开发过程中会考虑到多种目标场景,在具体的业务场景中,需要根据业务的实际情况对数据的参数或者使用方式进行调整。 + +TiDB 是一个兼容 MySQL 协议和语法的分布式数据库,但是由于其内部实现,特别是支持分布式存储以及分布式事务,使得一些使用方法和 MySQL 有所区别。 + +## 基本概念 + +TiDB 的最佳实践与其实现原理密切相关,建议读者先了解一些基本的实现机制,包括 Raft、分布式事务、数据分片、负载均衡、SQL 到 KV 的映射方案、二级索引的实现方法、分布式执行引擎。下面会做一点简单的介绍,更详细的信息可以参考 PingCAP 公众号以及知乎专栏的一些文章。 + +### Raft + +Raft 是一种一致性协议,能提供强一致的数据复制保证,TiDB 最底层用 Raft 来同步数据。每次写入都要写入多数副本,才能对外返回成功,这样即使丢掉少数副本,也能保证系统中还有最新的数据。比如最大 3 副本的话,每次写入 2 副本才算成功,任何时候,只丢失一个副本的情况下,存活的两个副本中至少有一个具有最新的数据。 + +相比 Master-Slave 方式的同步,同样是保存三副本,Raft 的方式更为高效,写入的延迟取决于最快的两个副本,而不是最慢的那个副本。所以使用 Raft 同步的情况下,异地多活成为可能。在典型的两地三中心场景下,每次写入只需要本数据中心以及离得近的一个数据中心写入成功就能保证数据的一致性,而并不需要三个数据中心都写成功。但是这并不意味着在任何场景都能构建跨机房部署的业务,当写入量比较大时候,机房之间的带宽和延迟成为关键因素,如果写入速度超过机房之间的带宽,或者是机房之间延迟过大,整个 Raft 同步机制依然无法很好的运转。 + +### 分布式事务 + +TiDB 提供完整的分布式事务,事务模型是在 [Google Percolator](https://research.google.com/pubs/pub36726.html) 的基础上做了一些优化。具体的实现可以参考[《Percolator 和 TiDB 事务算法》](https://pingcap.com/blog-cn/percolator-and-txn/)这篇文章。本文档只讨论以下几点: + ++ 乐观锁 + + TiDB 的乐观事务模型,只有在真正提交的时候,才会做冲突检测。如果有冲突,则需要重试。这种模型在冲突严重的场景下,会比较低效,因为重试之前的操作都是无效的,需要重复做。举一个比较极端的例子,就是把数据库当做计数器用,如果访问的并发度比较高,那么一定会有严重的冲突,导致大量的重试甚至是超时。但是如果访问冲突并不十分严重,那么乐观锁模型具备较高的效率。在冲突严重的场景下,推荐使用悲观锁,或在系统架构层面解决问题,比如将计数器放在 Redis 中。 + ++ 悲观锁 + + TiDB 的悲观事务模型,悲观事务的行为和 MySQL 基本一致,在执行阶段就会上锁,先到先得,避免冲突情况下的重试,可以保证有较多冲突的事务的成功率。悲观锁同时解决了希望通过 `select for update` 对数据提前锁定的场景。但如果业务场景本身冲突较少,乐观锁的性能会更有优势。 + ++ 事务大小限制 + + 由于分布式事务要做两阶段提交,并且底层还需要做 Raft 复制,如果一个事务非常大,会使得提交过程非常慢,并且会卡住下面的 Raft 复制流程。为了避免系统出现被卡住的情况,我们对事务的大小做了限制: + + - 单个事务包含的 SQL 语句不超过 5000 条(默认) + - 单条 KV entry 不超过 6MB + - KV entry 的总大小不超过 10G + + 在 Google 的 Cloud Spanner 上面,也有[类似的限制](https://cloud.google.com/spanner/docs/limits)。 + +### 数据分片 + +TiKV 自动将底层数据按照 Key 的 Range 进行分片。每个 Region 是一个 Key 的范围,从 `StartKey` 到 `EndKey` 的左闭右开区间。Region 中的 Key-Value 总量超过一定值,就会自动分裂。这部分用户不需要担心。 + +### 负载均衡 + +PD 会根据整个 TiKV 集群的状态,对集群的负载进行调度。调度是以 Region 为单位,以 PD 配置的策略为调度逻辑,自动完成。 + +### SQL on KV + +TiDB 自动将 SQL 结构映射为 KV 结构。具体的可以参考[《三篇文章了解 TiDB 技术内幕 - 说计算》](https://pingcap.com/blog-cn/tidb-internal-2/)这篇文档。简单来说,TiDB 执行了以下操作: + ++ 一行数据映射为一个 KV,Key 以 `TableID` 构造前缀,以行 ID 为后缀 ++ 一条索引映射为一个 KV,Key 以 `TableID+IndexID` 构造前缀,以索引值构造后缀 + +可以看到,对于一个表中的数据或者索引,会具有相同的前缀,这样在 TiKV 的 Key 空间内,这些 Key-Value 会在相邻的位置。那么当写入量很大,并且集中在一个表上面时,就会造成写入的热点,特别是连续写入的数据中某些索引值也是连续的(比如 update time 这种按时间递增的字段),会在很少的几个 Region 上形成写入热点,成为整个系统的瓶颈。同样,如果所有的数据读取操作也都集中在很小的一个范围内 (比如在连续的几万或者十几万行数据上),那么可能造成数据的访问热点。 + +### 二级索引 + +TiDB 支持完整的二级索引,并且是全局索引,很多查询可以通过索引来优化。如果利用好二级索引,对业务非常重要,很多 MySQL 上的经验在 TiDB 这里依然适用,不过 TiDB 还有一些自己的特点,需要注意,这一节主要讨论在 TiDB 上使用二级索引的一些注意事项。 + ++ 二级索引是否越多越好 + + 二级索引能加速查询,但是要注意新增一个索引是有副作用的,上一节介绍了索引的存储模型,那么每增加一个索引,在插入一条数据的时候,就要新增一个 Key-Value,所以索引越多,写入越慢,并且空间占用越大。另外过多的索引也会影响优化器运行时间,并且不合适的索引会误导优化器。所以索引并不是越多越好。 + ++ 对哪些列建索引比较合适 + + 上文提到,索引很重要但不是越多越好,因此需要根据具体的业务特点创建合适的索引。原则上需要对查询中需要用到的列创建索引,目的是提高性能。下面几种情况适合创建索引: + + - 区分度比较大的列,通过索引能显著地减少过滤后的行数 + - 有多个查询条件时,可以选择组合索引,注意需要把等值条件的列放在组合索引的前面 + + 这里举一个例子,假设常用的查询是 `select * from t where c1 = 10 and c2 = 100 and c3 > 10`, 那么可以考虑建立组合索引 `Index cidx (c1, c2, c3)`,这样可以用查询条件构造出一个索引前缀进行 Scan。 + ++ 通过索引查询和直接扫描 Table 的区别 + + TiDB 实现了全局索引,所以索引和 Table 中的数据并不一定在一个数据分片上,通过索引查询的时候,需要先扫描索引,得到对应的行 ID,然后通过行 ID 去取数据,所以可能会涉及到两次网络请求,会有一定的性能开销。 + + 如果查询涉及到大量的行,那么扫描索引是并发进行,只要第一批结果已经返回,就可以开始去取 Table 的数据,所以这里是一个并行 + Pipeline 的模式,虽然有两次访问的开销,但是延迟并不会很大。 + + 以下情况不会涉及到两次访问的问题: + + - 索引中的列已经满足了查询需求。比如 Table `t` 上面的列 `c` 有索引,查询是 `select c from t where c > 10;`,这个时候,只需要访问索引,就可以拿到所需要的全部数据。这种情况称之为覆盖索引 (Covering Index)。所以如果很关注查询性能,可以将部分不需要过滤但是需要在查询结果中返回的列放入索引中,构造成组合索引,比如这个例子: `select c1, c2 from t where c1 > 10;`,要优化这个查询可以创建组合索引 `Index c12 (c1, c2)`。 + - 表的 Primary Key 是整数类型。在这种情况下,TiDB 会将 Primary Key 的值当做行 ID,所以如果查询条件是在 PK 上面,那么可以直接构造出行 ID 的范围,直接扫描 Table 数据,获取结果。 + ++ 查询并发度 + + 数据分散在很多 Region 上,所以 TiDB 在做查询的时候会并发进行,默认的并发度比较保守,因为过高的并发度会消耗大量的系统资源,且对于 OLTP 类型的查询,往往不会涉及到大量的数据,较低的并发度已经可以满足需求。对于 OLAP 类型的 Query,往往需要较高的并发度。所以 TiDB 支持通过 System Variable 来调整查询并发度。 + + - [tidb_distsql_scan_concurrency](/tidb-specific-system-variables.md#tidb_distsql_scan_concurrency) + + 在进行扫描数据的时候的并发度,这里包括扫描 Table 以及索引数据。 + + - [tidb_index_lookup_size](/tidb-specific-system-variables.md#tidb_index_lookup_size) + + 如果是需要访问索引获取行 ID 之后再访问 Table 数据,那么每次会把一批行 ID 作为一次请求去访问 Table 数据,这个参数可以设置 Batch 的大小,较大的 Batch 会使得延迟增加,较小的 Batch 可能会造成更多的查询次数。这个参数的合适大小与查询涉及的数据量有关。一般不需要调整。 + + - [tidb_index_lookup_concurrency](/tidb-specific-system-variables.md#tidb_index_lookup_concurrency) + + 如果是需要访问索引获取行 ID 之后再访问 Table 数据,每次通过行 ID 获取数据时候的并发度通过这个参数调节。 + ++ 通过索引保证结果顺序 + + 索引除了可以用来过滤数据之外,还能用来对数据排序,首先按照索引的顺序获取行 ID,然后再按照行 ID 的返回顺序返回行的内容,这样可以保证返回结果按照索引列有序。前面提到了扫索引和获取 Row 之间是并行 + Pipeline 模式,如果要求按照索引的顺序返回 Row,那么这两次查询之间的并发度设置的太高并不会降低延迟,所以默认的并发度比较保守。可以通过 [tidb_index_serial_scan_concurrency](/tidb-specific-system-variables.md#tidb_index_serial_scan_concurrency) 变量进行并发度调整。 + ++ 逆序索引 + + 目前 TiDB 支持对索引进行逆序 Scan,目前速度比顺序 Scan 慢一些,通常情况下慢 20%,在数据频繁修改造成版本较多的情况下,会慢的更多。如果可能,建议避免对索引的逆序 Scan。 + +## 场景与实践 + +上一节我们讨论了一些 TiDB 基本的实现机制及其对使用带来的影响,本节我们从具体的使用场景出发,谈一些更为具体的操作实践。我们以从部署到支撑业务这条链路为序,进行讨论。 + +### 部署 + +在部署之前请务必阅读 [TiDB 部署建议以及对硬件的需求](/hardware-and-software-requirements.md)。 + +推荐通过 [TiUP](/production-deployment-using-tiup.md) 部署 TiDB 集群,这个工具可以部署、停止、销毁、升级整个集群,非常方便易用。非常不推荐手动部署,后期的维护和升级会很麻烦。 + +### 导入数据 + +为了提高导入数据期间的写入性能,可以对 TiKV 的参数进行调优,具体的文档查看 [TiKV 性能参数调优](/tune-tikv-memory-performance.md)。 + +### 写入 + +上面提到了 TiDB 对单个事务的大小有限制,这层限制是在 KV 层面,反映在 SQL 层面的话,简单来说一行数据会映射为一个 KV entry,每多一个索引,也会增加一个 KV entry。 + +> **注意**: +> +> 对事务的大小限制,要考虑 TiDB 做编码以及事务额外 Key 的开销,在使用的时候,**建议每个事务的行数不超过 200 行,且单行数据小于 100k**,否则可能性能不佳。 + +建议无论是 Insert,Update 还是 Delete 语句,都通过分 Batch 或者是加 Limit 的方式限制。 + +在删除大量数据的时候,建议使用 `Delete * from t where xx limit 5000;` 这样的方案,通过循环来删除,用 `Affected Rows == 0` 作为循环结束条件。 + +如果一次删除的数据量非常大,这种循环的方式会越来越慢,因为每次删除都是从前向后遍历,前面的删除之后,短时间内会残留不少删除标记(后续会被 GC 清理掉),影响后面的 `Delete` 语句。如果有可能,建议把 `Where` 条件细化。举个例子,假设要删除 2017-05-26 当天的所有数据,那么可以这样做: + +```SQL +for i from 0 to 23: + while affected_rows > 0: + delete * from t where insert_time >= i:00:00 and insert_time < (i+1):00:00 limit 5000; + affected_rows = select affected_rows() +``` + +上面是一段伪代码,意思就是要把大块的数据拆成小块删除,以避免删除过程中前面的 Delete 语句影响后面的 Delete 语句。 + +### 查询 + +看业务的查询需求以及具体的语句,可以参考 [TiDB 专用系统变量和语法](/tidb-specific-system-variables.md)这篇文档 +可以通过 SET 语句控制 SQL 执行的并发度,另外通过 Hint 控制 Join 物理算子选择。 + +另外 MySQL 标准的索引选择 Hint 语法,也可以用,通过 `Use Index/Ignore Index hint` 控制优化器选择索引。 + +如果是个 OLTP 和 OLAP 混合类型的业务,可以把 TP 请求和 AP 请求发送到不同的 tidb-server 上,这样能够减小 AP 业务对于 TP 业务的影响。 承载 AP 业务的 tidb-server 推荐使用高配的机器,比如 CPU 核数比较多,内存比较大。 + +但彻底的隔离 OLTP 和 OLAP,推荐将 OLAP 的业务跑在 TiFlash 上。TiFlash 是列存引擎,在 OLAP 的分析查询场景上,性能极具亮点,TiFlash 可以在存储层上做到物理隔离,并可做到一致性读取。 + +### 监控和日志 + +Metrics 系统是了解系统状态的最佳方法,建议所有的用户都部署监控系统。 + +TiDB [使用 Grafana + Prometheus 监控系统状态](/tidb-monitoring-framework.md)。如果使用 TiUP 部署集群,那么会自动部署和配置监控系统。 + +监控系统中的监控项很多,大部分是给 TiDB 开发者查看的内容,如果没有对源代码比较深入的了解,并没有必要了解这些监控项。我们会精简出一些和业务相关或者是系统关键组件状态相关的监控项,放在一个独立的 `overview` 面板中,供用户使用。 + +除了监控之外,查看日志也是了解系统状态的常用方法。TiDB 的三个组件 tidb-server/tikv-server/pd-server 都有一个 `--log-file` 的参数。如果启动的时候设置了这个参数,那么日志会保存着参数所设置的文件的位置,另外会自动的按天对 Log 文件做归档。如果没有设置 `--log-file` 参数,日志会输出在 `stderr` 中。 + +从 4.0 版本开始,从解决易用性的角度出发,提供了 Dashboard UI 系统,通过浏览器访问 `http://PD_IP:PD_PORT/dashboard` 即可打开 TiDB Dashboard。Dashboard 可以提供集群状态、性能分析、流量可视化、SQL 诊断、日志搜索等功能。 + +### 文档 + +了解一个系统或者解决使用中的问题最好的方法是阅读文档,明白实现原理。TiDB 有大量的官方文档,希望大家在遇到问题的时候能先尝试通过文档或者搜索 Issue list 寻找解决方案。官方文档查看 [docs-cn](https://github.com/pingcap/docs-cn)。如果希望阅读英文文档,可以查看 [docs](https://github.com/pingcap/docs)。 + +其中的 [FAQ](/faq/tidb-faq.md) +和[故障诊断](/troubleshoot-tidb-cluster.md)章节建议大家仔细阅读。另外 TiDB 还有一些不错的工具,也有配套的文档,具体的见各项工具的 GitHub 页面。 + +除了文档之外,还有很多不错的文章介绍 TiDB 的各项技术细节内幕,大家可以关注下面这些文章发布渠道: + ++ 公众号:微信搜索 PingCAP ++ 知乎专栏:[TiDB 的后花园](https://zhuanlan.zhihu.com/newsql) ++ [官方博客](https://pingcap.github.io/blog/) + +## TiDB 的最佳适用场景 + +简单来说,TiDB 适合具备下面这些特点的场景: + ++ 数据量大,单机保存不下 ++ 不希望做 Sharding 或者懒得做 Sharding ++ 访问模式上没有明显的热点 ++ 需要事务、需要强一致、需要灾备 ++ 希望 Real-Time HTAP,减少存储链路 diff --git a/blacklist-control-plan.md b/blacklist-control-plan.md new file mode 100644 index 000000000000..04ecf8a227e5 --- /dev/null +++ b/blacklist-control-plan.md @@ -0,0 +1,246 @@ +--- +title: 优化规则与表达式下推的黑名单 +summary: 了解优化规则与表达式下推的黑名单。 +category: performance +--- + +# 优化规则与表达式下推的黑名单 + +本文主要介绍优化规则的黑名单与表达式下推的黑名单。 + +## 优化规则黑名单 + +**优化规则黑名单**是针对优化规则的调优手段之一,主要用于手动禁用一些优化规则。 + +### 重要的优化规则 + +|**优化规则**|**规则名称**|**简介**| +| :--- | :--- | :--- | +| 列裁剪 | column_prune | 对于上层算子不需要的列,不在下层算子输出该列,减少计算 | +| 子查询去关联 | decorrelate | 尝试对相关子查询进行改写,将其转换为普通 join 或 aggression 计算 | +| 聚合消除 | aggregation_eliminate | 尝试消除执行计划中的某些不必要的聚合算子 | +| 投影消除 | projection_eliminate | 消除执行计划中不必要的投影算子 | +| 最大最小消除 | max_min_eliminate | 改写聚合中的 max/min 计算,转化为 `order by` + `limit 1` | +| 谓词下推 | predicate_push_down | 尝试将执行计划中过滤条件下推到离数据源更近的算子上 | +| 外连接消除 | outer_join_eliminate | 尝试消除执行计划中不必要的 left join 或者 right join | +| 分区裁剪 | partition_processor | 将分区表查询改成为用 union all,并裁剪掉不满足过滤条件的分区 | +| 聚合下推 | aggregation_push_down | 尝试将执行计划中的聚合算子下推到更底层的计算节点 | +| TopN 下推 | topn_push_down | 尝试将执行计划中的 TopN 算子下推到离数据源更近的算子上 | +| Join 重排序 | join_reorder | 对多表 join 确定连接顺序 | + +### 禁用优化规则 + +当某些优化规则在一些特殊查询中的优化结果不理想时,可以使用**优化规则黑名单**禁用一些优化规则。 + +#### 使用方法 + +> **注意:** +> +> 以下操作都需要数据库的 super privilege 权限。每个优化规则都有各自的名字,比如列裁剪的名字是 "column_prune"。所有优化规则的名字都可以在[重要的优化规则](#重要的优化规则)表格中第二列查到。 + +- 如果你想禁用某些规则,可以在 `mysql.opt_rule_blacklist` 表中写入规则的名字,例如: + + {{< copyable "sql" >}} + + ```sql + insert into mysql.opt_rule_blacklist values("join_reorder"), ("topn_push_down"); + ``` + + 执行以下 SQL 语句可让禁用规则立即生效,包括相应 TiDB Server 的所有旧链接: + + {{< copyable "sql" >}} + + ```sql + admin reload opt_rule_blacklist; + ``` + + > **注意:** + > + > `admin reload opt_rule_blacklist` 只对执行该 SQL 语句的 TiDB server 生效。若需要集群中所有 TiDB server 生效,需要在每台 TiDB server 上执行该 SQL 语句。 + +- 需要解除一条规则的禁用时,需要删除表中禁用该条规则的相应数据,再执行 `admin reload`: + + {{< copyable "sql" >}} + + ```sql + delete from mysql.opt_rule_blacklist where name in ("join_reoder", "topn_push_down"); + admin reload opt_rule_blacklist; + ``` + +## 表达式下推黑名单 + +**表达式下推黑名单**是针对表达式下推的调优手段之一,主要用于对于某些存储类型手动禁用一些表达式。 + +### 已支持下推的表达式 + +| 表达式分类 | 具体操作 | +| :-------------- | :------------------------------------- | +| [逻辑运算](/functions-and-operators/operators.md#逻辑操作符) | AND (&&), OR (||), NOT (!) | +| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | <, <=, =, != (`<>`), >, >=, [`<=>`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal-to), [`IN()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in), IS NULL, LIKE, IS TRUE, IS FALSE, [`COALESCE()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce) | +| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | +, -, *, /, [`ABS()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs), [`CEIL()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil), [`CEILING()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceiling), [`FLOOR()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor) | +| [控制流运算](/functions-and-operators/control-flow-functions.md) | [`CASE`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#operator_case), [`IF()`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_if), [`IFNULL()`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_ifnull) | +| [JSON 运算](/functions-and-operators/json-functions.md) | [JSON_TYPE(json_val)][json_type],
[JSON_EXTRACT(json_doc, path[, path] ...)][json_extract],
[JSON_UNQUOTE(json_val)][json_unquote],
[JSON_OBJECT(key, val[, key, val] ...)][json_object],
[JSON_ARRAY([val[, val] ...])][json_array],
[JSON_MERGE(json_doc, json_doc[, json_doc] ...)][json_merge],
[JSON_SET(json_doc, path, val[, path, val] ...)][json_set],
[JSON_INSERT(json_doc, path, val[, path, val] ...)][json_insert],
[JSON_REPLACE(json_doc, path, val[, path, val] ...)][json_replace],
[JSON_REMOVE(json_doc, path[, path] ...)][json_remove] | +| [日期运算](/functions-and-operators/date-and-time-functions.md) | [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format) | + +### 禁止特定表达式下推 + +当函数的计算过程由于下推而出现异常时,可通过黑名单功能禁止其下推来快速恢复业务。具体而言,你可以将上述支持的函数或运算符名加入黑名单 `mysql.expr_pushdown_blacklist` 中,以禁止特定表达式下推。 + +`mysql.expr_pushdown_blacklist` 的 schema 如下: + +{{< copyable "sql" >}} + +```sql +desc mysql.expr_pushdown_blacklist; +``` + +```sql ++------------+--------------+------+------+-------------------+-------+ +| Field | Type | Null | Key | Default | Extra | ++------------+--------------+------+------+-------------------+-------+ +| name | char(100) | NO | | NULL | | +| store_type | char(100) | NO | | tikv,tiflash,tidb | | +| reason | varchar(200) | YES | | NULL | | ++------------+--------------+------+------+-------------------+-------+ +3 rows in set (0.00 sec) +``` + +以上结果字段解释如下: + ++ `name`:禁止下推的函数名。 ++ `store_type`:用于指明希望禁止该函数下推到哪些组件进行计算。组件可选 `tidb`、`tikv` 和 `tiflash`。`store_type` 不区分大小写,如果需要禁止向多个存储引擎下推,各个存储之间需用逗号隔开。 + - `store_type` 为 `tidb` 时表示在读取 TiDB 内存表时,是否允许该函数在其他 TiDB Server 上执行。 + - `store_type` 为 `tikv` 时表示是否允许该函数在 TiKV Server 的 Coprocessor 模块中执行。 + - `store_type` 为 `tiflash` 时表示是否允许该函数在 TiFlash Server 的 Coprocessor 模块中执行。 ++ `reason`:用于记录该函数被加入黑名单的原因。 + +### 使用方法 + +#### 加入黑名单 + +如果要将一个或多个函数或运算符加入黑名单,执行以下步骤: + +1. 向 `mysql.expr_pushdown_blacklist` 插入对应的函数名或运算符名以及希望禁止下推的存储引擎集合。 + +2. 执行 `admin reload expr_pushdown_blacklist;`。 + +#### 移出黑名单 + +如果要将一个或多个函数及运算符移出黑名单,执行以下步骤: + +1. 从 `mysql.expr_pushdown_blacklist` 表中删除对应的函数名或运算符名。 + +2. 执行 `admin reload expr_pushdown_blacklist;`。 + +> **注意:** +> +> `admin reload expr_pushdown_blacklist` 只对执行该 SQL 语句的 TiDB server 生效。若需要集群中所有 TiDB server 生效,需要在每台 TiDB server 上执行该 SQL 语句。 + +### 表达式黑名单用法示例 + +以下示例首先将运算符 `<` 及 `>` 加入黑名单,然后将运算符 `>` 从黑名单中移出。 + +黑名单是否生效可以从 `explain` 结果中进行观察(参见[如何理解 `explain` 结果](/query-execution-plan.md))。 + +1. 对于以下 SQL 语句,`where` 条件中的 `a < 2` 和 `a > 2` 可以下推到 TiKV 进行计算。 + + {{< copyable "sql" >}} + + ```sql + explain select * from t where a < 2 and a > 2; + ``` + + ```sql + +-------------------------+----------+-----------+---------------+------------------------------------+ + | id | estRows | task | access object | operator info | + +-------------------------+----------+-----------+---------------+------------------------------------+ + | TableReader_7 | 0.00 | root | | data:Selection_6 | + | └─Selection_6 | 0.00 | cop[tikv] | | gt(ssb_1.t.a, 2), lt(ssb_1.t.a, 2) | + | └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | + +-------------------------+----------+-----------+---------------+------------------------------------+ + 3 rows in set (0.00 sec) + ``` + +2. 往 `mysql.expr_pushdown_blacklist` 表中插入禁用表达式,并且执行 `admin reload expr_pushdown_blacklist`。 + + {{< copyable "sql" >}} + + ```sql + insert into mysql.expr_pushdown_blacklist values('<','tikv',''), ('>','tikv',''); + ``` + + ```sql + Query OK, 2 rows affected (0.01 sec) + Records: 2 Duplicates: 0 Warnings: 0 + ``` + + {{< copyable "sql" >}} + + ```sql + admin reload expr_pushdown_blacklist; + ``` + + ```sql + Query OK, 0 rows affected (0.00 sec) + ``` + +3. 重新观察执行计划,发现表达式下推黑名单生效,`where` 条件中的 `<` 和 `>` 没有被下推到 TiKV Coprocessor 上。 + + {{< copyable "sql" >}} + + ```sql + explain select * from t where a < 2 and a > 2; + ``` + + ```sql + +-------------------------+----------+-----------+---------------+------------------------------------+ + | id | estRows | task | access object | operator info | + +-------------------------+----------+-----------+---------------+------------------------------------+ + | Selection_7 | 10000.00 | root | | gt(ssb_1.t.a, 2), lt(ssb_1.t.a, 2) | + | └─TableReader_6 | 10000.00 | root | | data:TableFullScan_5 | + | └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | + +-------------------------+----------+-----------+---------------+------------------------------------+ + 3 rows in set (0.00 sec) + ``` + +4. 将某一表达式(`>` 大于)禁用规则从黑名单表中删除,并且执行 `admin reload expr_pushdown_blacklist`。 + + {{< copyable "sql" >}} + + ```sql + delete from mysql.expr_pushdown_blacklist where name = '>'; + ``` + + ```sql + Query OK, 1 row affected (0.01 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + admin reload expr_pushdown_blacklist; + ``` + + ```sql + Query OK, 0 rows affected (0.00 sec) + ``` + +5. 重新观察执行计划,`<` 和 `>` 表达式又可以重新被下推到 TiKV Coprocessor。 + + {{< copyable "sql" >}} + + ```sql + explain select * from t where a < 2 and a > 2; + ``` + + ```sql + +---------------------------+----------+-----------+---------------+--------------------------------+ + | id | estRows | task | access object | operator info | + +---------------------------+----------+-----------+---------------+--------------------------------+ + | Selection_8 | 0.00 | root | | lt(ssb_1.t.a, 2) | + | └─TableReader_7 | 0.00 | root | | data:Selection_6 | + | └─Selection_6 | 0.00 | cop[tikv] | | gt(ssb_1.t.a, 2) | + | └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | + +---------------------------+----------+-----------+---------------+--------------------------------+ + 4 rows in set (0.00 sec) + ``` diff --git a/br/backup-and-restore-faq.md b/br/backup-and-restore-faq.md new file mode 100644 index 000000000000..22b454ad8422 --- /dev/null +++ b/br/backup-and-restore-faq.md @@ -0,0 +1,59 @@ +--- +title: Backup & Restore 常见问题 +summary: BR 相关的常见问题以及解决方法。 +category: FAQ +--- + +# Backup & Restore 常见问题 + +本文列出了在使用 Backup & Restore (BR) 时,可能会遇到的问题及相应的解决方法。 + +如果遇到未包含在此文档且无法解决的问题,可以在 [AskTUG](http://asktug.com) 社区中提问。 + +## 恢复的时候,报错 `could not read local://...:download sst failed`,该如何处理? + +在恢复的时候,每个节点都必须能够访问到**所有**的备份文件(SST files),默认情况下,假如使用 local storage,备份文件会分散在各个节点中,此时是无法直接恢复的,必须将每个 TiKV 节点的备份文件拷贝到其它所有 TiKV 节点才能恢复。 + +建议在备份的时候挂载一块 NFS 网盘作为备份盘,详见[将单表数据备份到网络盘](/br/backup-and-restore-use-cases.md#将单表数据备份到网络盘推荐)。 + +## BR 备份时,对集群影响多大? + +使用 `sysbench` 的 `oltp_read_only` 场景全速备份到非服务盘,对集群的影响依照表结构的不同,对集群 QPS 的影响在 15%~25% 之间。 + +如果需要控制备份带来的影响,可以使用 `--ratelimit` 参数限速。 + +## BR 会备份系统表吗?在数据恢复的时候,这些系统表会冲突吗? + +全量备份的时候会过滤掉系统库(`information_schema`,`performance_schema`,`mysql`)。参考[备份原理](/br/backup-and-restore-tool.md#备份原理)。 + +因为这些系统库根本不可能存在于备份中,恢复的时候自然不可能发生冲突。 + +## BR 遇到 Permission denied 错误,即使用 root 运行 BR 也无法解决,该如何处理? + +需要确认 TiKV 是否有访问备份目录的权限。如果是备份,确认是否有写权限;如果是恢复,确认是否有读权限。 + +使用 root 运行 BR 仍旧有可能会因为磁盘权限而失败,因为备份文件 (SST) 的保存是由 TiKV 执行的。 + +> **注意:** +> +> 在恢复的时候也可能遇到同样的问题。 +> +> 使用 BR 进行数据的恢复时,检验读权限的时机是在第一次读取 SST 文件时,考虑到执行 DDL 的耗时,这个时刻可能会离开始运行 BR 的时间很远。这样可能会出现等了很长时间之后遇到 Permission denied 错误失败的情况。 +> +> 因此,最好在恢复前提前检查权限。 + +## BR 遇到错误信息 `Io(Os...)`,该如何处理? + +这类问题几乎都是 TiKV 在写盘的时候遇到的系统调用错误。检查备份目录的挂载方式和文件系统,试试看备份到其它文件夹或者其它硬盘。 + +目前已知备份到 samba 搭建的网盘时可能会遇到 `Code: 22(invalid argument)` 错误。 + +## 使用 local storage 的时候,BR 备份的文件会存在哪里? + +在使用 local storage 的时候,会在运行 BR 的节点生成 `backupmeta`,在各个 Region 的 Leader 节点生成备份文件。 + +## 备份数据有多大,备份会有副本吗? + +备份的时候仅仅在每个 Region 的 Leader 处生成该 Region 的备份文件。因此备份的大小等于数据大小,不会有多余的副本数据。所以最终的总大小大约是 TiKV 数据总量除以副本数。 + +但是假如想要从本地恢复数据,因为每个 TiKV 都必须要能访问到所有备份文件,在最终恢复的时候会有等同于恢复时 TiKV 节点数量的副本。 diff --git a/br/backup-and-restore-tool.md b/br/backup-and-restore-tool.md new file mode 100644 index 000000000000..aa6519bf9f04 --- /dev/null +++ b/br/backup-and-restore-tool.md @@ -0,0 +1,592 @@ +--- +title: 使用 BR 进行备份与恢复 +summary: 了解如何使用 BR 工具进行集群数据备份和恢复。 +category: how-to +aliases: ['/docs-cn/stable/reference/tools/br/br/'] +--- + +# 使用 BR 进行备份与恢复 + +Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行数据备份和恢复。相比 [`mydumper`/`loader`](/backup-and-restore-using-mydumper-lightning.md),BR 更适合大数据量的场景。本文档介绍了 BR 的使用限制、工作原理、命令行描述、备份恢复用例以及最佳实践。 + +## 使用限制 + +- BR 只支持 TiDB v3.1 及以上版本。 +- 目前只支持在全新的集群上执行恢复操作。 +- BR 备份最好串行执行,否则不同备份任务之间会相互影响。 + +## 推荐部署配置 + +- 推荐 BR 部署在 PD 节点上。 +- 推荐使用一块高性能 SSD 网盘,挂载到 BR 节点和所有 TiKV 节点上,网盘推荐万兆网卡,否则带宽有可能成为备份恢复时的性能瓶颈。 + +## 下载 Binary + +详见[下载链接](/download-ecosystem-tools.md#快速备份和恢复br)。 + +## 工作原理 + +BR 是分布式备份恢复的工具,它将备份或恢复操作命令下发到各个 TiKV 节点。TiKV 收到命令后执行相应的备份或恢复操作。在一次备份或恢复中,各个 TiKV 节点都会有一个对应的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。 + +### 备份原理 + +BR 执行备份操作时,会先从 PD 获取到以下信息: + +- 当前的 TS 作为备份快照的时间点 +- 当前集群的 TiKV 节点信息 + +然后 BR 根据这些信息,在内部启动一个 TiDB 实例,获取对应 TS 的数据库或表信息,同时过滤掉系统库 (`information_schema`,`performance_schema`,`mysql`)。 + +此时根据备份子命令,会有两种备份逻辑: + +- 全量备份:BR 遍历全部库表,并且根据每一张表构建需要备份的 KV Range +- 单表备份:BR 根据该表构建需要备份的 KV Range + +最后,BR 将需要备份的 KV Range 收集后,构造完整的备份请求分发给集群内的 TiKV 节点。 + +该请求的主要结构如下: + +``` +BackupRequest{ + ClusterId, // 集群 ID + StartKey, // 备份起始点,startKey 会被备份 + EndKey, // 备份结束点,endKey 不会被备份 + StartVersion, // 上一次备份快照的版本,用于增量备份 + EndVersion, // 备份快照时间点 + StorageBackend, // 备份文件存储地址 + RateLimit, // 备份速度 (MB/s) +} +``` + +TiKV 节点收到备份请求后,会遍历节点上所有的 Region Leader,找到和请求中 KV Range 有重叠范围的 Region,将该范围下的部分或者全部数据进行备份,在备份路径下生成对应的 SST 文件。 + +TiKV 节点在备份完对应 Region Leader 的数据后将元信息返回给 BR。BR 将这些元信息收集并存储进 `backupmeta` 文件中,等待恢复时使用。 + +假如 `StartVersion` 不为 0,这次备份会被视作增量备份。BR 除了收集 KV 以外,还会收集 `[StartVersion, EndVersion)` 之间的 DDL,在进行恢复的时候,会先恢复这些 DDL。 + +如果执行命令时开启了 checksum,那么 BR 在最后会对备份的每一张表计算 checksum 用于校验。 + +#### 备份文件类型 + +备份路径下会生成以下两种类型文件: + +- SST 文件:存储 TiKV 备份下来的数据信息 +- `backupmeta` 文件:存储本次备份的元信息,包括备份文件数、备份文件的 Key 区间、备份文件大小和备份文件 Hash (sha256) 值 + +#### SST 文件命名格式 + +SST 文件以 `storeID_regionID_regionEpoch_keyHash_cf` 的格式命名。格式名的解释如下: + +- storeID:TiKV 节点编号 +- regionID:Region 编号 +- regionEpoch:Region 版本号 +- keyHash:Range startKey 的 Hash (sha256) 值,确保唯一性 +- cf:RocksDB 的 ColumnFamily(默认为 `default` 或 `write`) + +### 恢复原理 + +BR 执行恢复操作时,会按顺序执行以下任务: + +1. 解析备份路径下的 backupMeta 文件,根据解析出来的库表信息,在内部启动一个 TiDB 实例在新集群创建对应的库表。 + +2. 把解析出来的 SST 文件,根据表进行聚合。 + +3. 根据 SST 文件的 Key Range 进行预切分 Region,使得每个 Region 至少对应一个 SST 文件。 + +4. 遍历要恢复的每一张表,以及这个表对应的 SST 文件。 + +5. 找到该文件对应的 Region,发送下载文件的请求到对应的 TiKV 节点,并在下载成功后,发送加载请求。 + +TiKV 收到加载 SST 文件的请求后,利用 Raft 机制保证加载 SST 数据的强一致性。在加载成功后,下载下来的 SST 文件会被异步删除。 + +在执行完恢复操作后,BR 会对恢复后的数据进行 checksum 计算,用于和备份下来的数据进行对比。 + +![br-arch](/media/br-arch.png) + +## BR 命令行描述 + +一条 `br` 命令是由子命令、选项和参数组成的。子命令即不带 `-` 或者 `--` 的字符。选项即以 `-` 或者 `--` 开头的字符。参数即子命令或选项字符后紧跟的、并传递给命令和选项的字符。 + +以下是一条完整的 `br` 命令行: + +`br backup full --pd "${PDIP}:2379" -s "local:///tmp/backup"` + +命令行各部分的解释如下: + +* `backup`:`br` 的子命令 +* `full`:`backup` 的子命令 +* `-s` 或 `--storage`:备份保存的路径 +* `"local:///tmp/backup"`:`-s` 的参数,保存的路径为各个 TiKV 节点本地磁盘的 `/tmp/backup` +* `--pd`:PD 服务地址 +* `"${PDIP}:2379"`:`--pd` 的参数 + +> **注意:** +> +> 在使用 `local` storage 的时候,备份数据会分散在各个节点的本地文件系统中。 +> +> **不建议**在生产环境中备份到本地磁盘,因为在日后恢复的时候,**必须**手动聚集这些数据才能完成恢复工作(见[恢复集群数据](#恢复集群数据))。 +> +> 聚集这些备份数据可能会造成数据冗余和运维上的麻烦,而且在不聚集这些数据便直接恢复的时候会遇到颇为迷惑的 `SST file not found` 报错。 +> +> 建议在各个节点挂载 NFS 网盘,或者直接备份到 `S3` 对象存储中。 + +### 命令和子命令 + +BR 由多层命令组成。目前,BR 包含 `backup`、`restore` 和 `version` 三个子命令: + +* `br backup` 用于备份 TiDB 集群 +* `br restore` 用于恢复 TiDB 集群 +* `br version` 用于查看 BR 工具版本信息 + +以上三个子命令可能还包含这些子命令: + +* `full`:可用于备份或恢复全部数据。 +* `db`:可用于备份或恢复集群中的指定数据库。 +* `table`:可用于备份或恢复集群指定数据库中的单张表。 + +### 常用选项 + +* `--pd`:用于连接的选项,表示 PD 服务地址,例如 `"${PDIP}:2379"`。 +* `-h`/`--help`:获取所有命令和子命令的使用帮助。例如 `br backup --help`。 +* `--ca`:指定 PEM 格式的受信任 CA 的证书文件路径。 +* `--cert`:指定 PEM 格式的 SSL 证书文件路径。 +* `--key`:指定 PEM 格式的 SSL 证书密钥文件路径。 +* `--status-addr`:BR 向 Prometheus 提供统计数据的监听地址。 + +## 备份集群数据 + +使用 `br backup` 命令来备份集群数据。可选择添加 `full` 或 `table` 子命令来指定备份的范围:全部集群数据或单张表的数据。 + +如果备份时间可能超过设定的 [`tikv_gc_life_time`](/garbage-collection-configuration.md#tikv_gc_life_time)(默认 `10m0s`,即表示 10 分钟),则需要将该参数调大。 + +例如,将 `tikv_gc_life_time` 调整为 `720h`: + +{{< copyable "sql" >}} + +```sql +mysql -h${TiDBIP} -P4000 -u${TIDB_USER} ${password_str} -Nse \ + "update mysql.tidb set variable_value='720h' where variable_name='tikv_gc_life_time'"; +``` + +### 备份全部集群数据 + +要备份全部集群数据,可使用 `br backup full` 命令。该命令的使用帮助可以通过 `br backup full -h` 或 `br backup full --help` 来获取。 + +用例:将所有集群数据备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下。 + +> **注意:** +> +> + 经测试,在全速备份的情况下,如果备份盘和服务盘不同,在线备份会让只读线上服务的 QPS 下降 15%~25% 左右。如果希望降低影响,请参考 `--ratelimit` 进行限速。 +> + 假如备份盘和服务盘相同,备份将会和服务争夺 I/O 资源,这可能会让只读线上服务的 QPS 骤降一半以上。请尽量禁止将在线服务的数据备份到 TiKV 的数据盘。 + +{{< copyable "shell-regular" >}} + +```shell +br backup full \ + --pd "${PDIP}:2379" \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --log-file backupfull.log +``` + +以上命令中,`--ratelimit` 选项限制了**每个 TiKV** 执行备份任务的速度上限(单位 MiB/s)。`--log-file` 选项指定把 BR 的 log 写到 `backupfull.log` 文件中。 + +备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。进度条效果如下: + +```shell +br backup full \ + --pd "${PDIP}:2379" \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --log-file backupfull.log +Full Backup <---------/................................................> 17.12%. +``` + +### 备份单个数据库的数据 + +要备份集群中指定单个数据库的数据,可使用 `br backup db` 命令。同样可通过 `br backup db -h` 或 `br backup db --help` 来获取子命令 `db` 的使用帮助。 + +用例:将数据库 `test` 备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下。 + +{{< copyable "shell-regular" >}} + +```shell +br backup db \ + --pd "${PDIP}:2379" \ + --db test \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --log-file backuptable.log +``` + +`db` 子命令的选项为 `--db`,用来指定数据库名。其他选项的含义与[备份全部集群数据](#备份全部集群数据)相同。 + +备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 + +### 备份单张表的数据 + +要备份集群中指定单张表的数据,可使用 `br backup table` 命令。同样可通过 `br backup table -h` 或 `br backup table --help` 来获取子命令 `table` 的使用帮助。 + +用例:将表 `test.usertable` 备份到各个 TiKV 节点的 `/tmp/backup` 路径,同时也会将备份的元信息文件 `backupmeta` 写到该路径下。 + +{{< copyable "shell-regular" >}} + +```shell +br backup table \ + --pd "${PDIP}:2379" \ + --db test \ + --table usertable \ + --storage "local:///tmp/backup" \ + --ratelimit 120 \ + --log-file backuptable.log +``` + +`table` 子命令有 `--db` 和 `--table` 两个选项,分别用来指定数据库名和表名。其他选项的含义与[备份全部集群数据](#备份全部集群数据)相同。 + +备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。 + +### 备份数据到 Amazon S3 后端存储 + +如果备份的存储并不是在本地,而是在 Amazon 的 S3 后端存储,那么需要在 `storage` 子命令中指定 S3 的存储路径,并且赋予 BR 节点和 TiKV 节点访问 Amazon S3 的权限。 + +这里可以参照 [AWS 官方文档](https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/user-guide/create-bucket.html)在指定的 `Region` 区域中创建一个 S3 桶 `Bucket`,如果有需要,还可以参照 [AWS 官方文档](https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/user-guide/create-folder.html) 在 Bucket 中创建一个文件夹 `Folder`。 + +将有权限访问该 S3 后端存储的账号的 `SecretKey` 和 `AccessKey` 作为环境变量传入 BR 节点,并且通过 BR 将权限传给 TiKV 节点。 + +{{< copyable "shell-regular" >}} + +```shell +export AWS_ACCESS_KEY_ID=${AccessKey} +export AWS_SECRET_ACCESS_KEY=${SecretKey} +``` + +在进行 BR 备份时,显示指定参数 `--s3.region` 和 `--send-credentials-to-tikv`, `--s3.region` 表示 S3 存储所在的区域,`--send-credentials-to-tikv` 表示将 S3 的访问权限传递给 TiKV 节点。 + +{{< copyable "shell-regular" >}} + +```shell +br backup full \ + --pd "${PDIP}:2379" \ + --storage "s3://${Bucket}/${Folder}" \ + --s3.region "${region}" \ + --send-credentials-to-tikv true \ + --log-file backuptable.log +``` + +### 增量备份 + +如果想要备份增量,只需要在备份的时候指定**上一次的备份时间戳** `--lastbackupts` 即可。 + +注意增量备份有以下限制: + +- 增量备份需要与前一次全量备份在不同的路径下 +- GC safepoint 必须在 `lastbackupts` 之前 + +{{< copyable "shell-regular" >}} + +```shell +br backup full\ + --pd ${PDIP}:2379 \ + -s local:///home/tidb/backupdata/incr \ + --lastbackupts ${LAST_BACKUP_TS} +``` + +以上命令会备份 `(LAST_BACKUP_TS, current PD timestamp]` 之间的增量数据。 + +你可以使用 `validate` 指令获取上一次备份的时间戳,示例如下: + +{{< copyable "shell-regular" >}} + +```shell +LAST_BACKUP_TS=`br validate decode --field="end-version" -s local:///home/tidb/backupdata` +``` + +示例备份的增量数据包括 `(LAST_BACKUP_TS, current PD timestamp]` 之间的新写入数据,以及这段时间内的 DDL。在恢复的时候,BR 会先把所有 DDL 恢复,而后才会恢复写入数据。 + +### Raw KV 备份(实验性功能) + +> **警告:** +> +> Raw KV 备份功能还在实验中,没有经过完备的测试。暂时请避免在生产环境中使用该功能。 + +在某些使用场景下,TiKV 可能会独立于 TiDB 运行。考虑到这点,BR 也提供跳过 TiDB 层,直接备份 TiKV 中数据的功能: + +{{< copyable "shell-regular" >}} + +```shell +br backup raw --pd $PD_ADDR \ + -s "local://$BACKUP_DIR" \ + --start 31 \ + --end 3130303030303030 \ + --format hex \ + --cf default +``` + +以上命令会备份 default CF 上 `[0x31, 0x3130303030303030)` 之间的所有键到 `$BACKUP_DIR` 去。 + +这里,`--start` 和 `--end` 的参数会先依照 `--format` 指定的方式解码,再被送到 TiKV 上去,目前支持以下解码方式: + +- "raw":不进行任何操作,将输入的字符串直接编码为二进制格式的键。 +- "hex":将输入的字符串视作十六进制数字。这是默认的编码方式。 +- "escape":对输入的字符串进行转义之后,再编码为二进制格式。 + +## 恢复集群数据 + +使用 `br restore` 命令来恢复备份数据。可选择添加 `full`、`db` 或 `table` 子命令来指定恢复操作的范围:全部集群数据、某个数据库或某张数据表。 + +> **注意:** +> +> 如果使用本地存储,在恢复前**必须**将所有备份的 SST 文件复制到各个 TiKV 节点上 `--storage` 指定的目录下。 +> +> 即使每个 TiKV 节点最后只需要读取部分 SST 文件,这些节点也需要有所有 SST 文件的完全访问权限。原因如下: +> +> * 数据被复制到了多个 Peer 中。在读取 SST 文件时,这些文件必须要存在于所有 Peer 中。这与数据的备份不同,在备份时,只需从单个节点读取。 +> * 在数据恢复的时候,每个 Peer 分布的位置是随机的,事先并不知道哪个节点将读取哪个文件。 +> +> 使用共享存储可以避免这些情况。例如,在本地路径上安装 NFS,或使用 S3。利用这些网络存储,各个节点都可以自动读取每个 SST 文件,此时上述注意事项不再适用。 + +### 恢复全部备份数据 + +要将全部备份数据恢复到集群中来,可使用 `br restore full` 命令。该命令的使用帮助可以通过 `br restore full -h` 或 `br restore full --help` 来获取。 + +用例:将 `/tmp/backup` 路径中的全部备份数据恢复到集群中。 + +{{< copyable "shell-regular" >}} + +```shell +br restore full \ + --pd "${PDIP}:2379" \ + --storage "local:///tmp/backup" \ + --ratelimit 128 \ + --log-file restorefull.log +``` + +以上命令中,`--ratelimit` 选项限制了**每个 TiKV** 执行恢复任务的速度上限(单位 MiB/s)。`--log-file` 选项指定把 BR 的 log 写到 `restorefull.log` 文件中。 + +恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。进度条效果如下: + +```shell +br restore full \ + --pd "${PDIP}:2379" \ + --storage "local:///tmp/backup" \ + --log-file restorefull.log +Full Restore <---------/...............................................> 17.12%. +``` + +### 恢复单个数据库的数据 + +要将备份数据中的某个数据库恢复到集群中,可以使用 `br restore db` 命令。该命令的使用帮助可以通过 `br restore db -h` 或 `br restore db --help` 来获取。 + +用例:将 `/tmp/backup` 路径中备份数据中的某个数据库恢复到集群中。 + +{{< copyable "shell-regular" >}} + +```shell +br restore db \ + --pd "${PDIP}:2379" \ + --db "test" \ + --storage "local:///tmp/backup" \ + --log-file restorefull.log +``` + +以上命令中 `--db` 选项指定了需要恢复的数据库名字。其余选项的含义与[恢复全部备份数据](#恢复全部备份数据)相同。 + +### 恢复单张表的数据 + +要将备份数据中的某张数据表恢复到集群中,可以使用 `br restore table` 命令。该命令的使用帮助可通过 `br restore table -h` 或 `br restore table --help` 来获取。 + +用例:将 `/tmp/backup` 路径下的备份数据中的某个数据表恢复到集群中。 + +{{< copyable "shell-regular" >}} + +```shell +br restore table \ + --pd "${PDIP}:2379" \ + --db "test" \ + --table "usertable" \ + --storage "local:///tmp/backup" \ + --log-file restorefull.log +``` + +### 从 Amazon S3 后端存储恢复数据 + +如果需要恢复的数据并不是存储在本地,而是在 Amazon 的 S3 后端,那么需要在 `storage` 子命令中指定 S3 的存储路径,并且赋予 BR 节点和 TiKV 节点访问 Amazon S3 的权限。 + +将有权限访问该 S3 后端存储的账号的 `SecretKey` 和 `AccessKey` 作为环境变量传入 BR 节点,并且通过 BR 将权限传给 TiKV 节点。 + +{{< copyable "shell-regular" >}} + +```shell +export AWS_ACCESS_KEY_ID=${AccessKey} +export AWS_SECRET_ACCESS_KEY=${SecretKey} +``` + +在进行 BR 恢复时,显示指定参数 `--s3.region` 和 `--send-credentials-to-tikv`, `--s3.region` 表示 S3 存储所在的区域,`--send-credentials-to-tikv` 表示将 S3 的访问权限传递给 TiKV 节点。`--storage`参数中的 `Bucket` 和 `Folder` 分别代表需要恢复的数据所在的 S3 存储桶和文件夹。 + +{{< copyable "shell-regular" >}} + +```shell +br restore full \ + --pd "${PDIP}:2379" \ + --storage "s3://${Bucket}/${Folder}" \ + --s3.region "${region}" \ + --send-credentials-to-tikv=true \ + --log-file restorefull.log +``` + +以上命令中 `--table` 选项指定了需要恢复的表名。其余选项的含义与[恢复某个数据库](#恢复某个数据库)相同。 + +### 增量恢复 + +增量恢复的方法和使用 BR 进行全量恢复的方法并无差别。需要注意,恢复增量数据的时候,需要保证备份时指定的 `last backup ts` 之前备份的数据已经全部恢复到目标集群。 + +### Raw KV 恢复(实验性功能) + +> **警告:** +> +> Raw KV 恢复功能还在实验中,没有经过完备的测试。暂时请避免在生产环境中使用该功能。 + +和 [Raw KV 备份](#raw-kv-备份实验性功能)相似地,恢复 Raw KV 的命令如下: + +{{< copyable "shell-regular" >}} + +```shell +br restore raw --pd $PD_ADDR \ + -s "local://$BACKUP_DIR" \ + --start 31 \ + --end 3130303030303030 \ + --format hex \ + --cf default +``` + +以上命令会将范围在 `[0x31, 0x3130303030303030)` 的已备份键恢复到 TiKV 集群中。这里键的编码方式和备份时相同。 + +### 在线恢复(实验性功能) + +> **警告:** +> +> 在线恢复功能还在实验中,没有经过完备的测试,同时还依赖 PD 的不稳定特性 Placement Rules。暂时请避免在生产环境中使用该功能。 + +在恢复的时候,写入过多的数据会影响在线集群的性能。为了尽量避免影响线上业务,BR 支持通过 [Placement rules](/configure-placement-rules.md) 隔离资源。让下载、导入 SST 的工作仅仅在指定的几个节点(下称“恢复节点”)上进行,具体操作如下: + +1. 配置 PD,启动 Placement rules: + + {{< copyable "shell-regular" >}} + + ```shell + echo "config set enable-placement-rules true" | pd-ctl + ``` + +2. 编辑恢复节点 TiKV 的配置文件,在 `server` 一项中指定: + + {{< copyable "" >}} + + ``` + [server] + labels = { exclusive = "restore" } + ``` + +3. 启动恢复节点的 TiKV,使用 BR 恢复备份的文件,和非在线恢复相比,这里只需要加上 `--online` 标志即可: + + {{< copyable "shell-regular" >}} + + ``` + br restore full \ + -s "local://$BACKUP_DIR" \ + --pd $PD_ADDR \ + --online + ``` + +## 最佳实践 + +- 推荐在 `-s` 指定的备份路径上挂载一个共享存储,例如 NFS。这样能方便收集和管理备份文件。 +- 在使用共享存储时,推荐使用高吞吐的存储硬件,因为存储的吞吐会限制备份或恢复的速度。 +- 推荐在业务低峰时执行备份操作,这样能最大程度地减少对业务的影响。 + +更多最佳实践内容,参见 [BR 备份与恢复场景示例](/br/backup-and-restore-use-cases.md)。 + +## 备份和恢复示例 + +本示例展示如何对已有的集群数据进行备份和恢复操作。可以根据机器性能、配置、数据规模来预估一下备份和恢复的性能。 + +### 数据规模和机器配置 + +假设对 TiKV 集群中的 10 张表进行备份和恢复。每张表有 500 万行数据,数据总量为 35 GB。 + +```sql +MySQL [sbtest]> show tables; ++------------------+ +| Tables_in_sbtest | ++------------------+ +| sbtest1 | +| sbtest10 | +| sbtest2 | +| sbtest3 | +| sbtest4 | +| sbtest5 | +| sbtest6 | +| sbtest7 | +| sbtest8 | +| sbtest9 | ++------------------+ + +MySQL [sbtest]> select count(*) from sbtest1; ++----------+ +| count(*) | ++----------+ +| 5000000 | ++----------+ +1 row in set (1.04 sec) +``` + +表结构如下: + +```sql +CREATE TABLE `sbtest1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `k` int(11) NOT NULL DEFAULT '0', + `c` char(120) NOT NULL DEFAULT '', + `pad` char(60) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY `k_1` (`k`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=5138499 +``` + +示例假设有 4 个 TiKV 节点,每个节点配置如下: + +| CPU | 内存 | 磁盘 | 副本数 | +| :--- | :--- | :--- | :--- | +| 16 核 | 32 GB | SSD | 3 | + +### 备份示例 + +- 备份前需确认已将 GC 时间调长,确保备份期间不会因为数据丢失导致中断 +- 备份前需确认 TiDB 集群没有执行 DDL 操作 + +执行以下命令对集群中的全部数据进行备份: + +{{< copyable "shell-regular" >}} + +``` +bin/br backup full -s local:///tmp/backup --pd "${PDIP}:2379" --log-file backup.log +``` + +``` +[INFO] [collector.go:165] ["Full backup summary: total backup ranges: 2, total success: 2, total failed: 0, total take(s): 0.00, total kv: 4, total size(Byte): 133, avg speed(Byte/s): 27293.78"] ["backup total regions"=2] ["backup checksum"=1.640969ms] ["backup fast checksum"=227.885µs] +``` + +### 恢复示例 + +恢复操作前,需确认待恢复的 TiKV 集群是全新的集群。 + +执行以下命令对全部数据进行恢复: + +{{< copyable "shell-regular" >}} + +``` +bin/br restore full -s local:///tmp/backup --pd "${PDIP}:2379" --log-file restore.log +``` + +``` +[INFO] [collector.go:165] ["Full Restore summary: total restore tables: 1, total success: 1, total failed: 0, total take(s): 0.26, total kv: 20000, total size(MB): 10.98, avg speed(MB/s): 41.95"] ["restore files"=3] ["restore ranges"=2] ["split region"=0.562369381s] ["restore checksum"=36.072769ms] +``` diff --git a/br/backup-and-restore-use-cases.md b/br/backup-and-restore-use-cases.md new file mode 100644 index 000000000000..6724a1c0575e --- /dev/null +++ b/br/backup-and-restore-use-cases.md @@ -0,0 +1,452 @@ +--- +title: BR 备份与恢复场景示例 +category: reference +aliases: ['/docs-cn/stable/reference/tools/br/use-cases/'] +--- + +# BR 备份与恢复场景示例 + +[Backup & Restore](/br/backup-and-restore-tool.md)(下文简称 BR)一款分布式的快速备份和恢复工具。本文展示了[四种备份和恢复场景](#使用场景)下的 BR 操作过程,以帮助读者达到以下目标: + +* 正确使用网络盘或本地盘进行备份或恢复 +* 通过相关监控指标了解备份或恢复的状态 +* 了解在备份或恢复时如何调优性能 +* 处理备份时可能发生的异常 + +> **注意:** +> +> 使用 BR 时应注意[使用限制](/br/backup-and-restore-tool.md#使用限制)。 + +## 目标读者 + +读者需要对 TiDB 和 TiKV 有一定的了解。在阅读本文前,推荐先阅读[使用 BR 进行备份与恢复](/br/backup-and-restore-tool.md)。 + +## 环境准备 + +本部分介绍推荐的 TiDB 的部署方式、示例中的集群版本、TiKV 集群硬件信息和集群配置。读者可根据自己的硬件和配置来预估备份恢复的性能。 + +### 部署方式 + +推荐使用 [TiDB Ansible](/online-deployment-using-ansible.md) 部署 TiDB 集群,再下载 [TiDB Toolkit](/download-ecosystem-tools.md#快速备份和恢复br) 获取 BR 应用。 + +### 集群版本 + +* TiKV: v3.1.0-beta.1 +* PD: v3.1.0-beta.1 +* br: v3.1.0-beta.1 + +### TiKV 集群硬件信息 + +* 操作系统:CentOS Linux release 7.6.1810 (Core) +* CPU:16-Core Common KVM processor +* RAM:32GB +* 硬盘:500G SSD * 2 +* 网卡:10000MB/s + +### 配置 + +BR 可以直接将命令下发到 TiKV 集群来执行备份和恢复,不依赖 TiDB server 组件,因此无需对 TiDB server 进行配置。 + +* TiKV: 默认配置 +* PD : 默认配置 + +## 使用场景 + +本文描述以下四种使用场景: + +* [将单表数据备份到网络盘(推荐)](#将单表数据备份到网络盘推荐) +* [从网络磁盘恢复备份数据(推荐)](#从网络磁盘恢复备份数据推荐) +* [将单表数据备份到本地磁盘](#将单表数据备份到本地磁盘) +* [从本地磁盘恢复备份数据](#从本地磁盘恢复备份数据) + +推荐使用网络盘来进行备份和恢复操作,这样可以省去收集备份数据文件的繁琐步骤。尤其在 TiKV 集群规模较大的情况下,使用网络盘可以大幅提升操作效率。 + +> **注意:** +> +> 在进行备份或恢复操作前,需要先进行备份或恢复的准备工作。 + +### 备份前的准备工作 + +`br backup` 命令的详细使用方法请参考 [BR 命令行描述](/br/backup-and-restore-tool.md#br-命令行描述)。 + +1. 运行 `br backup` 命令前,查询 TiDB 集群的 [`tikv_gc_life_time`](/garbage-collection-configuration.md#tikv_gc_life_time) 配置项的值,并使用 MySQL 客户端将该项调整至合适的值,确保备份期间不会发生 [Garbage Collection](/garbage-collection-overview.md) (GC)。 + + {{< copyable "sql" >}} + + ```sql + SELECT * FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'; + UPDATE mysql.tidb SET VARIABLE_VALUE = '720h' WHERE VARIABLE_NAME = 'tikv_gc_life_time'; + ``` + +2. 在备份完成后,将该参数调回原来的值。 + + {{< copyable "sql" >}} + + ```sql + UPDATE mysql.tidb SET VARIABLE_VALUE = '10m' WHERE VARIABLE_NAME = 'tikv_gc_life_time'; + ``` + +### 恢复前的准备工作 + +`br restore` 命令的详细使用方法请参考 [BR 命令行描述](/br/backup-and-restore-tool.md#br-命令行描述)。 + +> **注意:** +> +> 运行 `br restore` 前检查新集群确保没有同名的表。 + +### 将单表数据备份到网络盘(推荐) + +使用 `br backup` 命令,将单表数据 `--db batchmark --table order_line` 备份到指定的网络盘路径 `local:///br_data` 下。 + +#### 前置要求 + +* 配置一台高性能 SSD 硬盘主机为 NFS server 存储数据。其他所有 BR 节点和 TiKV 节点为 NFS client,挂载相同的路径(例如 `/br_data`)到 NFS server 上以访问 NFS server。 +* NFS server 和 NFS client 间的数据传输速率至少要达到备份集群的 `TiKV 实例数 * 150MB/s`。否则网络 I/O 有可能成为性能瓶颈。 + +#### 部署拓扑 + +部署拓扑如下图所示: + +![img](/media/br/backup-nfs-deploy.png) + +#### 运行备份 + +备份操作前,在 TiDB 中使用 `admin checksum table order_line` 命令获得备份目标表 `--db batchmark --table order_line` 的统计信息。统计信息示例如下: + +![img](/media/br/total-data.png) + +运行 BR 备份命令: + +{{< copyable "shell-regular" >}} + +```shell +bin/br backup table \ + --db batchmark \ + --table order_line \ + -s local:///br_data \ + --pd ${PD_ADDR}:2379 \ + --log-file backup-nfs.log +``` + +#### 备份过程中的运行指标 + +在 BR 备份过程中,需关注以下监控面版中的运行指标来了解备份的状态。 + +**Backup CPU Utilization**:参与备份的 TiKV 节点(例如 backup-worker 和 backup-endpoint)的 CPU 使用率。 + +![img](/media/br/backup-cpu.png) + +**IO Utilization**:参与备份的 TiKV 节点的 I/O 使用率。 + +![img](/media/br/backup-io.png) + +**BackupSST Generation Throughput**:参与备份的 TiKV 节点生成 backupSST 文件的吞吐。正常时单个 TiKV 节点的吞吐在 150MB/s 左右。 + +![img](/media/br/backup-throughput.png) + +**One Backup Range Duration**:备份一个 range 的操作耗时,包括扫描耗时 (scan KV) 和保存耗时(保存为 backupSST 文件)。 + +![img](/media/br/backup-range-duration.png) + +**One Backup Subtask Duration**: 一次备份任务会被拆分成多个子任务。该监控项显示子任务的耗时。 + +> **注意:** +> +> * 虽然本次任务是备份单表,但因为表中有 3 个索引,所以正常会拆分成 4 个子任务。 +> * 下图中有 13 个点,说明有 9 次 (13-4) 重试。备份过程中可能发生 Region 调度行为,少量重试是正常的。 + +![img](/media/br/backup-subtask-duration.png) + +**Backup Errors**:备份过程中的错误。正常时无错误。即使出现少量错误,备份操作也有重试机制,可能会导致备份时间增加,但不会影响备份的正确性。 + +![img](/media/br/backup-errors.png) + +**Checksum Request Duration**:对备份集群执行 admin checksum 的耗时统计。 + +![img](/media/br/checksum-duration.png) + +#### 结果解读 + +使用 BR 前已设置日志的存放路径。从路径下存放的日志中可以获取此次备份的相关统计信息。在日志中搜关键字 "summary",可以看到以下信息: + +``` +["Table backup summary: + total backup ranges: 4, + total success: 4, + total failed: 0, + total take(s): 986.43, + total kv: 5659888624, + total size(MB): 353227.18, + avg speed(MB/s): 358.09"] + ["backup total regions"=7196] + ["backup checksum"=6m28.291772955s] + ["backup fast checksum"=24.950298ms] +``` + +以上日志信息中包含以下内容: + +* 备份耗时:`total take(s): 986.43` +* 数据大小:`total size(MB): 353227.18` +* 备份吞吐:`avg speed(MB/s): 358.09` +* 校验耗时:`take=6m28.29s` + +通过以上数据可以计算得到单个 TiKV 实例的吞吐为:`avg speed(MB/s)`/`tikv_count` = `89`。 + +#### 性能调优 + +如果 TiKV 的资源使用没有出现明显的瓶颈(例如[备份过程中的运行指标](#备份过程中的运行指标)中的 **Backup CPU Utilization** 最高为 `1500%` 左右,**IO Utilization** 普遍低于 `30%`),可以尝试调大 `--concurrency` 参数以进行性能调优。该方法不适用于存在许多小表的场景。 + +示例如下: + +{{< copyable "shell-regular" >}} + +```shell +bin/br backup table \ + --db batchmark \ + --table order_line \ + -s local:///br_data/ \ + --pd ${PD_ADDR}:2379 \ + --log-file backup-nfs.log \ + --concurrency 16 +``` + +![img](/media/br/backup-diff.png) + +![img](/media/br/backup-diff2.png) + +性能调优后的结果如下所示(保持数据大小不变): + +* 备份耗时:`total take(s)` 从 `986.43` 减少到 `535.53` +* 数据大小:`total size(MB): 353227.18` +* 备份吞吐:`avg speed(MB/s)` 从 `358.09` 提升到 `659.59` +* 单个 TiKV 实例的吞吐:`avg speed(MB/s)/tikv_count` 从 `89` 提升到 `164.89` + +### 从网络磁盘恢复备份数据(推荐) + +使用 `br restore` 命令,将一份完整的备份数据恢复到一个离线集群。暂不支持恢复到在线集群。 + +#### 前置要求 + +无 + +#### 部署拓扑 + +部署拓扑如下图所示: + +![img](/media/br/restore-nfs-deploy.png) + +#### 运行恢复 + +运行 `br restore` 命令: + +{{< copyable "shell-regular" >}} + +```shell +bin/br restore table --db batchmark --table order_line -s local:///br_data --pd 172.16.5.198:2379 --log-file restore-nfs.log +``` + +#### 恢复过程中的运行指标 + +在 BR 恢复过程中,需关注以下监控面版中的运行指标来了解恢复的状态。 + +**CPU Utilization**:参与恢复的 TiKV 节点 CPU 使用率。 + +![img](/media/br/restore-cpu.png) + +**IO Utilization**:参与恢复的 TiKV 节点的 I/O 使用率。 + +![img](/media/br/restore-io.png) + +**Region** 分布:Region 分布越均匀,说明恢复资源利用越充分。 + +![img](/media/br/restore-region.png) + +**Process SST Duration**:处理 SST 文件的延迟。恢复一张表时时,如果 `tableID` 发生了变化,需要对 `tableID` 进行 `rewrite`,否则会进行 `rename`。通常 `rewrite` 延迟要高于 `rename` 的延迟。 + +![img](/media/br/restore-process-sst.png) + +**DownLoad SST Throughput**:从 External Storage 下载 SST 文件的吞吐。 + +![img](/media/br/restore-download-sst.png) + +**Restore Errors**:恢复过程中的错误。 + +![img](/media/br/restore-errors.png) + +**Checksum Request duration**:对恢复集群执行 admin checksum 的耗时统计,会比备份时的 checksum 延迟高。 + +![img](/media/br/restore-checksum.png) + +#### 结果解读 + +使用 BR 前已设置日志的存放路径。从路径下存放的日志中可以获取此次恢复的相关统计信息。在日志中搜关键字 "summary",可以看到以下信息: + +``` +["Table Restore summary: + total restore tables: 1, + total success: 1, + total failed: 0, + total take(s): 961.37, + total kv: 5659888624, + total size(MB): 353227.18, + avg speed(MB/s): 367.42"] + ["restore files"=9263] + ["restore ranges"=6888] + ["split region"=49.049182743s] + ["restore checksum"=6m34.879439498s] +``` + +以上日志信息中包含以下内容: + +* 恢复耗时:`total take(s):961.37` +* 数据大小:`total size(MB): 353227.18` +* 恢复吞吐:`avg speed(MB/s): 367.42` +* `Region Split` 耗时:`take=49.049182743s` +* 校验耗时:`take=6m34.879439498s` + +根据上表数据可以计算得到: + +* 单个 TiKV 吞吐:`avg speed(MB/s)`/`tikv_count` = `91.8` +* 单个 TiKV 平均恢复速度:`total size(MB)`/(`split time` + `restore time`)/`tikv_count` = `87.4` + +#### 性能调优 + +如果 TiKV 资源使用没有明显的瓶颈,可以尝试调大 `--concurrency` 参数(默认为 `128`),示例如下: + +{{< copyable "shell-regular" >}} + +```shell +bin/br restore table --db batchmark --table order_line -s local:///br_data/ --pd 172.16.5.198:2379 --log-file restore-concurrency.log --concurrency 1024 +``` + +性能调优后的结果如下表所示(保持数据大小不变): + +* 恢复耗时:`total take(s)` 从 `961.37` 减少到 `443.49` +* 恢复吞吐:`avg speed(MB/s)` 从 `367.42` 提升到 `796.47` +* 单个 TiKV 实例的吞吐:`avg speed(MB/s)`/`tikv_count` 从 `91.8` 提升到 `199.1` +* 单个 TiKV 实例的平均恢复速度:`total size(MB)`/(`split time` + `restore time`)/`tikv_count` 从 `87.4` 提升到 `162.3` + +### 将单表数据备份到本地磁盘 + +使用 `br backup 命令`,将单表数据 `--db batchmark --table order_line` 备份到指定的本地磁盘路径 `local:///home/tidb/backup_local` 下。 + +#### 前置要求 + +* 各个 TiKV 节点有单独的磁盘用来存放 backupSST 数据。 +* `backup_endpoint` 节点有单独的磁盘用来存放备份的 `backupmeta` 文件。 +* TiKV 和 `backup_endpoint` 节点需要有相同的备份目录,例如 `/home/tidb/backup_local`。 + +#### 部署拓扑 + +![img](/media/br/backup-local-deploy.png) + +#### 运行备份 + +备份前在 TiDB 里通过 `admin checksum table order_line` 获得备份的目标表 `--db batchmark --table order_line` 的统计信息。统计信息示例如下: + +![img](/media/br/total-data.png) + +运行 `br backup` 命令: + +{{< copyable "shell-regular" >}} + +```shell +bin/br backup table \ + --db batchmark \ + --table order_line \ + -s local:///home/tidb/backup_local/ \ + --pd ${PD_ADDR}:2379 \ + --log-file backup_local.log +``` + +运行备份时,参考[备份过程中的运行指标](#备份过程中的运行指标)对相关指标进行监控,以了解备份状态。 + +#### 结果解读 + +使用 BR 前已设置日志的存放路径。从该路径下存放的日志获取此次备份的相关统计信息。在日志中搜关键字 "summary",可以看到以下信息: + +``` +["Table backup summary: total backup ranges: 4, total success: 4, total failed: 0, total take(s): 551.31, total kv: 5659888624, total size(MB): 353227.18, avg speed(MB/s): 640.71"] ["backup total regions"=6795] ["backup checksum"=6m33.962719217s] ["backup fast checksum"=22.995552ms] +``` + +以上日志信息中包含以下内容: + +* 备份耗时:`total take(s): 551.31` +* 数据大小:`total size(MB): 353227.18` +* 备份吞吐:`avg speed(MB/s): 640.71` +* 校验耗时:`take=6m33.962719217s` + +根据上表数据可以计算得到单个 TiKV 实例的吞吐:`avg speed(MB/s)`/`tikv_count` = `160`。 + +### 从本地磁盘恢复备份数据 + +使用 `br restore` 命令,将一份完整的备份数据恢复到一个离线集群。暂不支持恢复到在线集群。 + +#### 前置要求 + +* 集群中没有与备份数据相同的库表。目前 BR 不支持 table route。 +* 集群中各个 TiKV 节点有单独的磁盘用来存放要恢复的 backupSST 数据。 +* `restore_endpoint` 节点有单独的磁盘用来存放要恢复的 `backupmeta` 文件。 +* 集群中 TiKV 和 `restore_endpoint` 节点需要有相同的备份目录,例如 `/home/tidb/backup_local/`。 + +如果备份数据存放在本地磁盘,那么需要执行以下的步骤: + +1. 汇总所有 backupSST 文件到一个统一的目录下。 +2. 将汇总后的 backupSST 文件到复制到集群的所有 TiKV 节点下。 +3. 将 `backupmeta` 文件复制到到 `restore endpoint` 节点下。 + +#### 部署拓扑 + +![img](/media/br/restore-local-deploy.png) + +#### 运行恢复 + +运行 `br restore` 命令: + +{{< copyable "shell-regular" >}} + +```shell +bin/br restore table --db batchmark --table order_line -s local:///home/tidb/backup_local/ --pd 172.16.5.198:2379 --log-file restore_local.log +``` + +运行恢复时,参考[恢复过程中的运行指标](#恢复过程中的运行指标)对相关指标进行监控,以了解恢复状态。 + +#### 结果解读 + +使用 BR 前已设置日志的存放路径。从该日志中可以获取此次恢复的相关统计信息。在日志中搜关键字 "summary",可以看到以下信息: + +``` +["Table Restore summary: total restore tables: 1, total success: 1, total failed: 0, total take(s): 908.42, total kv: 5659888624, total size(MB): 353227.18, avg speed(MB/s): 388.84"] ["restore files"=9263] ["restore ranges"=6888] ["split region"=58.7885518s] ["restore checksum"=6m19.349067937s] +``` + +以上日志信息中包含以下内容: + +* 恢复耗时:`total take(s): 908.42` +* 数据大小:`total size(MB): 353227.18` +* 恢复吞吐:`avg speed(MB/s): 388.84` +* `Region Split` 耗时:`take=58.7885518s` +* 校验耗时:`take=6m19.349067937s` + +根据上表数据可以计算得到: + +* 单个 TiKV 实例的吞吐:`avg speed(MB/s)`/`tikv_count` = `97.2` +* 单个 TiKV 实例的平均恢复速度:`total size(MB)`/(`split time` + `restore time`)/`tikv_count` = `92.4` + +### 异常处理 + +本部分介绍如何处理备份过程中出现的常见错误。 + +#### 备份日志中出现 `key locked Error` + +日志中的错误消息:`log - ["backup occur kv error"][error="{\"KvError\":{\"locked\":` + +如果在备份过程中遇到 key 被锁住,目前 BR 会尝试清锁。少量报错不会影响备份的正确性。 + +#### 备份失败 + +日志中的错误消息:`log - Error: msg:"Io(Custom { kind: AlreadyExists, error: \"[5_5359_42_123_default.sst] is already exists in /dir/backup_local/\" })"` + +若备份失败并出现以上错误消息,采取以下其中一种操作后再重新备份: + +* 更换备份数据目录。例如将 `/dir/backup-2020-01-01/` 改为 `/dir/backup_local/`。 +* 删除所有 TiKV 和 BR 节点的备份目录。 diff --git a/certificate-authentication.md b/certificate-authentication.md new file mode 100644 index 000000000000..c22dfcfb26ed --- /dev/null +++ b/certificate-authentication.md @@ -0,0 +1,505 @@ +--- +title: TiDB 证书鉴权使用指南 +summary: 了解使用 TiDB 的证书鉴权功能。 +category: reference +aliases: ['/docs-cn/stable/reference/security/cert-based-authentication/'] +--- + +# TiDB 证书鉴权使用指南 + +TiDB 支持基于证书鉴权的登录方式。采用这种方式,TiDB 对不同用户签发证书,使用加密连接来传输数据,并在用户登录时验证证书。相比 MySQL 用户常用的用户名密码验证方式,与 MySQL 相兼容的证书鉴权方式更安全,因此越来越多的用户使用证书鉴权来代替用户名密码验证。 + +在 TiDB 上使用证书鉴权的登录方法,可能需要进行以下操作: + ++ 创建安全密钥和证书 ++ 配置 TiDB 和客户端使用的证书 ++ 配置登陆时需要校验的用户证书信息 ++ 更新和替换证书 + +本文介绍了如何进行证书鉴权的上述几个操作。 + +## 创建安全密钥和证书 + +目前推荐使用 [OpenSSL](https://www.openssl.org/) 来生成密钥和证书,生成证书的过程和[为 TiDB 客户端服务端间通信开启加密传输](/enable-tls-between-clients-and-servers.md)过程类似,下面更多演示如何在证书中配置更多需校验的属性字段。 + +### 生成 CA 密钥和证书 + +1. 执行以下命令生成 CA 密钥: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl genrsa 2048 > ca-key.pem + ``` + + 命令执行后输出以下结果: + + {{< copyable "shell-regular" >}} + + ```bash + Generating RSA private key, 2048 bit long modulus (2 primes) + ....................+++++ + ...............................................+++++ + e is 65537 (0x010001) + ``` + +2. 执行以下命令生成该密钥对应的证书: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl req -new -x509 -nodes -days 365000 -key ca-key.pem -out ca-cert.pem + ``` + +3. 输入证书细节信息,示例如下: + + {{< copyable "shell-regular" >}} + + ```bash + Country Name (2 letter code) [AU]:US + State or Province Name (full name) [Some-State]:California + Locality Name (eg, city) []:San Francisco + Organization Name (eg, company) [Internet Widgits Pty Ltd]:PingCAP Inc. + Organizational Unit Name (eg, section) []:TiDB + Common Name (e.g. server FQDN or YOUR name) []:TiDB admin + Email Address []:s@pingcap.com + ``` + + > **注意:** + > + > 以上信息中,`:` 后的文字为用户输入的信息。 + +### 生成服务端密钥和证书 + +1. 执行以下命令生成服务端的密钥: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl req -newkey rsa:2048 -days 365000 -nodes -keyout server-key.pem -out server-req.pem + ``` + +2. 输入证书细节信息,示例如下: + + {{< copyable "shell-regular" >}} + + ```bash + Country Name (2 letter code) [AU]:US + State or Province Name (full name) [Some-State]:California + Locality Name (eg, city) []:San Francisco + Organization Name (eg, company) [Internet Widgits Pty Ltd]:PingCAP Inc. + Organizational Unit Name (eg, section) []:TiKV + Common Name (e.g. server FQDN or YOUR name) []:TiKV Test Server + Email Address []:k@pingcap.com + + Please enter the following 'extra' attributes + to be sent with your certificate request + A challenge password []: + An optional company name []: + ``` + +3. 执行以下命令生成服务端的 RSA 密钥: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl rsa -in server-key.pem -out server-key.pem + ``` + + 输出结果如下: + + ```bash + writing RSA key + ``` + +4. 使用 CA 证书签名来生成服务端的证书: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl x509 -req -in server-req.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem + ``` + + 输出结果示例如下: + + ```bash + Signature ok + subject=C = US, ST = California, L = San Francisco, O = PingCAP Inc., OU = TiKV, CN = TiKV Test Server, emailAddress = k@pingcap.com + Getting CA Private Key + ``` + + > **注意:** + > + > 以上结果中,用户登陆时 TiDB 将强制检查 `subject` 部分的信息是否一致。 + +### 生成客户端密钥和证书 + +生成服务端密钥和证书后,需要生成客户端使用的密钥和证书。通常需要为不同的用户生成不同的密钥和证书。 + +1. 执行以下命令生成客户端的密钥: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl req -newkey rsa:2048 -days 365000 -nodes -keyout client-key.pem -out client-req.pem + ``` + +2. 输入证书细节信息,示例如下: + + {{< copyable "shell-regular" >}} + + ```bash + Country Name (2 letter code) [AU]:US + State or Province Name (full name) [Some-State]:California + Locality Name (eg, city) []:San Francisco + Organization Name (eg, company) [Internet Widgits Pty Ltd]:PingCAP Inc. + Organizational Unit Name (eg, section) []:TiDB + Common Name (e.g. server FQDN or YOUR name) []:tpch-user1 + Email Address []:zz@pingcap.com + + Please enter the following 'extra' attributes + to be sent with your certificate request + A challenge password []: + An optional company name []: + ``` + +3. 执行以下命令生成客户端 RSA 证书: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl rsa -in client-key.pem -out client-key.pem + ``` + + 以上命令的输出结果如下: + + ```bash + writing RSA key + ``` + +4. 执行以下命令,使用 CA 证书签名来生成客户端证书: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl x509 -req -in client-req.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem + ``` + + 输出结果示例如下: + + ```bash + Signature ok + subject=C = US, ST = California, L = San Francisco, O = PingCAP Inc., OU = TiDB, CN = tpch-user1, emailAddress = zz@pingcap.com + Getting CA Private Key + ``` + + > **注意:** + > + > 以上结果中,`subject` 部分后的信息会被用来在 `require` 中配置和要求验证。 + +### 验证证书 + +执行以下命令验证证书: + +{{< copyable "shell-regular" >}} + +```bash +openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem +``` + +如果验证通过,会显示以下信息: + +``` +server-cert.pem: OK +client-cert.pem: OK +``` + +## 配置 TiDB 和客户端使用证书 + +在生成证书后,需要在 TiDB 中配置服务端所使用的证书,同时让客户端程序使用客户端证书。 + +### 配置 TiDB 服务端 + +修改 TiDB 配置文件中的 `[security]` 段。这一步指定 CA 证书、服务端密钥和服务端证书存放的路径。可将 `path/to/server-cert.pem`、`path/to/server-key.pem` 和 `path/to/ca-cert.pem` 替换成实际的路径。 + +{{< copyable "" >}} + +``` +[security] +ssl-cert ="path/to/server-cert.pem" +ssl-key ="path/to/server-key.pem" +ssl-ca="path/to/ca-cert.pem" +``` + +启动 TiDB 日志。如果日志中有以下内容,即代表配置生效: + +``` +[INFO] [server.go:264] ["secure connection is enabled"] ["client verification enabled"=true] +``` + +### 配置客户端程序 + +配置客户端程序,让客户端使用客户端密钥和证书来登录 TiDB。 + +以 MySQL 客户端为例,可以通过指定 `ssl-cert`、`ssl-key`、`ssl-ca` 来使用新的 CA 证书、客户端密钥和证书: + +{{< copyable "shell-regular" >}} + +```bash +mysql -utest -h0.0.0.0 -P4000 --ssl-cert /path/to/client-cert.new.pem --ssl-key /path/to/client-key.new.pem --ssl-ca /path/to/ca-cert.pem +``` + +> **注意:** +> +> `/path/to/client-cert.new.pem`、`/path/to/client-key.new.pem` 和 `/path/to/ca-cert.pem` 是 CA 证书、客户端密钥和客户端存放的路径。可将以上命令中的这些部分替换为实际的路径。 + +## 配置登陆时需要校验的用户证书信息 + +使用客户端连接 TiDB 进行授权配置。先获取需要验证的用户证书信息,再对这些信息进行配置。 + +### 获取用户证书信息 + +用户证书信息可由 `require subject`、`require issuer`、`require san` 和 `require cipher` 来指定,用于检查 X.509 certificate attributes。 + ++ `require subject`:指定用户在连接时需要提供客户端证书的 `subject` 内容。指定该选项后,不需要再配置 `require ssl` 或 x509。配置内容对应[生成客户端密钥和证书](#生成客户端密钥和证书) 中的录入信息。 + + 可以执行以下命令来获取该项的信息: + + {{< copyable "shell-regular" >}} + + ``` + openssl x509 -noout -subject -in client-cert.pem | sed 's/.\{8\}//' | sed 's/, /\//g' | sed 's/ = /=/g' | sed 's/^/\//' + ``` + ++ `require issuer`:指定签发用户证书的 CA 证书的 `subject` 内容。配置内容对应[生成 CA 密钥和证书](#生成-ca-密钥和证书) 中的录入信息。 + + 可以执行以下命令来获取该项的信息: + + {{< copyable "shell-regular" >}} + + ``` + openssl x509 -noout -subject -in ca-cert.pem | sed 's/.\{8\}//' | sed 's/, /\//g' | sed 's/ = /=/g' | sed 's/^/\//' + ``` + ++ `require san`:指定签发用户证书的 CA 证书的 `Subject Alternative Name` 内容。配置内容对应生成客户端证书使用的 [openssl.cnf 配置文件的 `alt_names` 信息](/generate-self-signed-certificates.md)。 + + + 可以执行以下命令来获取已生成证书中的 `require san` 项的信息: + + {{< copyable "shell-regular" >}} + + ```shell + openssl x509 -noout -ext subjectAltName -in client.crt + ``` + + + `require san` 目前支持以下 `Subject Alternative Name` 检查项: + + - URI + - IP + - DNS + + + 多个检查项可通过逗号连接后进行配置。例如,对用户 `u1` 进行以下配置: + + {{< copyable "sql" >}} + + ```sql + create user 'u1'@'%' require san 'DNS:d1,URI:spiffe://example.org/myservice1,URI:spiffe://example.org/myservice2' + ``` + + 以上配置只允许用户 `u1` 使用 URI 项为 `spiffe://example.org/myservice1` 或 `spiffe://example.org/myservice2`、DNS 项为 `d1` 的证书登录 TiDB。 + ++ `require cipher`:配置该项检查客户端支持的 `cipher method`。可以使用以下语句来查看支持的列表: + + {{< copyable "sql" >}} + + ```sql + SHOW SESSION STATUS LIKE 'Ssl_cipher_list'; + ``` + +### 配置用户证书信息 + +获取用户证书信息(`require subject`, `require issuer`、`require san` 和 `require cipher`)后,可在创建用户、赋予权限或更改用户时配置用户证书信息。将以下命令中的 `` 替换为对应的信息。可以选择配置其中一项或多项,使用空格或 `and` 分隔。 + ++ 可以在创建用户 (`create user`) 时配置登陆时需要校验的证书信息: + + {{< copyable "sql" >}} + + ```sql + create user 'u1'@'%' require issuer '' subject '' san '' cipher ''; + ``` + ++ 可以在赋予权限 (`grant`) 时配置登陆时需要校验的证书信息: + + {{< copyable "sql" >}} + + ```sql + grant all on *.* to 'u1'@'%' require issuer '' subject '' san '' cipher ''; + ``` + ++ 还可以在修改已有用户 (alter user) 时配置登陆时需要校验的证书信息: + + {{< copyable "sql" >}} + + ```sql + alter user 'u1'@'%' require issuer '' subject '' san '' cipher ''; + ``` + +配置完成后,用户在登录时 TiDB 会验证以下内容: + ++ 使用 SSL 登录,且证书为服务器配置的 CA 证书所签发 ++ 证书的 `Issuer` 信息和权限配置里的信息相匹配 ++ 证书的 `Subject` 信息和权限配置里的信息相匹配 ++ 证书的 `Subject Alternative Name` 信息和权限配置里的信息相匹配 + +全部验证通过后用户才能登录,否则会报 `ERROR 1045 (28000): Access denied` 错误。登录后,可以通过以下命令来查看当前链接是否使用证书登录、TLS 版本和 Cipher 算法。 + +连接 MySQL 客户端并执行: + +{{< copyable "sql" >}} + +```sql +\s +``` + +返回结果如下: + +``` +-------------- +mysql Ver 15.1 Distrib 10.4.10-MariaDB, for Linux (x86_64) using readline 5.1 + +Connection id: 1 +Current database: test +Current user: root@127.0.0.1 +SSL: Cipher in use is TLS_AES_256_GCM_SHA384 +``` + +然后执行: + +{{< copyable "sql" >}} + +```sql +show variables like '%ssl%'; +``` + +返回结果如下: + +``` ++---------------+----------------------------------+ +| Variable_name | Value | ++---------------+----------------------------------+ +| ssl_cert | /path/to/server-cert.pem | +| ssl_ca | /path/to/ca-cert.pem | +| have_ssl | YES | +| have_openssl | YES | +| ssl_key | /path/to/server-key.pem | ++---------------+----------------------------------+ +6 rows in set (0.067 sec) +``` + +## 更新和替换证书 + +证书和密钥通常会周期性更新。下文介绍更新密钥和证书的流程。 + +CA 证书是客户端和服务端相互校验的依据,所以如果需要替换 CA 证书,则需要生成一个组合证书来在替换期间同时支持客户端和服务器上新旧证书的验证,并优先替换客户端和服务端的 CA 证书,再替换客户端和服务端的密钥和证书。 + +### 更新 CA 密钥和证书 + +1. 以替换 CA 密钥为例(假设 `ca-key.pem` 被盗),将旧的 CA 密钥和证书进行备份: + + {{< copyable "shell-regular" >}} + + ```bash + mv ca-key.pem ca-key.old.pem && \ + mv ca-cert.pem ca-cert.old.pem + ``` + +2. 生成新的 CA 密钥: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl genrsa 2048 > ca-key.pem + ``` + +3. 用新的密钥生成新的 CA 证书: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl req -new -x509 -nodes -days 365000 -key ca-key.pem -out ca-cert.new.pem + ``` + + > **注意:** + > + > 生成新的 CA 证书是为了替换密钥和证书,保证在线用户不受影响。所以以上命令中填写的附加信息必须与已配置的 `require issuer` 信息一致。 + +4. 生成组合 CA 证书: + + {{< copyable "shell-regular" >}} + + ```bash + cat ca-cert.new.pem ca-cert.old.pem > ca-cert.pem + ``` + +之后使用新生成的组合 CA 证书并重启 TiDB Server,此时服务端可以同时接受和使用新旧 CA 证书。 + +之后先将所有客户端用的 CA 证书也替换为新生成的组合 CA 证书,使客户端能同时和使用新旧 CA 证书。 + +### 更新客户端密钥和证书 + +> **注意:** +> +> 需要将集群中所有服务端和客户端使用的 CA 证书都替换为新生成的组合 CA 证书后才能开始进行以下步骤。 + +1. 生成新的客户端 RSA 密钥: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl req -newkey rsa:2048 -days 365000 -nodes -keyout client-key.new.pem -out client-req.new.pem && \ + sudo openssl rsa -in client-key.new.pem -out client-key.new.pem + ``` + + > **注意:** + > + > 以上命令是为了替换密钥和证书,保证在线用户不受影响,所以以上命令中填写的附加信息必须与已配置的 `require subject` 信息一致。 + +2. 使用新的组合 CA 证书和新 CA 密钥生成新客户端证书: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl x509 -req -in client-req.new.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.new.pem + ``` + +3. 让客户端使用新的客户端密钥和证书来连接 TiDB (以 MySQL 客户端为例): + + {{< copyable "shell-regular" >}} + + ```bash + mysql -utest -h0.0.0.0 -P4000 --ssl-cert /path/to/client-cert.new.pem --ssl-key /path/to/client-key.new.pem --ssl-ca /path/to/ca-cert.pem + ``` + + > **注意:** + > + > `/path/to/client-cert.new.pem`、`/path/to/client-key.new.pem` 和 `/path/to/ca-cert.pem` 是 CA 证书、客户端密钥和客户端存放的路径。可将以上命令中的这些部分替换为实际的路径。 + +### 更新服务端密钥和证书 + +1. 生成新的服务端 RSA 密钥: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl req -newkey rsa:2048 -days 365000 -nodes -keyout server-key.new.pem -out server-req.new.pem && \ + sudo openssl rsa -in server-key.new.pem -out server-key.new.pem + ``` + +2. 使用新的组合 CA 证书和新 CA 密钥生成新服务端证书: + + {{< copyable "shell-regular" >}} + + ```bash + sudo openssl x509 -req -in server-req.new.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.new.pem + ``` + +3. 配置 TiDB 使用上面新生成的服务端密钥和证书并重启。参见[配置 TiDB 服务端](#配置-tidb-服务端)。 diff --git a/character-set-and-collation.md b/character-set-and-collation.md new file mode 100644 index 000000000000..376eae921dc7 --- /dev/null +++ b/character-set-and-collation.md @@ -0,0 +1,408 @@ +--- +title: 字符集和排序规则 +category: reference +aliases: ['/docs-cn/stable/reference/sql/characterset-and-collation/','/docs-cn/stable/reference/sql/character-set/'] +--- + +# 字符集和排序规则 + +本文介绍了 TiDB 中支持的字符集和排序规则。 + +## 字符集和排序规则的概念 + +字符集 (character set) 是符号与编码的集合。 + +排序规则 (collation) 是在字符集中比较字符的规则。 + +## 支持的字符集和排序规则 + +目前 TiDB 支持以下字符集: + +{{< copyable "sql" >}} + +```sql +SHOW CHARACTER SET; +``` + +```sql ++---------|---------------|-------------------|--------+ +| Charset | Description | Default collation | Maxlen | ++---------|---------------|-------------------|--------+ +| utf8 | UTF-8 Unicode | utf8_bin | 3 | +| utf8mb4 | UTF-8 Unicode | utf8mb4_bin | 4 | +| ascii | US ASCII | ascii_bin | 1 | +| latin1 | Latin1 | latin1_bin | 1 | +| binary | binary | binary | 1 | ++---------|---------------|-------------------|--------+ +5 rows in set (0.00 sec) +``` + +支持的排序规则如下: + +```sql +mysql> show collation; ++-------------+---------+------+---------+----------+---------+ +| Collation | Charset | Id | Default | Compiled | Sortlen | ++-------------+---------+------+---------+----------+---------+ +| utf8mb4_bin | utf8mb4 | 46 | Yes | Yes | 1 | +| latin1_bin | latin1 | 47 | Yes | Yes | 1 | +| binary | binary | 63 | Yes | Yes | 1 | +| ascii_bin | ascii | 65 | Yes | Yes | 1 | +| utf8_bin | utf8 | 83 | Yes | Yes | 1 | ++-------------+---------+------+---------+----------+---------+ +5 rows in set (0.01 sec) +``` + +> **注意:** +> +> 每个字符集可能对应多个排序规则,但与之对应的**默认排序规则**有且仅有一个。 + +利用以下的语句可以查看字符集对应的排序规则(以下是[新的排序规则框架](#新框架下的排序规则支持))下的结果: + +{{< copyable "sql" >}} + +```sql +SHOW COLLATION WHERE Charset = 'utf8mb4'; +``` + +```sql ++--------------------+---------+------+---------+----------+---------+ +| Collation | Charset | Id | Default | Compiled | Sortlen | ++--------------------+---------+------+---------+----------+---------+ +| utf8mb4_bin | utf8mb4 | 46 | Yes | Yes | 1 | +| utf8mb4_general_ci | utf8mb4 | 45 | | Yes | 1 | ++--------------------+---------+------+---------+----------+---------+ +2 rows in set (0.00 sec) +``` + +## 不同范围的字符集和排序规则 + +字符集和排序规则可以在设置在不同的层次。 + +### 数据库的字符集和排序规则 + +每个数据库都有相应的字符集和排序规则。数据库的字符集和排序规则可以通过以下语句来设置: + +```sql +CREATE DATABASE db_name + [[DEFAULT] CHARACTER SET charset_name] + [[DEFAULT] COLLATE collation_name] + +ALTER DATABASE db_name + [[DEFAULT] CHARACTER SET charset_name] + [[DEFAULT] COLLATE collation_name] +``` + +在这里 `DATABASE` 可以跟 `SCHEMA` 互换使用。 + +不同的数据库之间可以使用不一样的字符集和排序规则。 + +通过系统变量 `character_set_database` 和 `collation_database` 可以查看到当前数据库的字符集以及排序规则: + +{{< copyable "sql" >}} + +```sql +create schema test1 character set utf8mb4 COLLATE uft8mb4_general_ci; +``` + +```sql +Query OK, 0 rows affected (0.09 sec) +``` + +{{< copyable "sql" >}} + +```sql +use test1; +``` + +```sql +Database changed +``` + +{{< copyable "sql" >}} + +```sql +SELECT @@character_set_database, @@collation_database; +``` + +```sql ++--------------------------|----------------------+ +| @@character_set_database | @@collation_database | ++--------------------------|----------------------+ +| utf8mb4 | uft8mb4_general_ci | ++--------------------------|----------------------+ +1 row in set (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +create schema test2 character set latin1 COLLATE latin1_bin; +``` + +```sql +Query OK, 0 rows affected (0.09 sec) +``` + +{{< copyable "sql" >}} + +```sql +use test2; +``` + +```sql +Database changed +``` + +{{< copyable "sql" >}} + +```sql +SELECT @@character_set_database, @@collation_database; +``` + +```sql ++--------------------------|----------------------+ +| @@character_set_database | @@collation_database | ++--------------------------|----------------------+ +| latin1 | latin1_bin | ++--------------------------|----------------------+ +1 row in set (0.00 sec) +``` + +在 INFORMATION_SCHEMA 中也可以查看到这两个值: + +{{< copyable "sql" >}} + +```sql +SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME +FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'db_name'; +``` + +### 表的字符集和排序规则 + +表的字符集和排序规则可以通过以下语句来设置: + +```sql +CREATE TABLE tbl_name (column_list) + [[DEFAULT] CHARACTER SET charset_name] + [COLLATE collation_name]] + +ALTER TABLE tbl_name + [[DEFAULT] CHARACTER SET charset_name] + [COLLATE collation_name] +``` + +例如: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1(a int) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; +``` + +```sql +Query OK, 0 rows affected (0.08 sec) +``` + +如果表的字符集和排序规则没有设置,那么数据库的字符集和排序规则就作为其默认值。 + +### 列的字符集和排序规则 + +列的字符集和排序规则的语法如下: + +```sql +col_name {CHAR | VARCHAR | TEXT} (col_length) + [CHARACTER SET charset_name] + [COLLATE collation_name] + +col_name {ENUM | SET} (val_list) + [CHARACTER SET charset_name] + [COLLATE collation_name] +``` + +如果列的字符集和排序规则没有设置,那么表的字符集和排序规则就作为其默认值。 + +### 字符串的字符集和排序规则 + +每一个字符串都对应一个字符集和一个排序规则,在使用字符串时指此选项可选,如下: + +```sql +[_charset_name]'string' [COLLATE collation_name] +``` + +示例如下: + +{{< copyable "sql" >}} + +```sql +SELECT 'string'; +SELECT _utf8mb4'string'; +SELECT _utf8mb4'string' COLLATE utf8mb4_general_ci; +``` + +规则如下: + +* 规则 1:如果指定了 `CHARACTER SET charset_name` 和 `COLLATE collation_name`,则直接使用 `charset_name` 字符集和 `collation_name` 排序规则。 +* 规则 2:如果指定了 `CHARACTER SET charset_name` 且未指定 `COLLATE collation_name`,则使用 `charset_name` 字符集和 `charset_name` 对应的默认排序规则。 +* 规则 3:如果 `CHARACTER SET charset_name` 和 `COLLATE collation_name` 都未指定,则使用 `character_set_connection` 和 `collation_connection` 系统变量给出的字符集和排序规则。 + +### 客户端连接的字符集和排序规则 + +* 服务器的字符集和排序规则可以通过系统变量 `character_set_server` 和 `collation_server` 获取。 +* 数据库的字符集和排序规则可以通过环境变量 `character_set_database` 和 `collation_database` 获取。 + +对于每一个客户端的连接,也有相应的变量表示字符集和排序规则:`character_set_connection` 和 `collation_connection`。 + +`character_set_client` 代表客户端的字符集。在返回结果前,服务端会把结果根据 `character_set_results` 转换成对应的字符集,包括结果的元信息等。 + +可以用以下的语句来影响这些跟客户端相关的字符集变量: + +* `SET NAMES 'charset_name' [COLLATE 'collation_name']` + + `SET NAMES` 用来设定客户端会在之后的请求中使用的字符集。`SET NAMES utf8mb4` 表示客户端会在接下来的请求中,都使用 utf8mb4 字符集。服务端也会在之后返回结果的时候使用 utf8mb4 字符集。 + `SET NAMES 'charset_name'` 语句其实等于下面语句的组合: + + {{< copyable "sql" >}} + + ```sql + SET character_set_client = charset_name; + SET character_set_results = charset_name; + SET character_set_connection = charset_name; + ``` + + `COLLATE` 是可选的,如果没有提供,将会用 `charset_name` 对应的默认排序规则设置 `collation_connection`。 + +* `SET CHARACTER SET 'charset_name'` + + 跟 `SET NAMES` 类似,等价于下面语句的组合: + + {{< copyable "sql" >}} + + ```sql + SET character_set_client = charset_name; + SET character_set_results = charset_name; + SET charset_connection = @@charset_database; + SET collation_connection = @@collation_database; + ``` + +## 服务器、数据库、表、列、字符串的字符集和排序规则的优先级 + +优先级从高到低排列顺序为: + +字符串 > 列 > 表 > 数据库 > 服务器 + +## 字符集和排序规则的通用选择规则 + +* 规则 1:如果指定了 `CHARACTER SET charset_name` 和 `COLLATE collation_name`,则直接使用 `charset_name` 字符集和 `collation_name` 排序规则。 +* 规则 2:如果指定了 `CHARACTER SET charset_name` 且未指定 `COLLATE collation_name`,则使用 `charset_name` 字符集和 `charset_name` 对应的默认排序规则。 +* 规则 3:如果 `CHARACTER SET charset_name` 和 `COLLATE collation_name` 都未指定,则使用更高优先级的字符集和排序规则。 + +## 字符合法性检查 + +当指定的字符集为 utf8 或 utf8mb4 时,TiDB 仅支持合法的 utf8 字符。对于不合法的字符,会报错:`incorrect utf8 value`。该字符合法性检查与 MySQL 8.0 兼容,与 MySQL 5.7 及以下版本不兼容。 + +如果不希望报错,可以通过 `set @@tidb_skip_utf8_check=1;` 跳过字符检查。 + +## 排序规则支持 + +排序规则的语法支持和语义支持受到配置项 [`new_collations_enabled_on_first_bootstrap`](/tidb-configuration-file.md#new_collations_enabled_on_first_bootstrap) 的影响。这里语法支持和语义支持有所区别。语法支持是指 TiDB 能够解析和设置排序规则;而语义支持是指 TiDB 能够在比较字符串时正确地使用排序规则。 + +在 4.0 版本之前,TiDB 只提供了旧的排序规则框架,能够在语法上支持的绝大部分 MySQL 排序规则,但语义上所有的排序规则都当成二进制排序规则。 + +4.0 版本中,TiDB 增加了新的排序规则框架用于在语义上支持不同的排序规则,保证字符串比较时严格遵循对应的排序规则,详情请见下文。 + +### 旧框架下的排序规则支持 + +在 4.0 版本之前,TiDB 中可以指定大部分 MySQL 中的排序规则,并把这些排序规则按照默认排序规则处理,即以编码字节序为字符定序。和 MySQL 不同的是,TiDB 在比较字符前按照排序规则的 PADDING 属性将字符末尾的空格删除,因此会造成以下的行为区别: + +{{< copyable "sql" >}} + +```sql +create table t(a varchar(20) charset utf8mb4 collate utf8mb4_general_ci primary key); +Query OK, 0 rows affected +insert into t values ('A'); +Query OK, 1 row affected +insert into t values ('a'); +Query OK, 1 row affected # MySQL 中,由于 utf8mb4_general_ci 大小写不敏感,报错 Duplicate entry 'a'。 +insert into t1 values ('a '); +Query OK, 1 row affected # MySQL 中,由于补齐空格比较,报错 Duplicate entry 'a '。 +``` + +### 新框架下的排序规则支持 + +TiDB 4.0 新增了完整的排序规则支持框架,从语义上支持了排序规则,并新增了配置开关 `new_collations_enabled_on_first_bootstrap`,在集群初次初始化时决定是否启用新排序规则框架。在该配置开关打开之后初始化集群,可以通过 `mysql`.`tidb` 表中的 `new_collation_enabled` 变量确认是否启用新排序规则框架: + +{{< copyable "sql" >}} + +```sql +select VARIABLE_VALUE from mysql.tidb where VARIABLE_NAME='new_collation_enabled'; +``` + +```sql ++----------------+ +| VARIABLE_VALUE | ++----------------+ +| True | ++----------------+ +1 row in set (0.00 sec) +``` + +在新的排序规则框架下,TiDB 能够支持 `utf8_general_ci` 和 `utf8mb4_general_ci` 这两种排序规则,与 MySQL 兼容。 + +使用 `utf8_general_ci` 或者 `utf8mb4_general_ci` 时,字符串之间的比较是大小写不敏感 (case-insensitive) 和口音不敏感 (accent-insensitive) 的。同时,TiDB 还修正了排序规则的 `PADDING` 行为: + +{{< copyable "sql" >}} + +```sql +create table t(a varchar(20) charset utf8mb4 collate utf8mb4_general_ci primary key); +Query OK, 0 rows affected (0.00 sec) +insert into t values ('A'); +Query OK, 1 row affected (0.00 sec) +insert into t values ('a'); +ERROR 1062 (23000): Duplicate entry 'a' for key 'PRIMARY' +insert into t values ('a '); +ERROR 1062 (23000): Duplicate entry 'a ' for key 'PRIMARY' +``` + +> **注意:** +> +> TiDB 中 padding 的实现方式与 MySQL 的不同。在 MySQL 中,padding 是通过补齐空格实现的。而在 TiDB 中 padding 是通过裁剪掉末尾的空格来实现的。两种做法在绝大多数情况下是一致的,唯一的例外是字符串尾部包含小于空格 (0x20) 的字符时,例如 `'a' < 'a\t'` 在 TiDB 中的结果为 `1`,而在 MySQL 中,其等价于 `'a ' < 'a\t'`,结果为 `0`。 + +## 表达式中排序规则的 Coercibility 值 + +如果一个表达式涉及多个不同排序规则的子表达式时,需要对计算时用的排序规则进行推断,规则如下: + ++ 显式 `COLLATE` 子句的 coercibility 值为 `0`。 ++ 如果两个字符串的排序规则不兼容,这两个字符串 `concat` 结果的 coercibility 值为 `1`。目前所实现的排序规则都是互相兼容的。 ++ 列或者 `CAST()`、`CONVERT()` 和 `BINARY()` 的排序规则的 coercibility 值为 `2`。 ++ 系统常量(`USER()` 或者 `VERSION()` 返回的字符串)的 coercibility 值为 `3`。 ++ 常量的 coercibility 值为 `4`。 ++ 数字或者中间变量的 coercibility 值为 `5`。 ++ `NULL` 或者由 `NULL` 派生出的表达式的 coercibility 值为 `6`。 + +在推断排序规则时,TiDB 优先使用 coercibility 值较低的表达式的排序规则。如果 coercibility 值相同,则按以下优先级确定排序规则: + +binary > utf8mb4_bin > utf8mb4_general_ci > utf8_bin > utf8_general_ci > latin1_bin > ascii_bin + +如果两个子表达式的排序规则不相同,而且表达式的 coercibility 值都为 `0` 时,TiDB 无法推断排序规则并报错。 + +## `COLLATE` 子句 + +TiDB 支持使用 `COLLATE` 子句来指定一个表达式的排序规则,该表达式的 coercibility 值为 `0`,具有最高的优先级。示例如下: + +{{< copyable "sql" >}} + +```sql +select 'a' = _utf8mb4 'A' collate utf8mb4_general_ci; +``` + +```sql ++-----------------------------------------------+ +| 'a' = _utf8mb4 'A' collate utf8mb4_general_ci | ++-----------------------------------------------+ +| 1 | ++-----------------------------------------------+ +1 row in set (0.00 sec) +``` + +更多细节,参考 [Connection Character Sets and Collations](https://dev.mysql.com/doc/refman/5.7/en/charset-connection.html)。 diff --git a/check-before-deployment.md b/check-before-deployment.md new file mode 100644 index 000000000000..8b5ccd985a50 --- /dev/null +++ b/check-before-deployment.md @@ -0,0 +1,332 @@ +--- +title: TiDB 环境与系统配置检查 +summary: 了解部署 TiDB 前的环境检查操作。 +category: how-to +--- + +# TiDB 环境与系统配置检查 + +本文介绍部署 TiDB 前的环境检查操作,以下各项操作按优先级排序。 + +## 在 TiKV 部署目标机器上添加数据盘 EXT4 文件系统挂载参数 + +生产环境部署,建议使用 EXT4 类型文件系统的 NVME 类型的 SSD 磁盘存储 TiKV 数据文件。这个配置方案为最佳实施方案,其可靠性、安全性、稳定性已经在大量线上场景中得到证实。 + +使用 `root` 用户登录目标机器,将部署目标机器数据盘格式化成 ext4 文件系统,挂载时添加 `nodelalloc` 和 `noatime` 挂载参数。`nodelalloc` 是必选参数,否则 TiUP 安装时检测无法通过;`noatime` 是可选建议参数。 + +> **注意:** +> +> 如果你的数据盘已经格式化成 ext4 并挂载了磁盘,可先执行 `umount /dev/nvme0n1p1` 命令卸载,从编辑 `/etc/fstab` 文件步骤开始执行,添加挂载参数重新挂载即可。 + +以 `/dev/nvme0n1` 数据盘为例,具体操作步骤如下: + +1. 查看数据盘。 + + {{< copyable "shell-root" >}} + + ```bash + fdisk -l + ``` + + ``` + Disk /dev/nvme0n1: 1000 GB + ``` + +2. 创建分区。 + + {{< copyable "shell-root" >}} + + ```bash + parted -s -a optimal /dev/nvme0n1 mklabel gpt -- mkpart primary ext4 1 -1 + ``` + + > **注意:** + > + > 使用 `lsblk` 命令查看分区的设备号:对于 nvme 磁盘,生成的分区设备号一般为 `nvme0n1p1`;对于普通磁盘(例如 `/dev/sdb`),生成的的分区设备号一般为 `sdb1`。 + +3. 格式化文件系统。 + + {{< copyable "shell-root" >}} + + ```bash + mkfs.ext4 /dev/nvme0n1p1 + ``` + +4. 查看数据盘分区 UUID。 + + 本例中 `nvme0n1p1` 的 UUID 为 `c51eb23b-195c-4061-92a9-3fad812cc12f`。 + + {{< copyable "shell-root" >}} + + ```bash + lsblk -f + ``` + + ``` + NAME FSTYPE LABEL UUID MOUNTPOINT + sda + ├─sda1 ext4 237b634b-a565-477b-8371-6dff0c41f5ab /boot + ├─sda2 swap f414c5c0-f823-4bb1-8fdf-e531173a72ed + └─sda3 ext4 547909c1-398d-4696-94c6-03e43e317b60 / + sr0 + nvme0n1 + └─nvme0n1p1 ext4 c51eb23b-195c-4061-92a9-3fad812cc12f + ``` + +5. 编辑 `/etc/fstab` 文件,添加 `nodelalloc` 挂载参数。 + + {{< copyable "shell-root" >}} + + ```bash + vi /etc/fstab + ``` + + ``` + UUID=c51eb23b-195c-4061-92a9-3fad812cc12f /data1 ext4 defaults,nodelalloc,noatime 0 2 + ``` + +6. 挂载数据盘。 + + {{< copyable "shell-root" >}} + + ```bash + mkdir /data1 && \ + mount -a + ``` + +7. 执行以下命令,如果文件系统为 ext4,并且挂载参数中包含 `nodelalloc`,则表示已生效。 + + {{< copyable "shell-root" >}} + + ```bash + mount -t ext4 + ``` + + ``` + /dev/nvme0n1p1 on /data1 type ext4 (rw,noatime,nodelalloc,data=ordered) + ``` + +## 检测及关闭系统 swap + +本段介绍 swap 关闭方法。TiDB 运行需要有足够的内存,并且不建议使用 swap 作为内存不足的缓冲,这会降低性能。因此建议永久关闭系统 swap,并且不要使用 `swapoff -a` 方式关闭,否则重启机器后该操作会失效。 + +建议执行以下命令关闭系统 swap: + +{{< copyable "shell-regular" >}} + +```bash +echo "vm.swappiness = 0">> /etc/sysctl.conf +swapoff -a && swapon -a +sysctl -p +``` + +## 检测及关闭目标部署机器的防火墙 + +本段介绍如何关闭目标主机防火墙配置,因为在 TiDB 集群中,需要将节点间的访问端口打通才可以保证读写请求、数据心跳等信息的正常的传输。在普遍线上场景中,数据库到业务服务和数据库节点的网络联通都是在安全域内完成数据交互。如果没有特殊安全的要求,建议将目标节点的防火墙进行关闭。否则建议[按照端口使用规则](/hardware-and-software-requirements.md#网络要求),将端口信息配置到防火墙服务的白名单中。 + +1. 检查防火墙状态(以 CentOS Linux release 7.7.1908 (Core) 为例) + + {{< copyable "shell-regular" >}} + + ```shell + sudo firewall-cmd --state + sudo systemctl status firewalld.service + ``` + +2. 关闭防火墙服务 + + {{< copyable "shell-regular" >}} + + ```bash + sudo systemctl stop firewalld.service + ``` + +3. 关闭防火墙自动启动服务 + + {{< copyable "shell-regular" >}} + + ```bash + sudo systemctl disable firewalld.service + ``` + +4. 检查防火墙状态 + + {{< copyable "shell-regular" >}} + + ```bash + sudo systemctl status firewalld.service + ``` + +## 检测及安装 NTP 服务 + +TiDB 是一套分布式数据库系统,需要节点间保证时间的同步,从而确保 ACID 模型的事务线性一致性。目前解决授时的普遍方案是采用 NTP 服务,可以通过互联网中的 `pool.ntp.org` 授时服务来保证节点的时间同步,也可以使用离线环境自己搭建的 NTP 服务来解决授时。 + +采用如下步骤检查是否安装 NTP 服务以及与 NTP 服务器正常同步: + +1. 执行以下命令,如果输出 `running` 表示 NTP 服务正在运行: + + {{< copyable "shell-regular" >}} + + ```bash + sudo systemctl status ntpd.service + ``` + + ``` + ntpd.service - Network Time Service + Loaded: loaded (/usr/lib/systemd/system/ntpd.service; disabled; vendor preset: disabled) + Active: active (running) since 一 2017-12-18 13:13:19 CST; 3s ago + ``` + +2. 执行 `ntpstat` 命令检测是否与 NTP 服务器同步: + + > **注意:** + > + > Ubuntu 系统需安装 `ntpstat` 软件包。 + + {{< copyable "shell-regular" >}} + + ```bash + ntpstat + ``` + + - 如果输出 `synchronised to NTP server`,表示正在与 NTP 服务器正常同步: + + ``` + synchronised to NTP server (85.199.214.101) at stratum 2 + time correct to within 91 ms + polling server every 1024 s + ``` + + - 以下情况表示 NTP 服务未正常同步: + + ``` + unsynchronised + ``` + + - 以下情况表示 NTP 服务未正常运行: + + ``` + Unable to talk to NTP daemon. Is it running? + ``` + +如果要使 NTP 服务尽快开始同步,执行以下命令。可以将 `pool.ntp.org` 替换为你的 NTP 服务器: + +{{< copyable "shell-regular" >}} + +```bash +sudo systemctl stop ntpd.service && \ +sudo ntpdate pool.ntp.org && \ +sudo systemctl start ntpd.service +``` + +如果要在 CentOS 7 系统上手动安装 NTP 服务,可执行以下命令: + +{{< copyable "shell-regular" >}} + +```bash +sudo yum install ntp ntpdate && \ +sudo systemctl start ntpd.service && \ +sudo systemctl enable ntpd.service +``` + +## 手动配置 SSH 互信及 sudo 免密码 + +对于有需求,通过手动配置中控机至目标节点互信的场景,可参考本段。通常推荐使用 TiUP 部署工具会自动配置 SSH 互信及免密登陆,可忽略本段内容。 + +1. 以 `root` 用户依次登录到部署目标机器创建 `tidb` 用户并设置登录密码。 + + {{< copyable "shell-root" >}} + + ```bash + useradd tidb && \ + passwd tidb + ``` + +2. 执行以下命令,将 `tidb ALL=(ALL) NOPASSWD: ALL` 添加到文件末尾,即配置好 sudo 免密码。 + + {{< copyable "shell-root" >}} + + ```bash + visudo + ``` + + ``` + tidb ALL=(ALL) NOPASSWD: ALL + ``` + +3. 以 `tidb` 用户登录到中控机,执行以下命令。将 `10.0.1.1` 替换成你的部署目标机器 IP,按提示输入部署目标机器 `tidb` 用户密码,执行成功后即创建好 SSH 互信,其他机器同理。 + + {{< copyable "shell-regular" >}} + + ```bash + ssh-copy-id -i ~/.ssh/id_rsa.pub 10.0.1.1 + ``` + +4. 以 `tidb` 用户登录中控机,通过 `ssh` 的方式登录目标机器 IP。如果不需要输入密码并登录成功,即表示 SSH 互信配置成功。 + + {{< copyable "shell-regular" >}} + + ```bash + ssh 10.0.1.1 + ``` + + ``` + [tidb@10.0.1.1 ~]$ + ``` + +5. 以 `tidb` 用户登录到部署目标机器后,执行以下命令,不需要输入密码并切换到 `root` 用户,表示 `tidb` 用户 sudo 免密码配置成功。 + + {{< copyable "shell-regular" >}} + + ```bash + sudo -su root + ``` + + ``` + [root@10.0.1.1 tidb]# + ``` + +## 安装 numactl 工具 + +本段主要介绍如果安装 NUMA 工具。在线上环境中,因为硬件机器配置往往高于需求,为了更合理规划资源,会考虑单机多实例部署 TiDB 或者 TiKV。NUMA 绑核工具的使用,主要为了防止 CPU 资源的争抢,引发性能衰退。 + +> **注意:** +> +> - NUMA 绑核是用来隔离 CPU 资源的一种方法,适合高配置物理机环境部署多实例使用。 +> - 通过 `tiup cluster deploy` 完成部署操作,就可以通过 `exec` 命令来进行集群级别管理工作。 + +1. 登录到目标节点进行安装(以 CentOS Linux release 7.7.1908 (Core) 为例) + + {{< copyable "shell-regular" >}} + + ```bash + sudo yum -y install numactl + ``` + +2. 通过 TiUP 的 cluster 执行完 exec 命令来完成批量安装 + + {{< copyable "shell-regular" >}} + + ```bash + tiup cluster exec --help + ``` + + ``` + Run shell command on host in the tidb cluster + + Usage: + cluster exec [flags] + + Flags: + --command string the command run on cluster host (default "ls") + -h, --help help for exec + --sudo use root permissions (default false) + ``` + + 将 tidb-test 集群所有目标主机通过 sudo 权限执行安装命令 + + {{< copyable "shell-regular" >}} + + ```bash + tiup cluster exec tidb-test --sudo --command "yum -y install numactl" + ``` diff --git a/check-cluster-status-using-sql-statements.md b/check-cluster-status-using-sql-statements.md new file mode 100644 index 000000000000..00d44fb8d5c2 --- /dev/null +++ b/check-cluster-status-using-sql-statements.md @@ -0,0 +1,28 @@ +--- +title: 使用 SQL 语句检查 TiDB 集群状态 +category: reference +aliases: ['/docs-cn/stable/reference/performance/check-cluster-status-using-sql-statements/'] +--- + +# 使用 SQL 语句检查 TiDB 集群状态 + +为了方便排查问题,TiDB 提供了一些 SQL 语句和系统表以查询一些有用的信息。 + +`INFORMATION_SCHEMA` 中提供了如下几个系统表,用于查询集群状态,诊断常见的集群问题。 + +- [`TABLES`](/system-tables/system-table-information-schema.md#tables-表) +- [`TIDB_INDEXES`](/system-tables/system-table-information-schema.md#tidb_indexes-表) +- [`ANALYZE_STATUS`](/system-tables/system-table-information-schema.md#analyze_status-表) +- [`TIDB_HOT_REGIONS`](/system-tables/system-table-information-schema.md#tidb_hot_regions-表) +- [`TIKV_STORE_STATUS`](/system-tables/system-table-information-schema.md#tikv_store_status-表) +- [`TIKV_REGION_STATUS`](/system-tables/system-table-information-schema.md#tikv_region_status-表) +- [`TIKV_REGION_PEERS`](/system-tables/system-table-information-schema.md#tikv_region_peers-表) + +除此之外,执行下列语句也可获得对排查问题或查询集群状态有用的信息: + +- `ADMIN SHOW DDL` 可以获得是 `DDL owner` 角色的 TiDB 的 ID 及 `IP:PORT` 等具体信息。 +- `SHOW ANALYZE STATUS` 和 [`ANALYZE_STATUS`](/system-tables/system-table-information-schema.md#analyze_status-表) 表的功能相同。 +- 特殊的 `EXPLAIN` 语句: + - `EXPLAIN ANALYZE` 语句可以获得一个 SQL 语句执行中的一些具体信息。 + - `EXPLAIN FOR CONNECTION` 可以获得一个连接中最后执行的查询的执行计划。可以配合 `SHOW PROCESSLIST` 使用。 + - 关于 `EXPLAIN` 相关的更具体的信息,参考文档[理解 TiDB 执行计划](/query-execution-plan.md)。 diff --git a/choose-index.md b/choose-index.md new file mode 100644 index 000000000000..a7f9724dbf2e --- /dev/null +++ b/choose-index.md @@ -0,0 +1,77 @@ +--- +title: 索引的选择 +category: performance +--- + +# 索引的选择 + +从存储层读取数据是 SQL 计算过程中最为耗时的部分之一,TiDB 目前支持从不同的存储和不同的索引中读取数据,索引选择得是否合理将很大程度上决定一个查询的运行速度。 + +本章节将介绍 TiDB 如何选择索引去读入数据,以及相关的一些控制索引选择的方式。 + +## 读表 + +在介绍索引的选择之前,首先要了解 TiDB 有哪些读表的方式,这些方式的触发条件是什么,不同方式有什么区别,各有什么优劣。 + +### 读表算子 + +| 读表算子 | 触发条件 | 适用场景 | 说明 | +| :------- | :------- | :------- | :---- | +| PointGet/BatchPointGet | 读表的范围是一个或多个单点范围 | 任何场景 | 如果能被触发,通常被认为是最快的算子,因为其直接调用 kvget 的接口进行计算,不走 coprocessor | +| TableReader | 无 | 任何场景 | 从 TiKV 端直接扫描表数据,一般被认为是效率最低的算子,除非在 `_tidb_rowid` 这一列上存在范围查询,或者无其他可以选择的读表算子时,才会选择这个算子 | +| TableReader | 表在 TiFlash 节点上存在副本 | 需要读取的列比较少,但是需要计算的行很多 | TiFlash 是列式存储,如果需要对少量的列和大量的行进行计算,一般会选择这个算子 | +| IndexReader | 表有一个或多个索引,且计算所需的列被包含在索引里 | 存在较小的索引上的范围查询,或者对索引列有顺序需求的时候 | 当存在多个索引的时候,会根据估算代价选择合理的索引 | +| IndexLookupReader | 表有一个或多个索引,且计算所需的列**不完全**被包含在索引里 | 同 IndexReader | 因为计算列不完全被包含在索引里,所以读完索引后需要回表,这里会比 IndexReader 多一些开销 | + +> 注意: +> +> TableReader 是基于 `_tidb_rowid` 的索引,TiFlash 是列存索引,所以索引的选择即是读表算子的选择。 + +## 索引的选择 + +TiDB 在选择索引时,会基于每个读表算子的代价估算,在此基础上提供了启发式规则 "Skyline-Pruning",以降低错误估算导致选错索引的概率。 + +### Skyline-Pruning + +Skyline-Pruning 是一个针对索引的启发式过滤规则,评判一个索引的好坏需要从以下三个维度进行衡量: + +- 选择该索引读表时,是否需要回表(即该索引生成的计划是 IndexReader 还是 IndexLookupReader)。不用回表的索引在这个维度上优于需要回表的索引。 + +- 选择该索引是否能满足一定的顺序。因为索引的读取可以保证某些列集合的顺序,所以满足查询要求顺序的索引在这个维度上优于不满足的索引。 + +- 索引的列涵盖了多少访问条件。“访问条件”指的是可以转化为某列范围的 `where` 条件,如果某个索引的列集合涵盖的访问条件越多,那么它在这个维度上更优。 + +对于这三种维度,如果某个索引 `idx_a` 在**三个维度上都不比 `idx_b` 差**,且**有一个维度比 `idx_b` 好**,那么就会优先选择 `idx_a`。 + +### 基于代价选择 + +在使用 Skyline-Pruning 规则排除了不合适的索引之后,索引的选择完全基于代价估算,读表的代价估算需要考虑以下几个方面: + +- 索引的每行数据在存储层的平均长度。 +- 索引生成的查询范围的行数量。 +- 索引的回表代价。 +- 索引查询时的范围数量。 + +根据这些因子和代价模型,优化器会选择一个代价最低的索引进行读表。 + +#### 代价选择调优的常见问题 + +1. 估算的行数量不准确? + + 一般是统计信息过期或者准确度不够造成的,可以重新执行 `analyze table` 或者修改 `analyze table` 的参数。 + +2. 统计信息准确,为什么读 TiFlash 更快,而优化器选择了 TiKV? + + 目前区别 TiFlash 和 TiKV 的代价模型还比较粗糙,可以调小 `tidb_opt_seek_factor` 的值,让优化器倾向于选择 TiFlash。 + +3. 统计信息准确,某个索引要回表,但是它比另一个不用回表的索引实际执行更快,为什么选择了不用回表的索引? + + 碰到这种情况,可能是代价估算时对于回表的代价计算得过大,可以调小 `tidb_opt_network_factor`,降低回表的代价。 + +## 控制索引的选择 + +通过 [Optimizer Hints](/optimizer-hints.md) 可以实现单条查询对索引选择的控制。 + +- `USE_INDEX`/`IGNORE_INDEX` 可以强制优化器使用/不使用某些索引。 + +- `READ_FROM_STORAGE` 可以强制优化器对于某些表选择 TiKV/TiFlash 的存储引擎进行查询。 diff --git a/column-pruning.md b/column-pruning.md new file mode 100644 index 000000000000..e3db40df00e0 --- /dev/null +++ b/column-pruning.md @@ -0,0 +1,20 @@ +--- +title: 列裁剪 +category: performance +--- + +# 列裁剪 + +列裁剪的基本思想在于:对于算子中实际用不上的列,优化器在优化的过程中没有必要保留它们。 对这些列的删除会减少 I/O 资源占用,并为后续的优化带来便利。下面给出一个列重复的例子: + +假设表 t 里面有 a b c d 四列,执行如下语句: + +{{< copyable "sql" >}} + +```sql +select a from t where b > 5 +``` + +在该查询的过程中,t 表实际上只有 a, b 两列会被用到,而 c, d 的数据则显得多余。对应到该语句的查询计划,Selection 算子会用到 b 列,下面接着的 DataSource 算子会用到 a, b 两列,而剩下 c, d 两列则都可以裁剪掉,DataSource 算子在读数据时不需要将它们读进来。 + +出于上述考量,TiDB 会在逻辑优化阶段进行自上而下的扫描,裁剪不需要的列,减少资源浪费。该扫描过程称作 “列裁剪”,对应逻辑优化规则中的 `columnPruner`。如果要关闭这个规则,可以在参照[优化规则及表达式下推的黑名单](/blacklist-control-plan.md)中的关闭方法。 diff --git a/command-line-flags-for-pd-configuration.md b/command-line-flags-for-pd-configuration.md new file mode 100644 index 000000000000..bf3afdec8daf --- /dev/null +++ b/command-line-flags-for-pd-configuration.md @@ -0,0 +1,115 @@ +--- +title: PD 配置参数 +category: reference +aliases: ['/docs-cn/stable/reference/configuration/pd-server/configuration/'] +--- + +# PD 配置参数 + +PD 可以通过命令行参数或环境变量配置。 + +## `--advertise-client-urls` + ++ 对外客户端访问 URL 列表。 ++ 默认:`${client-urls}` ++ 在某些情况下,譬如 docker,或者 NAT 网络环境,客户端并不能通过 PD 自己监听的 client URLs 来访问到 PD,这时候,你就可以设置 advertise urls 来让客户端访问 ++ 例如,docker 内部 IP 地址为 172.17.0.1,而宿主机的 IP 地址为 192.168.100.113 并且设置了端口映射 `-p 2379:2379`,那么可以设置为 `--advertise-client-urls="http://192.168.100.113:2379"`,客户端可以通过 `http://192.168.100.113:2379` 来找到这个服务。 + +## `--advertise-peer-urls` + ++ 对外其他 PD 节点访问 URL 列表。 ++ 默认:`${peer-urls}` ++ 在某些情况下,譬如 docker,或者 NAT 网络环境,其他节点并不能通过 PD 自己监听的 peer URLs 来访问到 PD,这时候,你就可以设置 advertise urls 来让其他节点访问 ++ 例如,docker 内部 IP 地址为 172.17.0.1,而宿主机的 IP 地址为 192.168.100.113 并且设置了端口映射 `-p 2380:2380`,那么可以设置为 `--advertise-peer-urls="http://192.168.100.113:2380"`,其他 PD 节点可以通过 `http://192.168.100.113:2380` 来找到这个服务。 + +## `--client-urls` + ++ 处理客户端请求监听 URL 列表。 ++ 默认:`http://127.0.0.1:2379` ++ 如果部署一个集群,\-\-client-urls 必须指定当前主机的 IP 地址,例如 `http://192.168.100.113:2379"`,如果是运行在 docker 则需要指定为 `http://0.0.0.0:2379`。 + +## `--peer-urls` + ++ 处理其他 PD 节点请求监听 URL 列表。 ++ default: `http://127.0.0.1:2380` ++ 如果部署一个集群,\-\-peer-urls 必须指定当前主机的 IP 地址,例如 `http://192.168.100.113:2380`,如果是运行在 docker 则需要指定为 `http://0.0.0.0:2380`。 + +## `--config` + ++ 配置文件。 ++ 默认:"" ++ 如果你指定了配置文件,PD 会首先读取配置文件的配置。然后如果对应的配置在命令行参数里面也存在,PD 就会使用命令行参数的配置来覆盖配置文件里面的。 + +## `--data-dir` + ++ PD 存储数据路径。 ++ 默认:`default.${name}` + +## `--initial-cluster` + ++ 初始化 PD 集群配置。 ++ 默认:`"{name}=http://{advertise-peer-url}"` ++ 例如,如果 name 是 "pd", 并且 `advertise-peer-urls` 是 `http://192.168.100.113:2380`, 那么 `initial-cluster` 就是 `pd=http://192.168.100.113:2380`。 ++ 如果你需要启动三台 PD,那么 `initial-cluster` 可能就是 + `pd1=http://192.168.100.113:2380, pd2=http://192.168.100.114:2380, pd3=192.168.100.115:2380`。 + +## `--join` + ++ 动态加入 PD 集群。 ++ 默认:"" ++ 如果你想动态将一台 PD 加入集群,你可以使用 `--join="${advertise-client-urls}"`, `advertise-client-url` 是当前集群里面任意 PD 的 `advertise-client-url`,你也可以使用多个 PD 的,需要用逗号分隔。 + +## `-L` + ++ Log 级别。 ++ 默认:"info" ++ 我们能选择 debug, info, warn, error 或者 fatal。 + +## `--log-file` + ++ Log 文件。 ++ 默认:"" ++ 如果没设置这个参数,log 会默认输出到 "stderr",如果设置了,log 就会输出到对应的文件里面,在每天凌晨,log 会自动轮转使用一个新的文件,并且将以前的文件改名备份。 + +## `--log-rotate` + ++ 是否开启日志切割。 ++ 默认:true ++ 当值为 true 时,按照 PD 配置文件中 `[log.file]` 信息执行。 + +## `--name` + ++ 当前 PD 的名字。 ++ 默认:"pd" ++ 如果你需要启动多个 PD,一定要给 PD 使用不同的名字 + +## `--cacert` + ++ CA 文件路径,用于开启 TLS。 ++ 默认:"" + +## `--cert` + ++ 包含 X509 证书的 PEM 文件路径,用户开启 TLS。 ++ 默认:"" + +## `--key` + ++ 包含 X509 key 的 PEM 文件路径,用于开启 TLS。 ++ 默认:"" + +## `--metrics-addr` + ++ 指定 Prometheus Pushgateway 的地址。 ++ 默认:"" ++ 如果留空,则不开启 Prometheus Push。 + +## `--force-new-cluster` + ++ 强制使用当前节点创建新的集群。 ++ 默认:false ++ 仅用于在 PD 丢失多数副本的情况下恢复服务,可能会产生部分数据丢失。 + +## `-V`, `--version` + ++ 输出版本信息并退出。 diff --git a/command-line-flags-for-tidb-configuration.md b/command-line-flags-for-tidb-configuration.md new file mode 100644 index 000000000000..fd296ba4896b --- /dev/null +++ b/command-line-flags-for-tidb-configuration.md @@ -0,0 +1,186 @@ +--- +title: TiDB 配置参数 +category: reference +aliases: ['/docs-cn/stable/reference/configuration/tidb-server/configuration/'] +--- + +# TiDB 配置参数 + +在启动 TiDB 时,你可以使用命令行参数或环境变量来配置 TiDB。本文将详细介绍 TiDB 的命令行启动参数。TiDB 的默认端口为 4000(客户端请求)与 10080(状态报告)。 + +## `--advertise-address` + ++ 登录 TiDB 的 IP 地址 ++ 默认:"" ++ 必须确保用户和集群中的其他机器都能够访问到该 IP 地址 + +## `--binlog-socket` + ++ TiDB 服务使用 unix socket file 方式接受内部连接,如 Pump 服务 ++ 默认:"" ++ 例如,可以使用 "/tmp/pump.sock" 来接受 Pump unix socket file 通信 + +## `--config` + ++ 配置文件 ++ 默认:"" ++ 如果你指定了配置文件,TiDB 会首先读取配置文件的配置。如果对应的配置在命令行参数里面也存在,TiDB 就会使用命令行参数的配置来覆盖配置文件中的配置。详细的配置项请参阅 [TiDB 配置文件描述](/tidb-configuration-file.md)。 + +## `--cors` + ++ 用于设置 TiDB HTTP 状态服务的 Access-Control-Allow-Origin ++ 默认:"" + +## `--host` + ++ TiDB 服务监听的 host ++ 默认:"0.0.0.0" ++ 0.0.0.0 默认会监听所有的网卡地址。如果有多块网卡,可以指定对外提供服务的网卡,如 192.168.100.113 + +## `--enable-binlog` + ++ 是否产生 TiDB binlog ++ 默认:false + +## `-L` + ++ Log 级别 ++ 默认:"info" ++ 可选项为:debug、info、warn、error、fatal + +## `--log-file` + ++ Log 文件 ++ 默认:"" ++ 如果未设置该参数,log 会默认输出到 "stderr";如果设置了该参数,log 会输出到对应的文件中。每天凌晨,log 会自动轮转使用一个新的文件,并且将以前的文件改名备份 + +## `--log-slow-query` + ++ 慢查询日志文件路径 ++ 默认:"" ++ 如果未设置该参数,log 会默认输出到 `--log-file` 指定的文件中 + +## `--metrics-addr` + ++ Prometheus Pushgateway 地址 ++ 默认:"" ++ 如果该参数为空,TiDB 不会将统计信息推送给 Pushgateway。参数格式示例:`--metrics-addr=192.168.100.115:9091` + +## `--metrics-interval` + ++ 推送统计信息到 Prometheus Pushgateway 的时间间隔 ++ 默认:15s ++ 设置为 0 表示不推送统计信息给 Pushgateway。示例:`--metrics-interval=2` 指每两秒推送到 Pushgateway + +## `-P` + ++ TiDB 服务监听端口 ++ 默认:"4000" ++ TiDB 服务会使用该端口接受 MySQL 客户端发来的请求 + +## `--path` + ++ 对于本地存储引擎 "mocktikv" 来说,path 指定的是实际的数据存放路径 ++ 当 `--store = tikv` 时,必须指定 path;当 `--store = mocktikv` 时,如果不指定 path,会使用默认值。 ++ 对于 "TiKV" 存储引擎来说,path 指定的是实际的 PD 地址。假如在 192.168.100.113:2379、192.168.100.114:2379 和 192.168.100.115:2379 上面部署了 PD,那么 path 为 "192.168.100.113:2379, 192.168.100.114:2379, 192.168.100.115:2379" ++ 默认:"/tmp/tidb" ++ 可以通过 `tidb-server --store=mocktikv --path=""` 来启动一个纯内存引擎的 TiDB + +## `--tmp-storage-path` + ++ TiDB 临时磁盘存储位置。 ++ 默认:`<操作系统临时文件夹>/tidb/tmp-storage` + +## `--proxy-protocol-networks` + ++ PROXY Protocol 允许的代理服务器地址列表。如需配置多个地址,用 `,` 分隔。 ++ 默认:"" ++ 如果该参数为空,TiDB 会禁用 PROXY Protocol 功能。地址可以使用 IP 地址 (192.168.1.50) 或者 CIDR (192.168.1.0/24),`*` 代表所有地址。 + +## `--proxy-protocol-header-timeout` + ++ PROXY Protocol 请求头读取超时时间 ++ 默认:5 ++ 单位:秒 + +> **注意:** +> +> 不要将该参数配置为 `0`。除非特殊情况,一般使用默认值即可。 + +## `--report-status` + ++ 用于打开或者关闭服务状态监听端口 ++ 默认:true ++ 将参数值设置为 `true` 表明开启状态监听端口;设置为 `false` 表明关闭状态监听端口 + +## `--run-ddl` + ++ tidb-server 是否运行 DDL 语句,集群内至少需要有一台 tidb-server 设置该参数 ++ 默认:true ++ 值可以为 `true` 或者 `false`。设置为 `true` 表明自身会运行 DDL;设置为 `false` 表明自身不会运行 DDL + +## `--socket string` + ++ TiDB 服务使用 unix socket file 方式接受外部连接 ++ 默认:"" ++ 例如可以使用 "/tmp/tidb.sock" 来打开 unix socket file + +## `--status` + ++ TiDB 服务状态监听端口 ++ 默认:"10080" ++ 该端口用于展示 TiDB 内部数据,包括 [prometheus 统计](https://prometheus.io/) 和 [pprof](https://golang.org/pkg/net/http/pprof/) ++ Prometheus 统计可以通过 `http://host:status_port/metrics` 访问 ++ pprof 数据可以通过 `http://host:status_port/debug/pprof` 访问 + +## `--status-host` + ++ TiDB 服务状态监听 host ++ 默认:"0.0.0.0" + +## `--store` + ++ 用来指定 TiDB 底层使用的存储引擎 ++ 默认:"mocktikv" ++ 可以选择 "mocktikv"(本地存储引擎)或者 "tikv"(分布式存储引擎) + +## `--token-limit` + ++ TiDB 中同时允许运行的 Session 数量,用于流量控制 ++ 默认:1000 ++ 如果当前运行的连接多于该 token-limit,那么请求会阻塞,等待已经完成的操作释放 Token + +## `-V` + ++ 输出 TiDB 的版本 ++ 默认:"" + +## `--plugin-dir` + ++ plugin 存放目录 ++ 默认:"/data/deploy/plugin" + +## `--plugin-load` + ++ 需要加载的 plugin 名称,多个 plugin 以 "," 逗号分隔 ++ 默认:"" + +## `--affinity-cpus` + ++ 设置 TiDB server CPU 亲和性,以 "," 逗号分隔,例如 "1,2,3" ++ 默认:"" + +## `--repair-mode` + ++ 是否开启修复模式,仅用于数据修复场景 ++ 默认:false + +## `--repair-list` + ++ 修复模式下需要修复的表名 ++ 默认:"" + +## `--require-secure-transport` + ++ 是否要求客户端使用安全传输模式 ++ 默认:false diff --git a/command-line-flags-for-tikv-configuration.md b/command-line-flags-for-tikv-configuration.md new file mode 100644 index 000000000000..a5d989d55acf --- /dev/null +++ b/command-line-flags-for-tikv-configuration.md @@ -0,0 +1,75 @@ +--- +title: TiKV 配置参数 +category: reference +aliases: ['/docs-cn/stable/reference/configuration/tikv-server/configuration/'] +--- + +# TiKV 配置参数 + +TiKV 的命令行参数支持一些可读性好的单位转换。 + ++ 文件大小(以 bytes 为单位):KB, MB, GB, TB, PB(也可以全小写) ++ 时间(以毫秒为单位):ms, s, m, h + +## `-A, --addr` + ++ TiKV 监听地址 ++ 默认:"127.0.0.1:20160" ++ 如果部署一个集群,\-\-addr 必须指定当前主机的 IP 地址,例如 "192.168.100.113:20160",如果是运行在 docker 则需要指定为 "0.0.0.0:20160" + +## `--advertise-addr` + ++ TiKV 对外访问地址。 ++ 默认:${addr} ++ 在某些情况下,比如 Docker 或者 NAT 网络环境,客户端并不能通过 `--addr` 的地址来访问到 TiKV。这时候,你可以设置 `--advertise-addr` 来让客户端访问 TiKV。 ++ 例如,docker 内部 IP 地址为 172.17.0.1,而宿主机的 IP 地址为 192.168.100.113 并且设置了端口映射 -p 20160:20160,那么可以设置为 \-\-advertise-addr="192.168.100.113:20160",客户端可以通过 192.168.100.113:20160 来找到这个服务 + +## `--status-addr` + ++ TiKV 服务状态监听端口 ++ 默认:"20180" ++ Prometheus 统计可以通过 `http://host:status_port/metrics` 访问 ++ Profile 数据可以通过 `http://host:status_port/debug/pprof/profile` 访问 + +## `--advertise-status-addr` + ++ TiKV 对外访问服务状态地址 ++ 默认:使用 `--status-addr` ++ 在某些情况下,例如 docker 或者 NAT 网络环境,客户端并不能通过 `--status-addr` 的地址来访问到 TiKV。此时,你可以设置 `--advertise-status-addr` 来让客户端访问 TiKV。 ++ 例如,Docker 内部 IP 地址为 `172.17.0.1`,而宿主机的 IP 地址为 `192.168.100.113` 并且设置了端口映射 `-p 20180:20180`,那么可以设置 `\-\-advertise-status-addr="192.168.100.113:20180"`,客户端可以通过 `192.168.100.113:20180` 来找到这个服务。 + +## `-C, --config` + ++ 配置文件 ++ 默认:"" ++ 如果你指定了配置文件,TiKV 会首先读取配置文件的配置。然后如果对应的配置在命令行参数里面也存在,TiKV 就会使用命令行参数的配置来覆盖配置文件里面的 + +## `--capacity` + ++ TiKV 存储数据的容量 ++ 默认:0 (无限) ++ PD 需要使用这个值来对整个集群做 balance 操作。(提示:你可以使用 10GB 来替代 10737418240,从而简化参数的传递) + +## `--data-dir` + ++ TiKV 数据存储路径 ++ 默认:"/tmp/tikv/store" + +## `-L, --log` + ++ Log 级别 ++ 默认:"info" ++ 我们能选择 trace, debug, info, warn, error, 或者 off + +## `--log-file` + ++ Log 文件 ++ 默认:"" ++ 如果没设置这个参数,log 会默认输出到 "stderr",如果设置了,log 就会输出到对应的文件里面,在每天凌晨,log 会自动轮转使用一个新的文件,并且将以前的文件改名备份 + +## `--pd` + ++ PD 地址列表。 ++ 默认:"" ++ TiKV 必须使用这个值连接 PD,才能正常工作。使用逗号来分隔多个 PD 地址,例如: + 192.168.100.113:2379, 192.168.100.114:2379, 192.168.100.115:2379 diff --git a/comment-syntax.md b/comment-syntax.md new file mode 100644 index 000000000000..2d423aae92f7 --- /dev/null +++ b/comment-syntax.md @@ -0,0 +1,146 @@ +--- +title: 注释语法 +category: reference +summary: 本文介绍 TiDB 支持的注释语法。 +aliases: ['/docs-cn/stable/reference/sql/language-structure/comment-syntax/'] +--- + +# 注释语法 + +本文档介绍 TiDB 支持的注释语法。 + +TiDB 支持三种注释风格: + +* 用 `#` 注释一行: + + {{< copyable "sql" >}} + + ```sql + SELECT 1+1; # 注释文字 + ``` + + ``` + +------+ + | 1+1 | + +------+ + | 2 | + +------+ + 1 row in set (0.00 sec) + ``` + +* 用 `--` 注释一行: + + {{< copyable "sql" >}} + + ```sql + SELECT 1+1; -- 注释文字 + ``` + + ``` + +------+ + | 1+1 | + +------+ + | 2 | + +------+ + 1 row in set (0.00 sec) + ``` + + 用 `--` 注释时,必须要在其之后留出至少一个空格,否则注释不生效: + + {{< copyable "sql" >}} + + ```sql + SELECT 1+1--1; + ``` + + ``` + +--------+ + | 1+1--1 | + +--------+ + | 3 | + +--------+ + 1 row in set (0.01 sec) + ``` + +* 用 `/* */` 注释一块,可以注释多行: + + {{< copyable "sql" >}} + + ```sql + SELECT 1 /* 这是行内注释文字 */ + 1; + ``` + + ``` + +--------+ + | 1 + 1 | + +--------+ + | 2 | + +--------+ + 1 row in set (0.01 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + SELECT 1+ + -> /* + /*> 这是一条 + /*> 多行注释 + /*> */ + -> 1; + ``` + + ``` + +-------+ + | 1+ + + 1 | + +-------+ + | 2 | + +-------+ + 1 row in set (0.00 sec) + ``` + +## MySQL 兼容的注释语法 + +TiDB 也跟 MySQL 保持一致,支持一种 C 风格注释的变体: + +``` +/*! Specific code */ +``` + +或者 + +``` +/*!50110 Specific code */ +``` + +在这种格式中,TiDB 会执行注释中的语句,这个语法是为了让这些 SQL 在其他的数据库中被忽略,而在 TiDB 中被执行。 + +例如:`SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2 WHERE ...` + +在 TiDB 中,这种写法等价于 `SELECT STRAIGHT_JOIN col1 FROM table1,table2 WHERE ...` + +如果注释中指定了 Server 版本号,例如 `/*!50110 KEY_BLOCK_SIZE=1024 */`,在 MySQL 中表示只有 MySQL 的版本大于等于 5.1.10 才会处理这个 comment 中的内容。但是在 TiDB 中,这个 MySQL 版本号不会起作用,所有的 comment 都被会处理。 + +## TiDB 可执行的注释语法 + +TiDB 也有独立的注释语法,称为 TiDB 可执行注释语法,格式为 `/*T![feature_id] XXX */`。只有在当前版本中实现了 `feature_id` 对应的功能特性的 TiDB,才会试图解析该注释里的 SQL 片段。例如 v3.1.1 中引入了 `AUTO_RANDOM` 特性,该版本能够将 `/*T![auto_rand] auto_random */` 解析为 `auto_random`;而 v3.0.0 中没有实现 `AUTO_RANDOM` 特性,则上述 SQL 语句片段会被忽略。 + +## 优化器注释语法 + +还有一种注释会被当做是优化器 Hint 特殊对待: + +{{< copyable "sql" >}} + +```sql +SELECT /*+ hint */ FROM ...; +``` + +TiDB 支持的相关优化器 hint 详见 [Optimizer Hints](/optimizer-hints.md)。 + +> **注意** +> +> 由于 TiDB 可执行注释语法和优化器注释语法在 MySQL 客户端 5.7.7 之前的版本中,会被默认当成 comment 清除掉,如果需要在旧的客户端使用这两种语法,需要在启动客户端时加上 --comments 选项,例如 `mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 + +更多细节,请参考 [MySQL 文档](https://dev.mysql.com/doc/refman/5.7/en/comments.html)。 diff --git a/config-templates/complex-cdc.yaml b/config-templates/complex-cdc.yaml new file mode 100644 index 000000000000..e4267e371912 --- /dev/null +++ b/config-templates/complex-cdc.yaml @@ -0,0 +1,126 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +# # Monitored variables are applied to all the machines. +monitored: + node_exporter_port: 9100 + blackbox_exporter_port: 9115 + # deploy_dir: "/tidb-deploy/monitored-9100" + # data_dir: "/tidb-data/monitored-9100" + # log_dir: "/tidb-deploy/monitored-9100/log" + +# # Server configs are used to specify the runtime configuration of TiDB components. +# # All configuration items can be found in TiDB docs: +# # - TiDB: https://pingcap.com/docs/stable/reference/configuration/tidb-server/configuration-file/ +# # - TiKV: https://pingcap.com/docs/stable/reference/configuration/tikv-server/configuration-file/ +# # - PD: https://pingcap.com/docs/stable/reference/configuration/pd-server/configuration-file/ +# # All configuration items use points to represent the hierarchy, e.g: +# # readpool.storage.use-unified-pool +# # +# # You can overwrite this configuration via the instance-level `config` field. + +server_configs: + tidb: + log.slow-threshold: 300 + tikv: + # server.grpc-concurrency: 4 + # raftstore.apply-pool-size: 2 + # raftstore.store-pool-size: 2 + # rocksdb.max-sub-compactions: 1 + # storage.block-cache.capacity: "16GB" + # readpool.unified.max-thread-count: 12 + readpool.storage.use-unified-pool: false + readpool.coprocessor.use-unified-pool: true + pd: + schedule.leader-schedule-limit: 4 + schedule.region-schedule-limit: 2048 + schedule.replica-schedule-limit: 64 + +pd_servers: + - host: 10.0.1.4 + # ssh_port: 22 + # name: "pd-1" + # client_port: 2379 + # peer_port: 2380 + # deploy_dir: "/tidb-deploy/pd-2379" + # data_dir: "/tidb-data/pd-2379" + # log_dir: "/tidb-deploy/pd-2379/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.pd` values. + # config: + # schedule.max-merge-region-size: 20 + # schedule.max-merge-region-keys: 200000 + - host: 10.0.1.5 + - host: 10.0.1.6 + +tidb_servers: + - host: 10.0.1.1 + # ssh_port: 22 + # port: 4000 + # status_port: 10080 + # deploy_dir: "/tidb-deploy/tidb-4000" + # log_dir: "/tidb-deploy/tidb-4000/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tidb` values. + # config: + # log.slow-query-file: tidb-slow-overwrited.log + - host: 10.0.1.2 + - host: 10.0.1.3 + +tikv_servers: + - host: 10.0.1.7 + # ssh_port: 22 + # port: 20160 + # status_port: 20180 + # deploy_dir: "/tidb-deploy/tikv-20160" + # data_dir: "/tidb-data/tikv-20160" + # log_dir: "/tidb-deploy/tikv-20160/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tikv` values. + # config: + # server.grpc-concurrency: 4 + # server.labels: { zone: "zone1", dc: "dc1", host: "host1" } + + - host: 10.0.1.8 + - host: 10.0.1.9 + +cdc_servers: + - host: 10.0.1.1 + port: 8300 + deploy_dir: "/tidb-deploy/cdc-8300" + log_dir: "/tidb-deploy/cdc-8300/log" + - host: 10.0.1.2 + port: 8300 + deploy_dir: "/tidb-deploy/cdc-8300" + log_dir: "/tidb-deploy/cdc-8300/log" + - host: 10.0.1.3 + port: 8300 + deploy_dir: "/tidb-deploy/cdc-8300" + log_dir: "/tidb-deploy/cdc-8300/log" + +monitoring_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # port: 9090 + # deploy_dir: "/tidb-deploy/prometheus-8249" + # data_dir: "/tidb-data/prometheus-8249" + # log_dir: "/tidb-deploy/prometheus-8249/log" + +grafana_servers: + - host: 10.0.1.10 + # port: 3000 + # deploy_dir: /tidb-deploy/grafana-3000 + +alertmanager_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # web_port: 9093 + # cluster_port: 9094 + # deploy_dir: "/tidb-deploy/alertmanager-9093" + # data_dir: "/tidb-data/alertmanager-9093" + # log_dir: "/tidb-deploy/alertmanager-9093/log" \ No newline at end of file diff --git a/config-templates/complex-mini.yaml b/config-templates/complex-mini.yaml new file mode 100644 index 000000000000..4a4807867a2a --- /dev/null +++ b/config-templates/complex-mini.yaml @@ -0,0 +1,113 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +# # Monitored variables are applied to all the machines. +monitored: + node_exporter_port: 9100 + blackbox_exporter_port: 9115 + # deploy_dir: "/tidb-deploy/monitored-9100" + # data_dir: "/tidb-data/monitored-9100" + # log_dir: "/tidb-deploy/monitored-9100/log" + +# # Server configs are used to specify the runtime configuration of TiDB components. +# # All configuration items can be found in TiDB docs: +# # - TiDB: https://pingcap.com/docs/stable/reference/configuration/tidb-server/configuration-file/ +# # - TiKV: https://pingcap.com/docs/stable/reference/configuration/tikv-server/configuration-file/ +# # - PD: https://pingcap.com/docs/stable/reference/configuration/pd-server/configuration-file/ +# # All configuration items use points to represent the hierarchy, e.g: +# # readpool.storage.use-unified-pool +# # +# # You can overwrite this configuration via the instance-level `config` field. + +server_configs: + tidb: + log.slow-threshold: 300 + binlog.enable: false + binlog.ignore-error: false + tikv: + # server.grpc-concurrency: 4 + # raftstore.apply-pool-size: 2 + # raftstore.store-pool-size: 2 + # rocksdb.max-sub-compactions: 1 + # storage.block-cache.capacity: "16GB" + # readpool.unified.max-thread-count: 12 + readpool.storage.use-unified-pool: false + readpool.coprocessor.use-unified-pool: true + pd: + schedule.leader-schedule-limit: 4 + schedule.region-schedule-limit: 2048 + schedule.replica-schedule-limit: 64 + +pd_servers: + - host: 10.0.1.4 + # ssh_port: 22 + # name: "pd-1" + # client_port: 2379 + # peer_port: 2380 + # deploy_dir: "/tidb-deploy/pd-2379" + # data_dir: "/tidb-data/pd-2379" + # log_dir: "/tidb-deploy/pd-2379/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.pd` values. + # config: + # schedule.max-merge-region-size: 20 + # schedule.max-merge-region-keys: 200000 + - host: 10.0.1.5 + - host: 10.0.1.6 + +tidb_servers: + - host: 10.0.1.1 + # ssh_port: 22 + # port: 4000 + # status_port: 10080 + # deploy_dir: "/tidb-deploy/tidb-4000" + # log_dir: "/tidb-deploy/tidb-4000/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tidb` values. + # config: + # log.slow-query-file: tidb-slow-overwrited.log + - host: 10.0.1.2 + - host: 10.0.1.3 + +tikv_servers: + - host: 10.0.1.7 + # ssh_port: 22 + # port: 20160 + # status_port: 20180 + # deploy_dir: "/tidb-deploy/tikv-20160" + # data_dir: "/tidb-data/tikv-20160" + # log_dir: "/tidb-deploy/tikv-20160/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tikv` values. + # config: + # server.grpc-concurrency: 4 + # server.labels: { zone: "zone1", dc: "dc1", host: "host1" } + - host: 10.0.1.8 + - host: 10.0.1.9 + +monitoring_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # port: 9090 + # deploy_dir: "/tidb-deploy/prometheus-8249" + # data_dir: "/tidb-data/prometheus-8249" + # log_dir: "/tidb-deploy/prometheus-8249/log" + +grafana_servers: + - host: 10.0.1.10 + # port: 3000 + # deploy_dir: /tidb-deploy/grafana-3000 + +alertmanager_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # web_port: 9093 + # cluster_port: 9094 + # deploy_dir: "/tidb-deploy/alertmanager-9093" + # data_dir: "/tidb-data/alertmanager-9093" + # log_dir: "/tidb-deploy/alertmanager-9093/log" \ No newline at end of file diff --git a/config-templates/complex-multi-instance.yaml b/config-templates/complex-multi-instance.yaml new file mode 100644 index 000000000000..2513d0b3869c --- /dev/null +++ b/config-templates/complex-multi-instance.yaml @@ -0,0 +1,150 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +monitored: + node_exporter_port: 9100 + blackbox_exporter_port: 9115 + deploy_dir: "/tidb-deploy/monitored-9100" + data_dir: "/tidb-data-monitored-9100" + log_dir: "/tidb-deploy/monitored-9100/log" + +server_configs: + tidb: + log.slow-threshold: 300 + tikv: + readpool.unified.max-thread-count: + readpool.storage.use-unified-pool: false + readpool.coprocessor.use-unified-pool: true + storage.block-cache.capacity: "" + raftstore.capacity: "" + pd: + replication.location-labels: ["host"] + schedule.leader-schedule-limit: 4 + schedule.region-schedule-limit: 2048 + schedule.replica-schedule-limit: 64 + +pd_servers: + - host: 10.0.1.4 + - host: 10.0.1.5 + - host: 10.0.1.6 + +tidb_servers: + - host: 10.0.1.1 + port: 4000 + status_port: 10080 + deploy_dir: "/tidb-deploy/tidb-4000" + log_dir: "/tidb-deploy/tidb-4000/log" + numa_node: "0" + - host: 10.0.1.1 + port: 4001 + status_port: 10081 + deploy_dir: "/tidb-deploy/tidb-4001" + log_dir: "/tidb-deploy/tidb-4001/log" + numa_node: "1" + - host: 10.0.1.2 + port: 4000 + status_port: 10080 + deploy_dir: "/tidb-deploy/tidb-4000" + log_dir: "/tidb-deploy/tidb-4000/log" + numa_node: "0" + - host: 10.0.1.2 + port: 4001 + status_port: 10081 + deploy_dir: "/tidb-deploy/tidb-4001" + log_dir: "/tidb-deploy/tidb-4001/log" + numa_node: "1" + - host: 10.0.1.3 + port: 4000 + status_port: 10080 + deploy_dir: "/tidb-deploy/tidb-4000" + log_dir: "/tidb-deploy/tidb-4000/log" + numa_node: "0" + - host: 10.0.1.3 + port: 4001 + status_port: 10081 + deploy_dir: "/tidb-deploy/tidb-4001" + log_dir: "/tidb-deploy/tidb-4001/log" + numa_node: "1" + +tikv_servers: + - host: 10.0.1.7 + port: 20160 + status_port: 20180 + deploy_dir: "/tidb-deploy/tikv-20160" + data_dir: "/tidb-data/tikv-20160" + log_dir: "/tidb-deploy/tikv-20160/log" + numa_node: "0" + config: + server.labels: { host: "tikv1" } + - host: 10.0.1.7 + port: 20161 + status_port: 20181 + deploy_dir: "/tidb-deploy/tikv-20161" + data_dir: "/tidb-data/tikv-20161" + log_dir: "/tidb-deploy/tikv-20161/log" + numa_node: "1" + config: + server.labels: { host: "tikv1" } + - host: 10.0.1.8 + port: 20160 + status_port: 20180 + deploy_dir: "/tidb-deploy/tikv-20160" + data_dir: "/tidb-data/tikv-20160" + log_dir: "/tidb-deploy/tikv-20160/log" + numa_node: "0" + config: + server.labels: { host: "tikv2" } + - host: 10.0.1.8 + port: 20161 + status_port: 20181 + deploy_dir: "/tidb-deploy/tikv-20161" + data_dir: "/tidb-data/tikv-20161" + log_dir: "/tidb-deploy/tikv-20161/log" + numa_node: "1" + config: + server.labels: { host: "tikv2" } + - host: 10.0.1.9 + port: 20160 + status_port: 20180 + deploy_dir: "/tidb-deploy/tikv-20160" + data_dir: "/tidb-data/tikv-20160" + log_dir: "/tidb-deploy/tikv-20160/log" + numa_node: "0" + config: + server.labels: { host: "tikv3" } + - host: 10.0.1.9 + port: 20161 + status_port: 20181 + deploy_dir: "/tidb-deploy/tikv-20161" + data_dir: "/tidb-data/tikv-20161" + log_dir: "/tidb-deploy/tikv-20161/log" + numa_node: "1" + config: + server.labels: { host: "tikv3" } + +monitoring_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # port: 9090 + # deploy_dir: "/tidb-deploy/prometheus-8249" + # data_dir: "/tidb-data/prometheus-8249" + # log_dir: "/tidb-deploy/prometheus-8249/log" + +grafana_servers: + - host: 10.0.1.10 + # port: 3000 + # deploy_dir: /tidb-deploy/grafana-3000 + +alertmanager_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # web_port: 9093 + # cluster_port: 9094 + # deploy_dir: "/tidb-deploy/alertmanager-9093" + # data_dir: "/tidb-data/alertmanager-9093" + # log_dir: "/tidb-deploy/alertmanager-9093/log" \ No newline at end of file diff --git a/config-templates/complex-tidb-binlog.yaml b/config-templates/complex-tidb-binlog.yaml new file mode 100644 index 000000000000..36db4f2ca451 --- /dev/null +++ b/config-templates/complex-tidb-binlog.yaml @@ -0,0 +1,152 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +# # Monitored variables are applied to all the machines. +monitored: + node_exporter_port: 9100 + blackbox_exporter_port: 9115 + # deploy_dir: "/tidb-deploy/monitored-9100" + # data_dir: "/tidb-data/monitored-9100" + # log_dir: "/tidb-deploy/monitored-9100/log" + +# # Server configs are used to specify the runtime configuration of TiDB components. +# # All configuration items can be found in TiDB docs: +# # - TiDB: https://pingcap.com/docs/stable/reference/configuration/tidb-server/configuration-file/ +# # - TiKV: https://pingcap.com/docs/stable/reference/configuration/tikv-server/configuration-file/ +# # - PD: https://pingcap.com/docs/stable/reference/configuration/pd-server/configuration-file/ +# # All configuration items use points to represent the hierarchy, e.g: +# # readpool.storage.use-unified-pool +# # +# # You can overwrite this configuration via the instance-level `config` field. + +server_configs: + tidb: + log.slow-threshold: 300 + binlog.enable: true + binlog.ignore-error: true + tikv: + # server.grpc-concurrency: 4 + # raftstore.apply-pool-size: 2 + # raftstore.store-pool-size: 2 + # rocksdb.max-sub-compactions: 1 + # storage.block-cache.capacity: "16GB" + # readpool.unified.max-thread-count: 12 + readpool.storage.use-unified-pool: false + readpool.coprocessor.use-unified-pool: true + pd: + schedule.leader-schedule-limit: 4 + schedule.region-schedule-limit: 2048 + schedule.replica-schedule-limit: 64 + +pd_servers: + - host: 10.0.1.4 + # ssh_port: 22 + # name: "pd-1" + # client_port: 2379 + # peer_port: 2380 + # deploy_dir: "/tidb-deploy/pd-2379" + # data_dir: "/tidb-data/pd-2379" + # log_dir: "/tidb-deploy/pd-2379/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.pd` values. + # config: + # schedule.max-merge-region-size: 20 + # schedule.max-merge-region-keys: 200000 + - host: 10.0.1.5 + - host: 10.0.1.6 +tidb_servers: + - host: 10.0.1.1 + # ssh_port: 22 + # port: 4000 + # status_port: 10080 + # deploy_dir: "/tidb-deploy/tidb-4000" + # log_dir: "/tidb-deploy/tidb-4000/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tidb` values. + # config: + # log.slow-query-file: tidb-slow-overwrited.log + - host: 10.0.1.2 + - host: 10.0.1.3 +tikv_servers: + - host: 10.0.1.7 + # ssh_port: 22 + # port: 20160 + # status_port: 20180 + # deploy_dir: "/tidb-deploy/tikv-20160" + # data_dir: "/tidb-data/tikv-20160" + # log_dir: "/tidb-deploy/tikv-20160/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tikv` values. + # config: + # server.grpc-concurrency: 4 + # server.labels: { zone: "zone1", dc: "dc1", host: "host1" } + - host: 10.0.1.8 + - host: 10.0.1.9 + +pump_servers: + - host: 10.0.1.1 + ssh_port: 22 + port: 8250 + deploy_dir: "/tidb-deploy/pump-8249" + data_dir: "/tidb-data/pump-8249" + # The following configs are used to overwrite the `server_configs.drainer` values. + config: + gc: 7 + - host: 10.0.1.2 + ssh_port: 22 + port: 8250 + deploy_dir: "/tidb-deploy/pump-8249" + data_dir: "/tidb-data/pump-8249" + # The following configs are used to overwrite the `server_configs.drainer` values. + config: + gc: 7 + - host: 10.0.1.3 + ssh_port: 22 + port: 8250 + deploy_dir: "/tidb-deploy/pump-8249" + data_dir: "/tidb-data/pump-8249" + # The following configs are used to overwrite the `server_configs.drainer` values. + config: + gc: 7 +drainer_servers: + - host: 10.0.1.12 + port: 8249 + data_dir: "/tidb-data/drainer-8249" + # If drainer doesn't have a checkpoint, use initial commitTS as the initial checkpoint. + # Will get a latest timestamp from pd if commit_ts is set to -1 (the default value). + commit_ts: -1 + deploy_dir: "/tidb-deploy/drainer-8249" + # The following configs are used to overwrite the `server_configs.drainer` values. + config: + syncer.db-type: "tidb" + syncer.to.host: "10.0.1.12" + syncer.to.user: "root" + syncer.to.password: "" + syncer.to.port: 4000 + +monitoring_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # port: 9090 + # deploy_dir: "/tidb-deploy/prometheus-8249" + # data_dir: "/tidb-data/prometheus-8249" + # log_dir: "/tidb-deploy/prometheus-8249/log" + +grafana_servers: + - host: 10.0.1.10 + # port: 3000 + # deploy_dir: /tidb-deploy/grafana-3000 + +alertmanager_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # web_port: 9093 + # cluster_port: 9094 + # deploy_dir: "/tidb-deploy/alertmanager-9093" + # data_dir: "/tidb-data/alertmanager-9093" + # log_dir: "/tidb-deploy/alertmanager-9093/log" \ No newline at end of file diff --git a/config-templates/complex-tiflash.yaml b/config-templates/complex-tiflash.yaml new file mode 100644 index 000000000000..99cf55e0f52b --- /dev/null +++ b/config-templates/complex-tiflash.yaml @@ -0,0 +1,131 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +# # Monitored variables are applied to all the machines. +monitored: + node_exporter_port: 9100 + blackbox_exporter_port: 9115 + # deploy_dir: "/tidb-deploy/monitored-9100" + # data_dir: "/tidb-data/monitored-9100" + # log_dir: "/tidb-deploy/monitored-9100/log" + +# # Server configs are used to specify the runtime configuration of TiDB components. +# # All configuration items can be found in TiDB docs: +# # - TiDB: https://pingcap.com/docs/stable/reference/configuration/tidb-server/configuration-file/ +# # - TiKV: https://pingcap.com/docs/stable/reference/configuration/tikv-server/configuration-file/ +# # - PD: https://pingcap.com/docs/stable/reference/configuration/pd-server/configuration-file/ +# # All configuration items use points to represent the hierarchy, e.g: +# # readpool.storage.use-unified-pool +# # +# # You can overwrite this configuration via the instance-level `config` field. + +server_configs: + tidb: + log.slow-threshold: 300 + tikv: + # server.grpc-concurrency: 4 + # raftstore.apply-pool-size: 2 + # raftstore.store-pool-size: 2 + # rocksdb.max-sub-compactions: 1 + # storage.block-cache.capacity: "16GB" + # readpool.unified.max-thread-count: 12 + readpool.storage.use-unified-pool: false + readpool.coprocessor.use-unified-pool: true + pd: + schedule.leader-schedule-limit: 4 + schedule.region-schedule-limit: 2048 + schedule.replica-schedule-limit: 64 + replication.enable-placement-rules: true + +pd_servers: + - host: 10.0.1.4 + # ssh_port: 22 + # name: "pd-1" + # client_port: 2379 + # peer_port: 2380 + # deploy_dir: "/tidb-deploy/pd-2379" + # data_dir: "/tidb-data/pd-2379" + # log_dir: "/tidb-deploy/pd-2379/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.pd` values. + # config: + # schedule.max-merge-region-size: 20 + # schedule.max-merge-region-keys: 200000 + - host: 10.0.1.5 + - host: 10.0.1.6 +tidb_servers: + - host: 10.0.1.7 + # ssh_port: 22 + # port: 4000 + # status_port: 10080 + # deploy_dir: "/tidb-deploy/tidb-4000" + # log_dir: "/tidb-deploy/tidb-4000/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tidb` values. + # config: + # log.slow-query-file: tidb-slow-overwrited.log + - host: 10.0.1.8 + - host: 10.0.1.9 +tikv_servers: + - host: 10.0.1.1 + # ssh_port: 22 + # port: 20160 + # status_port: 20180 + # deploy_dir: "/tidb-deploy/tikv-20160" + # data_dir: "/tidb-data/tikv-20160" + # log_dir: "/tidb-deploy/tikv-20160/log" + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tikv` values. + # config: + # server.grpc-concurrency: 4 + # server.labels: { zone: "zone1", dc: "dc1", host: "host1" } + - host: 10.0.1.2 + - host: 10.0.1.3 + +tiflash_servers: + - host: 10.0.1.11 + data_dir: /tidb-data/tiflash-9000 + deploy_dir: /tidb-deploy/tiflash-9000 + # ssh_port: 22 + # tcp_port: 9000 + # http_port: 8123 + # flash_service_port: 3930 + # flash_proxy_port: 20170 + # flash_proxy_status_port: 20292 + # metrics_port: 8234 + # deploy_dir: /tidb-deploy/tiflash-9000 + # numa_node: "0,1" + # # The following configs are used to overwrite the `server_configs.tiflash` values. + # config: + # logger.level: "info" + # learner_config: + # log-level: "info" + # - host: 10.0.1.12 + # - host: 10.0.1.13 + +monitoring_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # port: 9090 + # deploy_dir: "/tidb-deploy/prometheus-8249" + # data_dir: "/tidb-data/prometheus-8249" + # log_dir: "/tidb-deploy/prometheus-8249/log" + +grafana_servers: + - host: 10.0.1.10 + # port: 3000 + # deploy_dir: /tidb-deploy/grafana-3000 + +alertmanager_servers: + - host: 10.0.1.10 + # ssh_port: 22 + # web_port: 9093 + # cluster_port: 9094 + # deploy_dir: "/tidb-deploy/alertmanager-9093" + # data_dir: "/tidb-data/alertmanager-9093" + # log_dir: "/tidb-deploy/alertmanager-9093/log" \ No newline at end of file diff --git a/config-templates/geo-redundancy-deployment.yaml b/config-templates/geo-redundancy-deployment.yaml new file mode 100644 index 000000000000..9f18ac900a60 --- /dev/null +++ b/config-templates/geo-redundancy-deployment.yaml @@ -0,0 +1,108 @@ +# Tip: PD priority needs to be manually set using the PD-ctl client tool. such as, member Leader_priority PD-name numbers. +# Global variables are applied to all deployments and used as the default value of +# the deployments if a specific deployment value is missing. + +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" +monitored: + node_exporter_port: 9100 + blackbox_exporter_port: 9115 + deploy_dir: "/tidb-deploy/monitored-9100" +server_configs: + tidb: + log.level: debug + log.slow-query-file: tidb-slow.log + tikv: + server.grpc-compression-type: gzip + readpool.storage.use-unified-pool: true + readpool.storage.low-concurrency: 8 + pd: + replication.location-labels: ["zone","dc","rack","host"] + replication.max-replicas: 5 + label-property: + reject-leader: + - key: "dc" + value: "sha" +pd_servers: + - host: 10.0.1.6 + - host: 10.0.1.7 + - host: 10.0.1.8 + - host: 10.0.1.9 + - host: 10.0.1.10 +tidb_servers: + - host: 10.0.1.1 + - host: 10.0.1.2 + - host: 10.0.1.3 + - host: 10.0.1.4 + - host: 10.0.1.5 +tikv_servers: + - host: 10.0.1.11 + ssh_port: 22 + port: 20160 + status_port: 20180 + deploy_dir: "/tidb-deploy/tikv-20160" + data_dir: "/tidb-data/tikv-20160" + config: + server.labels: + zone: bj + dc: bja + rack: rack1 + host: host1 + - host: 10.0.1.12 + ssh_port: 22 + port: 20161 + status_port: 20181 + deploy_dir: "/tidb-deploy/tikv-20161" + data_dir: "/tidb-data/tikv-20161" + config: + server.labels: + zone: bj + dc: bja + rack: rack1 + host: host2 + - host: 10.0.1.13 + ssh_port: 22 + port: 20160 + status_port: 20180 + deploy_dir: "/tidb-deploy/tikv-20160" + data_dir: "/tidb-data/tikv-20160" + config: + server.labels: + zone: bj + dc: bjb + rack: rack1 + host: host1 + - host: 10.0.1.14 + ssh_port: 22 + port: 20161 + status_port: 20181 + deploy_dir: "/tidb-deploy/tikv-20161" + data_dir: "/tidb-data/tikv-20161" + config: + server.labels: + zone: bj + dc: bjb + rack: rack1 + host: host2 + - host: 10.0.1.15 + ssh_port: 22 + port: 20160 + deploy_dir: "/tidb-deploy/tikv-20160" + data_dir: "/tidb-data/tikv-20160" + config: + server.labels: + zone: sh + dc: sha + rack: rack1 + host: host1 + readpool.storage.use-unified-pool: true + readpool.storage.low-concurrency: 10 + raftstore.raft-min-election-timeout-ticks: 1000 + raftstore.raft-max-election-timeout-ticks: 1020 +monitoring_servers: + - host: 10.0.1.16 +grafana_servers: + - host: 10.0.1.16 \ No newline at end of file diff --git a/config-templates/simple-cdc.yaml b/config-templates/simple-cdc.yaml new file mode 100644 index 000000000000..4d820082de20 --- /dev/null +++ b/config-templates/simple-cdc.yaml @@ -0,0 +1,36 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +pd_servers: + - host: 10.0.1.4 + - host: 10.0.1.5 + - host: 10.0.1.6 + +tidb_servers: + - host: 10.0.1.1 + - host: 10.0.1.2 + - host: 10.0.1.3 + +tikv_servers: + - host: 10.0.1.7 + - host: 10.0.1.8 + - host: 10.0.1.9 + +cdc_servers: + - host: 10.0.1.7 + - host: 10.0.1.8 + - host: 10.0.1.9 + +monitoring_servers: + - host: 10.0.1.10 + +grafana_servers: + - host: 10.0.1.10 + +alertmanager_servers: + - host: 10.0.1.10 \ No newline at end of file diff --git a/config-templates/simple-mini.yaml b/config-templates/simple-mini.yaml new file mode 100644 index 000000000000..57e48fd2d741 --- /dev/null +++ b/config-templates/simple-mini.yaml @@ -0,0 +1,31 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +pd_servers: + - host: 10.0.1.4 + - host: 10.0.1.5 + - host: 10.0.1.6 + +tidb_servers: + - host: 10.0.1.1 + - host: 10.0.1.2 + - host: 10.0.1.3 + +tikv_servers: + - host: 10.0.1.7 + - host: 10.0.1.8 + - host: 10.0.1.9 + +monitoring_servers: + - host: 10.0.1.10 + +grafana_servers: + - host: 10.0.1.10 + +alertmanager_servers: + - host: 10.0.1.10 \ No newline at end of file diff --git a/config-templates/simple-multi-instance.yaml b/config-templates/simple-multi-instance.yaml new file mode 100644 index 000000000000..735b3be1af61 --- /dev/null +++ b/config-templates/simple-multi-instance.yaml @@ -0,0 +1,95 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +server_configs: + tikv: + readpool.unified.max-thread-count: + readpool.storage.use-unified-pool: false + readpool.coprocessor.use-unified-pool: true + storage.block-cache.capacity: "" + raftstore.capacity: "" + pd: + replication.location-labels: ["host"] + +pd_servers: + - host: 10.0.1.4 + - host: 10.0.1.5 + - host: 10.0.1.6 + +tidb_servers: + - host: 10.0.1.1 + port: 4000 + status_port: 10080 + numa_node: "0" + - host: 10.0.1.1 + port: 4001 + status_port: 10081 + numa_node: "1" + - host: 10.0.1.2 + port: 4000 + status_port: 10080 + numa_node: "0" + - host: 10.0.1.2 + port: 4001 + status_port: 10081 + numa_node: "1" + - host: 10.0.1.3 + port: 4000 + status_port: 10080 + numa_node: "0" + - host: 10.0.1.3 + port: 4001 + status_port: 10081 + numa_node: "1" + +tikv_servers: + - host: 10.0.1.7 + port: 20160 + status_port: 20180 + numa_node: "0" + config: + server.labels: { host: "tikv1" } + - host: 10.0.1.7 + port: 20161 + status_port: 20181 + numa_node: "1" + config: + server.labels: { host: "tikv1" } + - host: 10.0.1.8 + port: 20160 + status_port: 20180 + numa_node: "0" + config: + server.labels: { host: "tikv2" } + - host: 10.0.1.8 + port: 20161 + status_port: 20181 + numa_node: "1" + config: + server.labels: { host: "tikv2" } + - host: 10.0.1.9 + port: 20160 + status_port: 20180 + numa_node: "0" + config: + server.labels: { host: "tikv3" } + - host: 10.0.1.9 + port: 20161 + status_port: 20181 + numa_node: "1" + config: + server.labels: { host: "tikv3" } + +monitoring_servers: + - host: 10.0.1.10 + +grafana_servers: + - host: 10.0.1.10 + +alertmanager_servers: + - host: 10.0.1.10 \ No newline at end of file diff --git a/config-templates/simple-tidb-binlog.yaml b/config-templates/simple-tidb-binlog.yaml new file mode 100644 index 000000000000..558023e00356 --- /dev/null +++ b/config-templates/simple-tidb-binlog.yaml @@ -0,0 +1,47 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +server_configs: + tidb: + binlog.enable: true + binlog.ignore-error: true + +pd_servers: + - host: 10.0.1.4 + - host: 10.0.1.5 + - host: 10.0.1.6 +tidb_servers: + - host: 10.0.1.1 + - host: 10.0.1.2 + - host: 10.0.1.3 +tikv_servers: + - host: 10.0.1.7 + - host: 10.0.1.8 + - host: 10.0.1.9 + +pump_servers: + - host: 10.0.1.1 + - host: 10.0.1.2 + - host: 10.0.1.3 +drainer_servers: + - host: 10.0.1.12 + config: + syncer.db-type: "tidb" + syncer.to.host: "10.0.1.12" + syncer.to.user: "root" + syncer.to.password: "" + syncer.to.port: 4000 + +monitoring_servers: + - host: 10.0.1.10 + +grafana_servers: + - host: 10.0.1.10 + +alertmanager_servers: + - host: 10.0.1.10 \ No newline at end of file diff --git a/config-templates/simple-tiflash.yaml b/config-templates/simple-tiflash.yaml new file mode 100644 index 000000000000..1e2024440854 --- /dev/null +++ b/config-templates/simple-tiflash.yaml @@ -0,0 +1,40 @@ +# # Global variables are applied to all deployments and used as the default value of +# # the deployments if a specific deployment value is missing. +global: + user: "tidb" + ssh_port: 22 + deploy_dir: "/tidb-deploy" + data_dir: "/tidb-data" + +server_configs: + pd: + replication.enable-placement-rules: true + +pd_servers: + - host: 10.0.1.4 + - host: 10.0.1.5 + - host: 10.0.1.6 + +tidb_servers: + - host: 10.0.1.7 + - host: 10.0.1.8 + - host: 10.0.1.9 + +tikv_servers: + - host: 10.0.1.1 + - host: 10.0.1.2 + - host: 10.0.1.3 + +tiflash_servers: + - host: 10.0.1.11 + data_dir: /tidb-data/tiflash-9000 + deploy_dir: /tidb-deploy/tiflash-9000 + +monitoring_servers: + - host: 10.0.1.10 + +grafana_servers: + - host: 10.0.1.10 + +alertmanager_servers: + - host: 10.0.1.10 \ No newline at end of file diff --git a/configure-load-base-split.md b/configure-load-base-split.md new file mode 100644 index 000000000000..aa715924603b --- /dev/null +++ b/configure-load-base-split.md @@ -0,0 +1,74 @@ +--- +title: Load Base Split +summary: 介绍 Load Base Split 功能。 +category: how-to +--- + +# Load Base Split + +Load Base Split 是 TiKV 在 4.0 版本引入的特性,旨在解决 Region 访问分布不均匀造成的热点问题,比如小表的全表扫描。 + +## 场景描述 + +在 TiDB 中,当流量集中在某些节点时很容易形成热点。PD 会尝试通过调度 Hot Region,尽可能让这些 Hot Region 均匀分布在各个节点上,以求获得更好的性能。 + +但是 PD 的调度的最小粒度是 Region。如果集群的热点数目少于节点数目,或者说存在某几个热点流量远高于其他 Region,对 PD 的热点调度来说,能做到的也只是让热点从一个节点转移到另一个节点,而无法让整个集群承担负载。 + +这种场景在读请求居多的 workload 中尤为常见。例如对小表的全表扫描和索引查找,或者是对一些字段的频繁访问。 + +在此之前解决此类问题的办法是手动输入命令去拆分一个或几个热点 Region,但是这样的操作存在以下两个问题: + +- 均匀拆分 Region 并不一定是最好的选择,请求可能集中在某几个 Key 上,即使均匀拆分后热点可能仍然集中在其中一个 Region 上,可能需要经过多次均匀拆分才能达到目标。 +- 人工介入不够及时和易用。 + +## 实现原理 + +Load Base Split 会基于统计信息自动拆分 Region。通过统计去识别出那些读流量在 10s 内持续超过阈值的 Region,并在合适的位置将这些 Region 拆分。在选择拆分的位置时,会尽可能平衡拆分后两个 Region 的访问量,并尽量避免跨 Region 的访问。 + +Load Base Split 后的 Region 不会被迅速 Merge。一方面,PD 的 `MergeChecker` 会跳过 hot Region ,另一方面 PD 也会针对心跳信息中的 `QPS`去进行判断,避免 Merge 两个 `QPS` 很高的 Region。 + +## 使用方法 + +目前的 Load Base Split 的控制参数为 `split.qps-threshold`。这个阈值的含义是:如果连续 10s 内,某个 Region 每秒的各类读请求之和超过 `split.qps-threshold`,那么就对此 Region 进行拆分。 + +目前默认开启 Load Base Split,但配置相对保守,默认为 `3000`。如果想要关闭这个功能,可以将这个阈值调到足够高即可。 + +目前有两种办法修改配置: + +- 通过 SQL 语句修改,例如: + + {{< copyable "sql" >}} + + ```sql + set config tikv split.qps-threshold=3000 + ``` + +- 通过 TiKV 修改,例如: + + {{< copyable "shell-regular" >}} + + ```shell + curl -X POST "http://ip:status_port/config" -H "accept: application/json" -d '{"split.qps-threshold":"3000"}' + ``` + +同理,目前也有两种办法查看配置: + +- 通过 SQL 查看,例如: + + {{< copyable "sql" >}} + + ```sql + show config where type='tikv' and name like '%split.qps-threshold%' + ``` + +- 通过 TiKV 查看,例如: + + {{< copyable "shell-regular" >}} + + ```shell + curl "http://ip:status_port/config" + ``` + +> **注意** +> +> 从 v4.0.0-rc.2 起可以使用 SQL 语句来修改和查看配置。 diff --git a/configure-memory-usage.md b/configure-memory-usage.md new file mode 100644 index 000000000000..b696e8fe7ed0 --- /dev/null +++ b/configure-memory-usage.md @@ -0,0 +1,68 @@ +--- +title: TiDB 内存控制文档 +category: how-to +aliases: ['/docs-cn/stable/how-to/configure/memory-control/'] +--- + +# TiDB 内存控制文档 + +目前 TiDB 已经能够做到追踪单条 SQL 查询过程中的内存使用情况,当内存使用超过一定阈值后也能采取一些操作来预防 OOM 或者排查 OOM 原因。在 TiDB 的配置文件中,我们可以使用如下配置来控制内存使用超阈值时 TiDB 的行为: + +{{< copyable "" >}} + +``` +# Valid options: ["log", "cancel"] +oom-action = "log" +``` + +- 如果上面的配置项使用的是 "log",那么当一条 SQL 的内存使用超过一定阈值(由 session 变量 `tidb_mem_quota_query` 来控制)后,TiDB 会在 log 文件中打印一条 LOG,然后这条 SQL 继续执行,之后如果发生了 OOM 可以在 LOG 中找到对应的 SQL。 +- 如果上面的配置项使用的是 "cancel",那么当一条 SQL 的内存使用超过一定阈值后,TiDB 会立即中断这条 SQL 的执行并给客户端返回一个 error,error 信息中会详细写明这条 SQL 执行过程中各个占用内存比较多的物理执行算子的内存使用情况。 + +## 如何配置一条 SQL 执行过程中的内存使用阈值 + +可以在配置文件中设置每个 Query 默认的 Memory Quota,例如将其设置为 32GB: + +{{< copyable "" >}} + +``` +mem-quota-query = 34359738368 +``` + +此外还可通过如下几个 session 变量来控制一条 Query 中的内存使用,大多数用户只需要设置 `tidb_mem_quota_query` 即可,其他变量是高级配置,大多数用户不需要关心: + +| 变量名 | 作用 | 单位 | 默认值 | +|:-----------------------------------|:---------------------------------------------------|:-------|:-----------| +| tidb_mem_quota_query | 配置整条 SQL 的内存使用阈值 | Byte | 32 << 30 | +| tidb_mem_quota_hashjoin | 配置 Hash Join 的内存使用阈值 | Byte | 32 << 30 | +| tidb_mem_quota_mergejoin | 配置 Merge Join 的内存使用阈值 | Byte | 32 << 30 | +| tidb_mem_quota_sort | 配置 Sort 的内存使用阈值 | Byte | 32 << 30 | +| tidb_mem_quota_topn | 配置 TopN 的内存使用阈值 | Byte | 32 << 30 | +| tidb_mem_quota_indexlookupreader | 配置 Index Lookup Reader 的内存使用阈值 | Byte | 32 << 30 | +| tidb_mem_quota_indexlookupjoin | 配置 Index Lookup Join 的内存使用阈值 | Byte | 32 << 30 | +| tidb_mem_quota_nestedloopapply | 配置 Nested Loop Apply 的内存使用阈值 | Byte | 32 << 30 | + +几个使用例子: + +配置整条 SQL 的内存使用阈值为 8GB: + +{{< copyable "sql" >}} + +```sql +set @@tidb_mem_quota_query = 8 << 30; +``` + +配置整条 SQL 的内存使用阈值为 8MB: + +{{< copyable "sql" >}} + +```sql +set @@tidb_mem_quota_query = 8 << 20; +``` + +配置整条 SQL 的内存使用阈值为 8KB: + +{{< copyable "sql" >}} + +```sql +set @@tidb_mem_quota_query = 8 << 10; +``` diff --git a/configure-placement-rules.md b/configure-placement-rules.md new file mode 100644 index 000000000000..e1cacf07ba1c --- /dev/null +++ b/configure-placement-rules.md @@ -0,0 +1,356 @@ +--- +title: Placement Rules 使用文档 +summary: 如何配置 Placement Rules +category: how-to +aliases: ['/docs-cn/stable/how-to/configure/placement-rules/'] +--- + +# Placement Rules 使用文档 + +> **注意:** +> +> 在配合使用 TiFlash 场景下,Placement Rules 功能进行过大量测试,可以在生产环境中使用。除配合使用 TiFlash 的场景外,单独开启 Placement Rules 没有经过大量测试,因此,不建议在生产环境单独开启该功能。 + +Placement Rules 是 PD 在 4.0 版本引入的试验特性,它是一套副本规则系统,用于指导 PD 针对不同类型的数据生成对应的调度。通过组合不同的调度规则,用户可以精细地控制任何一段连续数据的副本数量、存放位置、主机类型、是否参与 Raft 投票、是否可以担任 Raft leader 等属性。 + +## 规则系统介绍 + +整个规则系统的配置由多条规则即 Rule 组成。每条 Rule 可以指定不同的副本数量、Raft 角色、放置位置等属性,以及这条规则生效的 key range。PD 在进行调度时,会先根据 Region 的 key range 在规则系统中查到该 Region 对应的规则,然后再生成对应的调度,来使得 Region 副本的分布情况符合 Rule。 + +多条规则的 key range 可以有重叠部分的,即一个 Region 能匹配到多条规则。这种情况下 PD 根据 Rule 的属性来决定规则是相互覆盖还是同时生效。如果有多条规则同时生效,PD 会按照规则的堆叠次序依次去生成调度进行规则匹配。 + +此外,为了满足不同来源的规则相互隔离的需求,还引入了分组(Group)的概念。如果某条规则不希望与系统中的其他规则相互影响(比如被覆盖),可以使用单独的分组。 + +Placement Rules 示意图如下所示: + +![Placement rules overview](/media/placement-rules-1.png) + +### 规则字段 + +以下是每条规则中各个字段的具体含义: + +| 字段名 | 类型及约束 | 说明 | +| :--- | :--- | :--- | +| `GroupID` | `string` | 分组 ID,标识规则的来源 | +| `ID` | `string` | 分组内唯一 ID | +| `Index` | `int` | 分组内堆叠次序 | +| `Override` | `true`/`false` | 是否覆盖 index 的更小 Rule(限分组内) | +| `StartKey` | `string`,十六进制编码 | 适用 Range 起始 key | +| `EndKey` | `string`,十六进制编码 | 适用 Range 终止 key | +| `Role` | `string` | 副本角色,包括 leader/follower/learner | +| `Count` | `int`,正整数 | 副本数量 | +| `LabelConstraint` | `[]Constraint` | 用于按 label 筛选节点 | +| `LocationLabels` | `[]string` | 用于物理隔离 | + +`LabelConstraint` 与 Kubernetes 中的功能类似,支持通过 `in`、`notIn`、`exists` 和 `notExists` 四种原语来筛选 label。这四种原语的意义如下: + ++ `in`:给定 key 的 label value 包含在给定列表中。 ++ `notIn`:给定 key 的 label value 不包含在给定列表中。 ++ `exists`:包含给定的 label key。 ++ `notExists`:不包含给定的 label key。 + +`LocationLabels` 的意义和作用与 PD v4.0 之前的版本相同。比如配置 `[zone,rack,host]` 定义了三层的拓扑结构:集群分为多个 zone(可用区),每个 zone 下有多个 rack(机架),每个 rack 下有多个 host(主机)。PD 在调度时首先会尝试将 Region 的 Peer 放置在不同的 zone,假如无法满足(比如配置 3 副本但总共只有 2 个 zone)则保证放置在不同的 rack;假如 rack 的数量也不足以保证隔离,那么再尝试 host 级别的隔离,以此类推。 + +## 配置规则操作步骤 + +本节的操作步骤以使用 [pd-ctl](/pd-control.md) 工具为例,涉及到的命令也支持通过 HTTP API 进行调用。 + +### 开启 Placement Rules 特性 + +默认情况下,Placement Rules 特性是关闭的。要开启这个特性,可以集群初始化以前设置 PD 配置文件: + +{{< copyable "" >}} + +```toml +[replication] +enable-placement-rules = true +``` + +这样,PD 在初始化成功后会开启这个特性,并根据 `max-replicas` 及 `location-labels` 配置生成对应的规则: + +{{< copyable "" >}} + +```json +{ + "group_id": "pd", + "id": "default", + "start_key": "", + "end_key": "", + "role": "voter", + "count": 3, + "location_labels": ["zone", "rack", "host"] +} +``` + +如果是已经初始化过的集群,也可以通过 pd-ctl 进行在线开启: + +{{< copyable "shell-regular" >}} + +```bash +pd-ctl config placement-rules enable +``` + +PD 同样将根据系统的 `max-replicas` 及 `location-labels` 生成默认的规则。 + +> **注意:** +> +> 开启 Placement Rules 后,原先的 `max-replicas` 及 `location-labels` 配置项将不再生效。如果需要调整副本策略,应当使用 Placement Rules 相关接口。 + +### 关闭 Placement Rules 特性 + +使用 pd-ctl 可以关闭 Placement Rules 特性,切换为之前的调度策略。 + +{{< copyable "shell-regular" >}} + +```bash +pd-ctl config placement-rules disable +``` + +> **注意:** +> +> 关闭 Placement Rules 后,PD 将使用原先的 `max-replicas` 及 `location-labels` 配置。在 Placement Rules 开启期间对 Rule 的修改不会导致这两项配置的同步更新。此外,设置好的所有 Rule 都会保留在系统中,会在下次开启 Placement Rules 时被使用。 + +### 使用 pd-ctl 设置规则 + +> **注意:** +> +> 规则的变更将实时地影响 PD 调度,不恰当的规则设置可能导致副本数较少,影响系统的高可用。 + +pd-ctl 支持使用多种方式查看系统中的 Rule,输出是 json 格式的 Rule 或 Rule 列表: + ++ 查看所有规则列表 + + {{< copyable "shell-regular" >}} + + ```bash + pd-ctl config placement-rules show + ``` + ++ 查看 PD Group 的所有规则列表 + + {{< copyable "shell-regular" >}} + + ```bash + pd-ctl config placement-rules show --group=pd + ``` + ++ 查看对应 Group 和 ID 的某条规则 + + {{< copyable "shell-regular" >}} + + ```bash + pd-ctl config placement-rules show --group=pd --id=default + ``` + ++ 查看 Region 所匹配的规则列表 + + {{< copyable "shell-regular" >}} + + ```bash + pd-ctl config placement-rules show --region=2 + ``` + + 上面的例子中 `2` 为 Region ID。 + +新增和编辑规则是类似的,需要把对应的规则写进文件,然后使用 `save` 命令保存至 PD: + +{{< copyable "shell-regular" >}} + +```bash +cat > rules.json <}} + +```bash +cat > rules.json <}} + +```bash +pd-ctl config placement-rules load +``` + +以上命令将所有规则转存至 rules.json 文件。 + +{{< copyable "shell-regular" >}} + +```bash +pd-ctl config placement-rules load --group=pd --out=rule.txt +``` + +以上命令将 PD Group 的规则转存至 rule.txt 文件。 + +### 使用 tidb-ctl 查询表相关的 key range + +若需要针对元数据或某个特定的表进行特殊配置,可以通过 [tidb-ctl](https://github.com/pingcap/tidb-ctl) 的 [`keyrange` 命令](https://github.com/pingcap/tidb-ctl/blob/master/doc/tidb-ctl_keyrange.md) 来查询相关的 key。注意要添加 `--encode` 返回 PD 中的表示形式。 + +{{< copyable "shell-regular" >}} + +```bash +tidb-ctl keyrange --database test --table ttt --encode +``` + +```text +global ranges: + meta: (6d00000000000000f8, 6e00000000000000f8) + table: (7400000000000000f8, 7500000000000000f8) +table ttt ranges: (NOTE: key range might be changed after DDL) + table: (7480000000000000ff2d00000000000000f8, 7480000000000000ff2e00000000000000f8) + table indexes: (7480000000000000ff2d5f690000000000fa, 7480000000000000ff2d5f720000000000fa) + index c2: (7480000000000000ff2d5f698000000000ff0000010000000000fa, 7480000000000000ff2d5f698000000000ff0000020000000000fa) + index c3: (7480000000000000ff2d5f698000000000ff0000020000000000fa, 7480000000000000ff2d5f698000000000ff0000030000000000fa) + index c4: (7480000000000000ff2d5f698000000000ff0000030000000000fa, 7480000000000000ff2d5f698000000000ff0000040000000000fa) + table rows: (7480000000000000ff2d5f720000000000fa, 7480000000000000ff2e00000000000000f8) +``` + +> **注意:** +> +> DDL 等操作会导致 table ID 发生变化,需要同步更新对应的规则。 + +## 典型场景示例 + +本部分介绍 Placement Rules 的使用场景示例。 + +### 场景一:普通的表使用 3 副本,元数据使用 5 副本提升集群容灾能力 + +只需要增加一条规则,将 key range 限定在 meta 数据的范围,并把 `count` 值设为 `5`。添加规则示例如下: + +{{< copyable "" >}} + +```json +{ + "group_id": "pd", + "id": "meta", + "index": 1, + "override": true, + "start_key": "6d00000000000000f8", + "end_key": "6e00000000000000f8", + "role": "voter", + "count": "5", + "location_labels": ["zone", "rack", "host"] +} +``` + +### 场景二:5 副本按 2-2-1 的比例放置在 3 个数据中心,且第 3 个中心不产生 Leader + +创建三条规则,分别设置副本数为 2、2、1,并且在每个规则内通过 `label_constraints` 将副本限定在对应的数据中心内。另外,不需要 leader 的数据中心将 `role` 改为 `follower`。 + +{{< copyable "" >}} + +```json +[ + { + "group_id": "pd", + "id": "zone1", + "start_key": "", + "end_key": "", + "role": "voter", + "count": 2, + "label_constraints": [ + {"key": "zone", "op": "in", "values": ["zone1"]} + ], + "location_labels": ["rack", "host"] + }, + { + "group_id": "pd", + "id": "zone2", + "start_key": "", + "end_key": "", + "role": "voter", + "count": 2, + "label_constraints": [ + {"key": "zone", "op": "in", "values": ["zone2"]} + ], + "location_labels": ["rack", "host"] + }, + { + "group_id": "pd", + "id": "zone3", + "start_key": "", + "end_key": "", + "role": "follower", + "count": 1, + "label_constraints": [ + {"key": "zone", "op": "in", "values": ["zone3"]} + ], + "location_labels": ["rack", "host"] + } +] +``` + +### 场景三:为某张表添加 2 个 TiFlash Learner 副本 + +为表的 row key 单独添加一条规则,限定数量为 2,并且通过 `label_constraints` 保证副本产生在 `engine=tiflash` 的节点。注意这里使用了单独的 `group_id`,保证这条规则不会与系统中其他来源的规则互相覆盖或产生冲突。 + +{{< copyable "" >}} + +```json +{ + "group_id": "tiflash", + "id": "learner-replica-table-ttt", + "start_key": "7480000000000000ff2d5f720000000000fa", + "end_key": "7480000000000000ff2e00000000000000f8", + "role": "learner", + "count": 2, + "label_constraints": [ + {"key": "engine", "op": "in", "values": ["tiflash"]} + ], + "location_labels": ["host"] +} +``` + +### 场景四:为某张表在有高性能磁盘的北京节点添加 2 个 Follower 副本 + +这个例子展示了比较复杂的 `label_constraints` 配置,下面的例子限定了副本放置在 bj1 或 bj2 机房,且磁盘类型不能为 hdd。 + +{{< copyable "" >}} + +```json +{ + "group_id": "follower-read", + "id": "follower-read-table-ttt", + "start_key": "7480000000000000ff2d00000000000000f8", + "end_key": "7480000000000000ff2e00000000000000f8", + "role": "follower", + "count": 2, + "label_constraints": [ + {"key": "zone", "op": "in", "values": ["bj1", "bj2"]}, + {"key": "disk", "op": "notIn", "values": ["hdd"]} + ], + "location_labels": ["host"] +} +``` diff --git a/configure-store-limit.md b/configure-store-limit.md new file mode 100644 index 000000000000..d109f373a4e9 --- /dev/null +++ b/configure-store-limit.md @@ -0,0 +1,79 @@ +--- +title: Store Limit +summary: 介绍 Store Limit 功能。 +category: how-to +--- + +# Store Limit + +Store Limit 是 PD 在 3.0 版本引入的特性,旨在能够更加细粒度地控制调度的速度,针对不同调度场景进行调优。 + +## 实现原理 + +PD 的调度是以 operator 为单位执行的。一个 operator 可能包含多个调度操作。示例如下; + +``` +"replace-down-replica {mv peer: store [2] to [3]} (kind:region,replica, region:10(4,5), createAt:2020-05-18 06:40:25.775636418 +0000 UTC m=+2168762.679540369, startAt:2020-05-18 06:40:25.775684648 +0000 UTC m=+2168762.679588599, currentStep:0, steps:[add learner peer 20 on store 3, promote learner peer 20 on store 3 to voter, remove peer on store 2])" +``` + +以上示例中,`replace-down-replica` 这个 operator 具体包含以下操作: + +1. 在 `store 3` 上添加一个 learner peer,ID 为 `20`。 +2. 将 `store 3` 上 ID 为 `20` 的 learner peer 提升为 voter。 +3. 删除 `store 2` 上的 peer。 + +Store Limit 是通过在内存中维护了一个 store ID 到令牌桶的映射,来实现 store 级别的限速。这里不同的操作对应不同的令牌桶,目前仅支持限制添加 learner/peer 和删除 peer 两种操作的速度,即对应于每个 store 存在两种类型的令牌桶。 + +每次 operator 产生后会检查所包含的操作对应的令牌桶中是否有足够的 token。如果 token 充足才会将该 operator 加入到调度的队列中,同时从令牌桶中拿走对应的 token,否则该 operator 被丢弃。令牌桶会按照固定的速率补充 token,从而实现限速的目的。 + +Store Limit 与 PD 其他 limit 相关的参数(如 `region-schedule-limit`,`leader-schedule-limit` 等)不同的是,Store Limit 限制的主要是 operator 的消费速度,而其他的 limit 主要是限制 operator 的产生速度。引入 Store Limit 特性之前,调度的限速主要是全局的,所以即使限制了全局的速度,但还是有可能存在调度都集中在部分 store 上面,因而影响集群的性能。而 Store Limit 通过将限速的粒度进一步细化,可以更好的控制调度的行为。 + +## 使用方法 + +Store Limit 相关的参数可以通过 `pd-ctl` 进行设置。 + +### 查看当前 store 的 limit 设置 + +查看当前 store 的 limit 示例如下: + +{{< copyable "shell-regular" >}} + +```bash +store limit // 显示所有 store 添加 learner/peer 的速度上限 (如不设置具体类型,则显示的是添加 learner/peer 的速度)。 +store limit region-add // 显示所有 store 添加 learner/peer 的速度上限。 +store limit region-remove // 显示所有 store 删除 peer 的速度上限。 +``` + +### 设置全部 store 的 limit + +设置全部 store 的 limit 示例如下: + +{{< copyable "shell-regular" >}} + +```bash +store limit all 5 // 设置所有 store 添加 learner/peer 的速度上限为每分钟 5 个(如不设置具体类型,则默认设置的是添加 learner/peer 的速度)。 +store limit all 5 region-add // 设置所有 store 添加 learner/peer 的速度上限为每分钟 5 个。 +store limit all 5 region-remove // 设置所有 store 删除 peer 的速度上限为每分钟 5 个。 +``` + +### 设置单个 store 的 limit + +设置单个 store 的 limit 示例如下: + +{{< copyable "shell-regular" >}} + +```bash +store limit 1 5 // 设置 store 1 添加 learner/peer 的速度上限为每分钟 5 个(如不设置具体类型,则默认设置的是添加 learner/peer 的速度)。 +store limit 1 5 region-add // 设置 store 1 添加 learner/peer 的速度上限为每分钟 5 个。 +store limit 1 5 region-remove // 设置 store 1 删除 peer 的速度上限为每分钟 5 个。 +``` + +### 持久化 store limit 修改 + +由于 store limit 是一个内存中的映射关系,所以上述的修改在切换 leader 或者 PD 重启后会被重置。如果同时想要持久化修改,可以同时使用下面的方法进行设置: + +{{< copyable "shell-regular" >}} + +```bash +config set store-balance-rate 20 // 将所有 store 添加 learner/peer 和删除 peer 的速度上限为每分钟 20 个 +``` diff --git a/configure-time-zone.md b/configure-time-zone.md new file mode 100644 index 000000000000..3ffcd47dfcfa --- /dev/null +++ b/configure-time-zone.md @@ -0,0 +1,112 @@ +--- +title: 时区支持 +category: how-to +aliases: ['/docs-cn/stable/how-to/configure/time-zone/'] +--- + +# 时区支持 + +TiDB 使用的时区由 `time_zone` 全局变量和 session 变量决定。`time_zone` 的默认值是 `System`,`System` 对应的实际时区在 `TiDB` 集群 bootstrap 初始化时设置。具体逻辑如下: + +* 优先使用 `TZ` 环境变量 +* 如果失败,则从 `/etc/localtime` 的实际软链地址提取。 +* 如果上面两种都失败则使用 `UTC` 作为系统时区。 + +在运行过程中可以修改全局时区: + +{{< copyable "sql" >}} + +```sql +SET GLOBAL time_zone = timezone; +``` + +TiDB 还可以通过设置 session 变量 `time_zone` 为每个连接维护各自的时区。默认条件下,这个值取的是全局变量 `time_zone` 的值。修改 session 使用的时区: + +{{< copyable "sql" >}} + +```sql +SET time_zone = timezone; +``` + +查看当前使用的时区的值: + +{{< copyable "sql" >}} + +```sql +SELECT @@global.time_zone, @@session.time_zone; +``` + +设置 `time_zone` 的值的格式: + +* 'SYSTEM' 表明使用系统时间 +* 相对于 UTC 时间的偏移,比如 '+10:00' 或者 '-6:00' +* 某个时区的名字,比如 'Europe/Helsinki', 'US/Eastern' 或 'MET' + +`NOW()` 和 `CURTIME()` 的返回值都受到时区设置的影响。 + +> **注意:** +> +> 只有 Timestamp 数据类型的值是受时区影响的。可以理解为,Timestamp 数据类型的实际表示使用的是 (字面值 + 时区信息)。其它时间和日期类型,比如 Datetime/Date/Time 是不包含时区信息的,所以也不受到时区变化的影响。 + +{{< copyable "sql" >}} + +{{< copyable "sql" >}} + +```sql +create table t (ts timestamp, dt datetime); +``` + +``` +Query OK, 0 rows affected (0.02 sec) +``` + +{{< copyable "sql" >}} + +```sql +set @@time_zone = 'UTC'; +``` + +``` +Query OK, 0 rows affected (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +insert into t values ('2017-09-30 11:11:11', '2017-09-30 11:11:11'); +``` + +``` +Query OK, 1 row affected (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +set @@time_zone = '+8:00'; +``` + +``` +Query OK, 0 rows affected (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +select * from t; +``` + +``` ++---------------------|---------------------+ +| ts | dt | ++---------------------|---------------------+ +| 2017-09-30 19:11:11 | 2017-09-30 11:11:11 | ++---------------------|---------------------+ +1 row in set (0.00 sec) +``` + +上面的例子中,无论怎么调整时区的值,Datetime 类型字段的值是不受影响的,而 Timestamp 则随着时区改变,显示的值会发生变化。其实 Timestamp 持久化到存储的值始终没有变化过,只是根据时区的不同显示值不同。 + +Timestamp 类型和 Datetime 等类型的值,两者相互转换的过程中,会涉及到时区。这种情况一律基于 session 的当前 `time_zone` 时区处理。 + +另外,用户在导数据的过程中,也要需注意主库和从库之间的时区设定是否一致。 diff --git a/connectors-and-apis.md b/connectors-and-apis.md new file mode 100644 index 000000000000..5286a206ffdf --- /dev/null +++ b/connectors-and-apis.md @@ -0,0 +1,92 @@ +--- +title: 连接器和 API +category: reference +aliases: ['/docs-cn/stable/reference/supported-clients/'] +--- + +# 连接器和 API + +数据库连接器为客户端提供了连接数据库服务端的方式,APIs 提供了使用 MySQL 协议和资源的底层接口。无论是连接器还是 API,都可以用来在不同的语言和环境内连接服务器并执行 sql 语句,包括 odbc、java(jdbc)、Perl、Python、PHP、Ruby 和 C。 + +TiDB 兼容 MySQL(5.6、5.7) 的所有连接器和 API,包括: + ++ [MySQL Connector/C++](https://dev.mysql.com/doc/refman/5.7/en/connector-cpp-info.html) ++ [MySQL Connector/J](https://dev.mysql.com/doc/refman/5.7/en/connector-j-info.html) ++ [MySQL Connector/Net](https://dev.mysql.com/doc/refman/5.7/en/connector-net-info.html) ++ [MySQL Connector/ODBC](https://dev.mysql.com/doc/refman/5.7/en/connector-odbc-info.html) ++ [MySQL Connector/Python](https://dev.mysql.com/doc/refman/5.7/en/connector-python-info.html) ++ [MySQL C API](https://dev.mysql.com/doc/refman/5.7/en/c-api.html) ++ [MySQL PHP API](https://dev.mysql.com/doc/refman/5.7/en/apis-php-info.html) ++ [MySQL Perl API](https://dev.mysql.com/doc/refman/5.7/en/apis-perl.html) ++ [MySQL Python API](https://dev.mysql.com/doc/refman/5.7/en/apis-python.html) ++ [MySQL Ruby APIs](https://dev.mysql.com/doc/refman/5.7/en/apis-ruby.html) ++ [MySQL Tcl API](https://dev.mysql.com/doc/refman/5.7/en/apis-tcl.html) ++ [MySQL Eiffel Wrapper](https://dev.mysql.com/doc/refman/5.7/en/apis-eiffel.html) ++ [Mysql Go API](https://github.com/go-sql-driver/mysql) + +## 使用 MySQL 连接器连接 TiDB + +Oracle 官方提供了以下 API,TiDB 可以兼容所有这些 API。 + ++ [MySQL Connector/C++](https://dev.mysql.com/doc/refman/5.7/en/connector-cpp-info.html):C++ 语言的客户端库 ++ [MySQL Connector/J](https://dev.mysql.com/doc/refman/5.7/en/connector-j-info.html):Java 语言的客户端库,基于标准 JDBC 接口 ++ [MySQL Connector/Net](https://dev.mysql.com/doc/refman/5.7/en/connector-net-info.html):.Net 语言的客户端库,[MySQL for Visual Studio](https://dev.mysql.com/doc/visual-studio/en/)使用这个库,支持 Microsoft Visual Studio 2012,2013,2015和2017版本 ++ [MySQL Connector/ODBC](https://dev.mysql.com/doc/refman/5.7/en/connector-odbc-info.html):标准的 ODBC 接口,支持 Windows,Unix 和 OS X ++ [MySQL Connector/Python](https://dev.mysql.com/doc/refman/5.7/en/connector-python-info.html):Python 语言的客户端包,和 [Python DB API version 2.0](http://www.python.org/dev/peps/pep-0249/) 一致 + +## 使用 MySQL C API 连接 TiDB + +如果使用 C 语言程序直接连接 TiDB,可以直接链接 libmysqlclient 库,使用 MySQL 的 [C API](https://dev.mysql.com/doc/refman/5.7/en/c-api.html),这是最主要的一种 C 语言连接方式,被各种客户端和 API 广泛使用,包括 Connector/C。 + +## 使用 MySQL 第三方 API 连接 TiDB + +第三方 API 非 Oracle 官方提供,下表列出了常用的第三方 API: + +| Environment | API | Type | Notes | +| -------------- | ---------------------------------------- | -------------------------------- | ---------------------------------------- | +| Ada | GNU Ada MySQL Bindings | `libmysqlclient` | See [MySQL Bindings for GNU Ada](http://gnade.sourceforge.net/) | +| C | C API | `libmysqlclient` | See [Section 27.8, “MySQL C API”](https://dev.mysql.com/doc/refman/5.7/en/c-api.html). | +| C++ | Connector/C++ | `libmysqlclient` | See [MySQL Connector/C++ Developer Guide](https://dev.mysql.com/doc/connector-cpp/en/). | +| | MySQL++ | `libmysqlclient` | See [MySQL++ Web site](http://tangentsoft.net/mysql++/doc/). | +| | MySQL wrapped | `libmysqlclient` | See [MySQL wrapped](http://www.alhem.net/project/mysql/). | +| Go | go-sql-driver | Native Driver | See [Mysql Go API](https://github.com/go-sql-driver/mysql) | +| Cocoa | MySQL-Cocoa | `libmysqlclient` | Compatible with the Objective-C Cocoa environment. See | +| D | MySQL for D | `libmysqlclient` | See [MySQL for D](https://github.com/mysql-d/mysql-native). | +| Eiffel | Eiffel MySQL | `libmysqlclient` | See [Section 27.14, “MySQL Eiffel Wrapper”](https://dev.mysql.com/doc/refman/5.7/en/apis-eiffel.html). | +| Erlang | `erlang-mysql-driver` | `libmysqlclient` | See [`erlang-mysql-driver`.](http://code.google.com/p/erlang-mysql-driver/) | +| Haskell | Haskell MySQL Bindings | Native Driver | See [Brian O'Sullivan's pure Haskell MySQL bindings](http://www.serpentine.com/blog/software/mysql/). | +| | `hsql-mysql` | `libmysqlclient` | See [MySQL driver for Haskell](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hsql-mysql-1.7). | +| Java/JDBC | Connector/J | Native Driver | See [MySQL Connector/J 5.1 Developer Guide](https://dev.mysql.com/doc/connector-j/5.1/en/). | +| Lua | LuaSQL | `libmysqlclient` | See [LuaSQL](http://keplerproject.github.io/luasql/manual.html). | +| .NET/Mono | Connector/Net | Native Driver | See [MySQL Connector/Net Developer Guide](https://dev.mysql.com/doc/connector-net/en/). | +| Objective Caml | OBjective Caml MySQL Bindings | `libmysqlclient` | See [MySQL Bindings for Objective Caml](http://raevnos.pennmush.org/code/ocaml-mysql/). | +| Octave | Database bindings for GNU Octave | `libmysqlclient` | See [Database bindings for GNU Octave](http://octave.sourceforge.net/database/index.html). | +| ODBC | Connector/ODBC | `libmysqlclient` | See [MySQL Connector/ODBC Developer Guide](https://dev.mysql.com/doc/connector-odbc/en/). | +| Perl | `DBI`/`DBD::mysql` | `libmysqlclient` | See [Section 27.10, “MySQL Perl API”](https://dev.mysql.com/doc/refman/5.7/en/apis-perl.html). | +| | `Net::MySQL` | Native Driver | See [`Net::MySQL`](http://search.cpan.org/dist/Net-MySQL/MySQL.pm) at CPAN | +| PHP | `mysql`, `ext/mysql`interface (deprecated) | `libmysqlclient` | See [Original MySQL API](https://dev.mysql.com/doc/apis-php/en/apis-php-mysql.html). | +| | `mysqli`, `ext/mysqli`interface | `libmysqlclient` | See [MySQL Improved Extension](https://dev.mysql.com/doc/apis-php/en/apis-php-mysqli.html). | +| | `PDO_MYSQL` | `libmysqlclient` | See [MySQL Functions (PDO_MYSQL)](https://dev.mysql.com/doc/apis-php/en/apis-php-pdo-mysql.html). | +| | PDO mysqlnd | Native Driver | | +| Python | Connector/Python | Native Driver | See [MySQL Connector/Python Developer Guide](https://dev.mysql.com/doc/connector-python/en/). | +| Python | Connector/Python C Extension | `libmysqlclient` | See [MySQL Connector/Python Developer Guide](https://dev.mysql.com/doc/connector-python/en/). | +| | MySQLdb | `libmysqlclient` | See [Section 27.11, “MySQL Python API”](https://dev.mysql.com/doc/refman/5.7/en/apis-python.html). | +| Ruby | MySQL/Ruby | `libmysqlclient` | Uses `libmysqlclient`. See [Section 27.12.1, “The MySQL/Ruby API”](https://dev.mysql.com/doc/refman/5.7/en/apis-ruby-mysqlruby.html). | +| | Ruby/MySQL | Native Driver | See [Section 27.12.2, “The Ruby/MySQL API”](https://dev.mysql.com/doc/refman/5.7/en/apis-ruby-rubymysql.html). | +| Scheme | `Myscsh` | `libmysqlclient` | See [`Myscsh`](https://github.com/aehrisch/myscsh). | +| SPL | `sql_mysql` | `libmysqlclient` | See [`sql_mysql` for SPL](http://www.clifford.at/spl/spldoc/sql_mysql.html). | +| Tcl | MySQLtcl | `libmysqlclient` | See [Section 27.13, “MySQL Tcl API”](https://dev.mysql.com/doc/refman/5.7/en/apis-tcl.html). | + +## TiDB 支持的连接器版本 + +| Connector | Connector version | +| ---------------- | ---------------------------- | +| Connector/C | 6.1.0 GA | +| Connector/C++ | 1.0.5 GA | +| Connector/J | 5.1.8 | +| Connector/Net | 6.9.9 GA | +| Connector/Net | 6.8.8 GA | +| Connector/ODBC | 5.1 | +| Connector/ODBC | 3.51 (Unicode not supported) | +| Connector/Python | 2.0 | +| Connector/Python | 1.2 | diff --git a/constraints.md b/constraints.md new file mode 100644 index 000000000000..f0511d97e016 --- /dev/null +++ b/constraints.md @@ -0,0 +1,278 @@ +--- +title: 约束 +category: reference +aliases: ['/docs-cn/stable/reference/sql/constraints/'] +--- + +# 约束 + +TiDB 支持的约束与 MySQL 的基本相同。 + +## 非空约束 + +TiDB 支持的非空约束规则与 MySQL 支持的一致。例如: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE users ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + age INT NOT NULL, + last_login TIMESTAMP +); +``` + +{{< copyable "sql" >}} + +```sql +INSERT INTO users (id,age,last_login) VALUES (NULL,123,NOW()); +``` + +``` +Query OK, 1 row affected (0.02 sec) +``` + +{{< copyable "sql" >}} + +```sql +INSERT INTO users (id,age,last_login) VALUES (NULL,NULL,NOW()); +``` + +``` +ERROR 1048 (23000): Column 'age' cannot be null +``` + +{{< copyable "sql" >}} + +```sql +INSERT INTO users (id,age,last_login) VALUES (NULL,123,NULL); +``` + +``` +Query OK, 1 row affected (0.03 sec) +``` + +* 第一条 `INSERT` 语句成功,因为对于定义为 `AUTO_INCREMENT` 的列,允许 `NULL` 作为其特殊值。TiDB 将为其分配下一个自动值。 + +* 第二条 `INSERT` 语句失败,因为 `age` 列被定义为 `NOT NULL`。 + +* 第三条 `INSERT` 语句成功,因为 `last_login` 列没有被明确地指定为 `NOT NULL`。默认允许 `NULL` 值。 + +## 唯一约束 + +在 TiDB 的乐观事务中,默认会对唯一约束进行[惰性检查](/transaction-overview.md#事务的惰性检查)。通过在事务提交时再进行批量检查,TiDB 能够减少网络开销、提升性能。例如: + +{{< copyable "sql" >}} + +```sql +DROP TABLE IF EXISTS users; +CREATE TABLE users ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(60) NOT NULL, + UNIQUE KEY (username) +); +INSERT INTO users (username) VALUES ('dave'), ('sarah'), ('bill'); +``` + +{{< copyable "sql" >}} + +```sql +START TRANSACTION; +``` + +``` +Query OK, 0 rows affected (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +INSERT INTO users (username) VALUES ('jane'), ('chris'), ('bill'); +``` + +``` +Query OK, 3 rows affected (0.00 sec) +Records: 3 Duplicates: 0 Warnings: 0 +``` + +{{< copyable "sql" >}} + +```sql +INSERT INTO users (username) VALUES ('steve'),('elizabeth'); +``` + +``` +Query OK, 2 rows affected (0.00 sec) +Records: 2 Duplicates: 0 Warnings: 0 +``` + +{{< copyable "sql" >}} + +```sql +COMMIT; +``` + +``` +ERROR 1062 (23000): Duplicate entry 'bill' for key 'username' +``` + +第一条 `INSERT` 语句不会导致重复键错误,这同 MySQL 的规则一致。该检查将推迟到事务提交时才会进行。 + +你可通过设置 `tidb_constraint_check_in_place` 为 `1` 停用此行为(该变量设置对悲观事务无效,悲观事务始终在语句执行时检查约束)。如果停用此行为,则会在执行语句时就对唯一约束进行检查。例如: + +```sql +DROP TABLE IF EXISTS users; +CREATE TABLE users ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(60) NOT NULL, + UNIQUE KEY (username) +); +INSERT INTO users (username) VALUES ('dave'), ('sarah'), ('bill'); +``` + +{{< copyable "sql" >}} + +```sql +SET tidb_constraint_check_in_place = 1; +``` + +``` +Query OK, 0 rows affected (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +START TRANSACTION; +``` + +``` +Query OK, 0 rows affected (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +INSERT INTO users (username) VALUES ('jane'), ('chris'), ('bill'); +``` + +``` +ERROR 1062 (23000): Duplicate entry 'bill' for key 'username' +.. +``` + +第一条 `INSERT` 语句导致了重复键错误。这会造成额外的网络通信开销,并可能降低插入操作的吞吐量。 + +## 主键约束 + +与 MySQL 行为一样,主键约束包含了唯一约束,即创建了主键约束相当于拥有了唯一约束。此外,TiDB 其他的主键约束规则也与 MySQL 相似。例如: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); +``` + +``` +Query OK, 0 rows affected (0.12 sec) +``` + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t2 (a INT NULL PRIMARY KEY); +``` + +``` +ERROR 1171 (42000): All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead +``` + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t3 (a INT NOT NULL PRIMARY KEY, b INT NOT NULL PRIMARY KEY); +``` + +``` +ERROR 1068 (42000): Multiple primary key defined +``` + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t4 (a INT NOT NULL, b INT NOT NULL, PRIMARY KEY (a,b)); +``` + +``` +Query OK, 0 rows affected (0.10 sec) +``` + +分析: + +* 表 `t2` 创建失败,因为定义为主键的列 `a` 不能允许 `NULL` 值。 +* 表 `t3` 创建失败,因为一张表只能有一个主键。 +* 表 `t4` 创建成功,因为虽然只能有一个主键,但 TiDB 支持定义一个多列组合作为复合主键。 + +除上述规则外,默认情况下,TiDB 还有一个额外限制,即一旦一张表创建成功,其主键就不能再改变。如果需要添加/删除主键,需要在 TiDB 配置文件中将 `alter-primary-key` 设置为 `true`,并重启 TiDB 实例使之生效。 + +当开启添加/删除主键功能以后,TiDB 允许对表添加/删除主键。但需要注意的是,对于在未开启该功能时创建的整数类型的主键的表,即使开启添加/删除主键功能,也不能删除其主键约束。 + +## 外键约束 + +> **注意:** +> +> TiDB 仅部分支持外键约束功能。 + +TiDB 支持创建外键约束。例如: + +```sql +CREATE TABLE users ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + doc JSON +); +CREATE TABLE orders ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + user_id INT NOT NULL, + doc JSON, + FOREIGN KEY fk_user_id (user_id) REFERENCES users(id) +); +``` + +{{< copyable "sql" >}} + +```sql +SELECT table_name, column_name, constraint_name, referenced_table_name, referenced_column_name +FROM information_schema.key_column_usage WHERE table_name IN ('users', 'orders'); +``` + +``` ++------------+-------------+-----------------+-----------------------+------------------------+ +| table_name | column_name | constraint_name | referenced_table_name | referenced_column_name | ++------------+-------------+-----------------+-----------------------+------------------------+ +| users | id | PRIMARY | NULL | NULL | +| orders | id | PRIMARY | NULL | NULL | +| orders | user_id | fk_user_id | users | id | ++------------+-------------+-----------------+-----------------------+------------------------+ +3 rows in set (0.00 sec) +``` + +TiDB 也支持使用 `ALTER TABLE` 命令来删除外键(`DROP FOREIGN KEY`)和添加外键(`ADD FOREIGN KEY`): + +{{< copyable "sql" >}} + +```sql +ALTER TABLE orders DROP FOREIGN KEY fk_user_id; +ALTER TABLE orders ADD FOREIGN KEY fk_user_id (user_id) REFERENCES users(id); +``` + +### 注意 + +* TiDB 支持外键是为了在将其他数据库迁移到 TiDB 时,不会因为此语法报错。但是,TiDB 不会在 DML 语句中对外键进行约束检查。例如,即使 `users` 表中不存在 `id=123` 的记录,下列事务也能提交成功: + + ``` + START TRANSACTION; + INSERT INTO orders (user_id, doc) VALUES (123, NULL); + COMMIT; + ``` + +* TiDB 在执行 `SHOW CREATE TABLE` 语句的结果中不显示外键信息。 diff --git a/control-execution-plan.md b/control-execution-plan.md new file mode 100644 index 000000000000..32d1a043cedc --- /dev/null +++ b/control-execution-plan.md @@ -0,0 +1,12 @@ +--- +title: 控制执行计划 +category: performance +--- + +# 控制执行计划 + +SQL 性能调优的前两个章节介绍了如何理解 TiDB 的执行计划以及 TiDB 如何生成一个执行计划。本章节将介绍当你确定了执行计划所存在的问题时,可以使用哪些手段来控制执行计划的生成。本章节主要包括以下三方面内容: + +- [Optimizer Hints](/optimizer-hints.md)中,我们会介绍如何使用 Hint 来指导 TiDB 生成执行计划。 +- 但是使用 Hint 会侵入性地更改 SQL,在一些场景下并不能简单的插入 Hint。在[执行计划管理](/sql-plan-management.md)中,我们会介绍 TiDB 如何使用另一种语法来非侵入地控制执行计划的生成,同时还会介绍后台自动对执行计划进行演进的手段,来减轻诸如版本升级等原因造成的执行计划不稳定,而导致集群性能下降的问题。 +- 最后在[优化规则及表达式下推的黑名单](/blacklist-control-plan.md)中,我们会介绍黑名单的使用。 diff --git a/coprocessor-cache.md b/coprocessor-cache.md new file mode 100644 index 000000000000..dde4e5cd47ae --- /dev/null +++ b/coprocessor-cache.md @@ -0,0 +1,38 @@ +--- +title: 下推计算结果缓存 +category: reference +--- + +# 下推计算结果缓存 + +TiDB 从 4.0 起支持下推计算结果缓存(即 Coprocessor Cache 功能)。开启该功能后,将在 TiDB 实例侧缓存下推给 TiKV 计算的结果,在部分场景下起到加速效果。 + +## 配置 + +Coprocessor Cache 的配置均位于 TiDB 的 `tikv-client.copr-cache` 配置项中。Coprocessor 的具体开启和配置方法,见 [TiDB 配置文件描述](/tidb-configuration-file.md#tikv-clientcopr-cache-从-v400-版本开始引入)。 + +## 特性说明 + ++ 所有 SQL 在单个 TiDB 实例上的首次执行都不会被缓存。 ++ 缓存仅存储在 TiDB 内存中,TiDB 重启后缓存会失效。 ++ 不同 TiDB 实例之间不共享缓存。 ++ 缓存的是下推计算结果,即使缓存命中,后续仍有 TiDB 计算。 ++ 缓存以 Region 为单位。对 Region 的写入会导致涉及该 Region 的缓存失效。基于此原因,该功能主要会对很少变更的数据有效果。 ++ 下推计算请求相同时,缓存会被命中。通常在以下场景下,下推计算的请求是相同或部分相同的: + - SQL 语句完全一致,例如重复执行相同的 SQL 语句。 + + 该场景下所有下推计算的请求都是一致的,所有请求都能利用上下推计算缓存。 + + - SQL 语句包含一个变化的条件,其他部分一致,变化的条件是表主键或分区主键。 + + 该场景下一部分下推计算的请求会与之前出现过的一致,部分请求能利用上下推计算结果缓存。 + + - SQL 语句包含多个变化的条件,其他部分一致,变化的条件完全匹配一个复合索引列。 + + 该场景下一部分下推计算的请求会与之前出现过的一致,部分请求能利用上下推计算结果缓存。 + ++ 该功能对用户透明,开启和关闭都不影响计算结果,仅影响 SQL 执行时间。 + +## 检验缓存效果 + +目前 Coprocessor Cache 尚为实验性功能,用户无法判断一个 SQL 语句中有多少下推请求命中了缓存,也无法了解整体的缓存命中情况。后续版本中将引入相应的监控和检查方法。 diff --git a/correlated-subquery-optimization.md b/correlated-subquery-optimization.md new file mode 100644 index 000000000000..7f42fa658d12 --- /dev/null +++ b/correlated-subquery-optimization.md @@ -0,0 +1,79 @@ +--- +title: 关联子查询去关联 +summary: 了解如何给关联子查询解除关联。 +category: performance +--- + +# 关联子查询去关联 + +[子查询相关的优化](/subquery-optimization.md)中介绍了当没有关联列时,TiDB 是如何处理子查询的。由于为关联子查询解除关联依赖比较复杂,本文档中会介绍一些简单的场景以及这个优化规则的适用范围。 + +## 简介 + +以 `select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b)` 为例,这里子查询 `t1.a < (select sum(t2.a) from t2 where t2.b = t1.b)` 中涉及了关联列上的条件 `t2.b=t1.b`,不过恰好由于这是一个等值条件,因此可以将其等价的改写为 `select t1.* from t1, (select b, sum(a) sum_a from t2 group by b) t2 where t1.b = t2.b and t1.a < t2.sum_a;`。这样,一个关联子查询就被重新改写为 `JOIN` 的形式。 + +TiDB 之所以要进行这样的改写,是因为关联子查询每次子查询执行时都是要和它的外部查询结果绑定的。在上面的例子中,如果 `t1.a` 有一千万个值,那这个子查询就要被重复执行一千万次,因为 `t2.b=t1.b` 这个条件会随着 `t1.a` 值的不同而发生变化。当通过一些手段将关联依赖解除后,这个子查询就只需要被执行一次了。 + +## 限制 + +这种改写的弊端在于,在关联没有被解除时,优化器是可以使用关联列上的索引的。也就是说,虽然这个子查询可能被重复执行多次,但是每次都可以使用索引过滤数据。而解除关联的变换上,通常是会导致关联列的位置发生改变而导致虽然子查询只被执行了一次,但是单次执行的时间会比没有解除关联时的单次执行时间长。 + +因此,在外部的值比较少的情况下,不解除关联依赖反而可能对执行性能更优帮助。这时可以通过[优化规则及表达式下推的黑名单](/blacklist-control-plan.md)中关闭`子查询去关联`优化规则的方式来关闭这个优化。 + +## 样例 + +{{< copyable "sql" >}} + +```sql +create table t1(a int, b int); +create table t2(a int, b int, index idx(b)); +explain select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b); +``` + +```sql ++----------------------------------+----------+-----------+---------------+-----------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++----------------------------------+----------+-----------+---------------+-----------------------------------------------------------------------------------------+ +| HashJoin_11 | 9990.00 | root | | inner join, equal:[eq(test.t1.b, test.t2.b)], other cond:lt(cast(test.t1.a), Column#7) | +| ├─HashAgg_23(Build) | 7992.00 | root | | group by:test.t2.b, funcs:sum(Column#8)->Column#7, funcs:firstrow(test.t2.b)->test.t2.b | +| │ └─TableReader_24 | 7992.00 | root | | data:HashAgg_16 | +| │ └─HashAgg_16 | 7992.00 | cop[tikv] | | group by:test.t2.b, funcs:sum(test.t2.a)->Column#8 | +| │ └─Selection_22 | 9990.00 | cop[tikv] | | not(isnull(test.t2.b)) | +| │ └─TableFullScan_21 | 10000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | +| └─TableReader_15(Probe) | 9990.00 | root | | data:Selection_14 | +| └─Selection_14 | 9990.00 | cop[tikv] | | not(isnull(test.t1.b)) | +| └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | ++----------------------------------+----------+-----------+---------------+-----------------------------------------------------------------------------------------+ + +``` + +上面是优化生效的情况,可以看到 `HashJoin_11` 是一个普通的 `inner join`。 + +接下来,关闭关联规则: + +{{< copyable "sql" >}} + +```sql +insert into mysql.opt_rule_blacklist values("decorrelate"); +admin reload opt_rule_blacklist; +explain select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b); +``` + +```sql ++----------------------------------------+----------+-----------+------------------------+------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++----------------------------------------+----------+-----------+------------------------+------------------------------------------------------------------------------+ +| Projection_10 | 10000.00 | root | | test.t1.a, test.t1.b | +| └─Apply_12 | 10000.00 | root | | CARTESIAN inner join, other cond:lt(cast(test.t1.a), Column#7) | +| ├─TableReader_14(Build) | 10000.00 | root | | data:TableFullScan_13 | +| │ └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +| └─MaxOneRow_15(Probe) | 1.00 | root | | | +| └─HashAgg_27 | 1.00 | root | | funcs:sum(Column#10)->Column#7 | +| └─IndexLookUp_28 | 1.00 | root | | | +| ├─IndexRangeScan_25(Build) | 10.00 | cop[tikv] | table:t2, index:idx(b) | range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo | +| └─HashAgg_17(Probe) | 1.00 | cop[tikv] | | funcs:sum(test.t2.a)->Column#10 | +| └─TableRowIDScan_26 | 10.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | ++----------------------------------------+----------+-----------+------------------------+------------------------------------------------------------------------------+ +``` + +在执行了关闭关联规则的语句后,可以在 `IndexRangeScan_25(Build)` 的 `operator info` 中看到 `range: decided by [eq(test.t2.b, test.t1.b)]`。这部分信息就是关联依赖未被解除时,TiDB 使用关联条件进行索引范围查询的显示结果。 diff --git a/credits.md b/credits.md new file mode 100644 index 000000000000..4cdc6bada249 --- /dev/null +++ b/credits.md @@ -0,0 +1,179 @@ +--- +title: 荣誉列表 +summary: 了解 TiDB 社区贡献者列表及角色。 +category: contribute +--- + +TiDB 开发者社区以 SIG (Special Interest Group) 为单位管理组织开发者。每个模块都有其固定的 SIG 负责新功能开发、性能优化、稳定性保障等。如果你也想成为 TiDB 的开发者,加入感兴趣的 [SIG](https://github.com/pingcap/community/tree/master/special-interest-groups)、与一线工程师面对面讨论无疑是最好的方式。以下是截至 TiDB 4.0 GA,TiDB 社区贡献者列表及对应角色: + +## Committers + +| SIG name | GitHub ID | +|:--|:--| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[winoros](https://github.com/winoros)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[jackysp](https://github.com/jackysp)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[cofyc](https://github.com/cofyc)| +|[scheduling](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-scheduling)|[rleungx](https://github.com/rleungx)| +|[Dashboard](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-dashboard)|[breeswish](https://github.com/breeswish)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[lilin90](https://github.com/lilin90)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[qw4990](https://github.com/qw4990)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[kennytm](https://github.com/kennytm)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[lonng](https://github.com/lonng)| +|[web](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-web)|[wd0517](https://github.com/wd0517)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[zimulala](https://github.com/zimulala)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[bobotu](https://github.com/bobotu)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[cfzjywxk](https://github.com/cfzjywxk)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[lysu](https://github.com/lysu)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[tiancaiamao](https://github.com/tiancaiamao)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[youjiali1995](https://github.com/youjiali1995)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[coocood](https://github.com/coocood)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[imtbkcat](https://github.com/imtbkcat)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[MyonKeminta](https://github.com/MyonKeminta)| +|[transaction](https://github.com/tikv/community/tree/master/sig/transaction)|[nrc](https://github.com/nrc)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[AstroProfundis](https://github.com/AstroProfundis)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[aylei](https://github.com/aylei)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[DanielZhangQD](https://github.com/DanielZhangQD)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[gregwebs](https://github.com/gregwebs)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[jlerche](https://github.com/jlerche)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[LinuxGit](https://github.com/LinuxGit)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[onlymellb](https://github.com/onlymellb)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[qiffang](https://github.com/qiffang)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[sdojjy](https://github.com/sdojjy)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[shuijing198799](https://github.com/shuijing198799)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[tennix](https://github.com/tennix)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[weekface](https://github.com/weekface)| +|[scheduling](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-scheduling)|[disksing](https://github.com/disksing)| +|[scheduling](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-scheduling)|[hundundm](https://github.com/hundundm)| +|[scheduling](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-scheduling)|[lhy1024](https://github.com/lhy1024)| +|[scheduling](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-scheduling)|[nolouch](https://github.com/nolouch)| +|[scheduling](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-scheduling)|[shafreeck](https://github.com/shafreeck)| +|[Dashboard](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-dashboard)|[crazycs520](https://github.com/crazycs520)| +|[Dashboard](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-dashboard)|[Deardrops](https://github.com/Deardrops)| +|[Dashboard](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-dashboard)|[mapleFU](https://github.com/mapleFU)| +|[Dashboard](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-dashboard)|[reafans](https://github.com/reafans)| +|[Dashboard](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-dashboard)|[rleungx](https://github.com/rleungx)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[CaitinChen](https://github.com/CaitinChen)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[cofyc](https://github.com/cofyc)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[DanielZhangQD](https://github.com/DanielZhangQD)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[dcalvin](https://github.com/dcalvin)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[jackysp](https://github.com/jackysp)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[ran-huang](https://github.com/ran-huang)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[TomShawn](https://github.com/TomShawn)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[toutdesuite](https://github.com/toutdesuite)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[WangXiangUSTC](https://github.com/WangXiangUSTC)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[3pointer](https://github.com/3pointer)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[5kbpers](https://github.com/5kbpers)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[amyangfei](https://github.com/amyangfei)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[gmhdbjd](https://github.com/gmhdbjd)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[GregoryIan](https://github.com/GregoryIan)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[july2993](https://github.com/july2993)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[leoppro](https://github.com/leoppro)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[lichunzhu](https://github.com/lichunzhu)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[overvenus](https://github.com/overvenus)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[YuJuncen](https://github.com/YuJuncen)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[AstroProfundis](https://github.com/AstroProfundis)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[july2993](https://github.com/july2993)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[nrc](https://github.com/nrc)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[birdstorm](https://github.com/birdstorm)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[breeswish](https://github.com/breeswish)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[Reminiscent](https://github.com/Reminiscent)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[wshwsh12](https://github.com/wshwsh12)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[zz-jason](https://github.com/zz-jason)| +|[web](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-web)|[g1eny0ung](https://github.com/g1eny0ung)| +|[web](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-web)|[YiniXu9506](https://github.com/YiniXu9506)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[AilinKid](https://github.com/AilinKid)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[bb7133](https://github.com/bb7133)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[crazycs520](https://github.com/crazycs520)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[djshow832](https://github.com/djshow832)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[lonng](https://github.com/lonng)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[winkyao](https://github.com/winkyao)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[wjhuang2016](https://github.com/wjhuang2016)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[eurekaka](https://github.com/eurekaka)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[francis0407](https://github.com/francis0407)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[lzmhhh123](https://github.com/lzmhhh123)| +|[tools](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tools)|[csuzhangxc](https://github.com/csuzhangxc)| + +## Reviewers + +| SIG name | GitHub ID | +|:--|:--| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[anotherrachel](https://github.com/anotherrachel)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[aylei](https://github.com/aylei)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[crazycs520](https://github.com/crazycs520)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[ericsyh](https://github.com/ericsyh)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[juliezhang1112](https://github.com/juliezhang1112)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[morgo](https://github.com/morgo)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[weekface](https://github.com/weekface)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[YiniXu9506](https://github.com/YiniXu9506)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[b41sh](https://github.com/b41sh)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[js00070](https://github.com/js00070)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[mmyj](https://github.com/mmyj)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[shihongzhi](https://github.com/shihongzhi)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[tangwz](https://github.com/tangwz)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[tsthght](https://github.com/tsthght)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[Deardrops](https://github.com/Deardrops)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[lysu](https://github.com/lysu)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[imtbkcat](https://github.com/imtbkcat)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[lamxTyler](https://github.com/lamxTyler)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[SunRunAway](https://github.com/SunRunAway)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[wjhuang2016](https://github.com/wjhuang2016)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[XuHuaiyu](https://github.com/XuHuaiyu)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[zz-jason](https://github.com/zz-jason)| + +## Active Contributors + +| SIG name | GitHub ID | +|:--|:--| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[cwen0](https://github.com/cwen0)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[mikechengwei](https://github.com/mikechengwei)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[shonge](https://github.com/shonge)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[xiaojingchen](https://github.com/xiaojingchen)| +|[k8s](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-k8s)|[shinnosuke-okada](https://github.com/shinnosuke-okada)| +|[scheduling](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-scheduling)|[mantuliu](https://github.com/mantuliu)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[3pointer](https://github.com/3pointer)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[amyangfei](https://github.com/amyangfei)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[csuzhangxc](https://github.com/csuzhangxc)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[Deardrops](https://github.com/Deardrops)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[gmhdbjd](https://github.com/gmhdbjd)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[huangxiuyan](https://github.com/huangxiuyan)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[IzabelWang](https://github.com/IzabelWang)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[july2993](https://github.com/july2993)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[kissmydb](https://github.com/kissmydb)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[kolbe](https://github.com/kolbe)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[lamxTyler](https://github.com/lamxTyler)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[lance6716](https://github.com/lance6716)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[lichunzhu](https://github.com/lichunzhu)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[liubo0127](https://github.com/liubo0127)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[lysu](https://github.com/lysu)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[superlzs0476](https://github.com/superlzs0476)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[tangenta](https://github.com/tangenta)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[tennix](https://github.com/tennix)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[tiancaiamao](https://github.com/tiancaiamao)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[xiaojingchen](https://github.com/xiaojingchen)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[Yisaer](https://github.com/Yisaer)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[zhouqiang-cl](https://github.com/zhouqiang-cl)| +|[docs](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-docs)|[zimulala](https://github.com/zimulala)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[c4pt0r](https://github.com/c4pt0r)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[YangKeao](https://github.com/YangKeao)| +|[tiup](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-tiup)|[qinzuoyan](https://github.com/qinzuoyan)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[AerysNan](https://github.com/AerysNan)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[AndrewDi](https://github.com/AndrewDi)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[ekalinin](https://github.com/ekalinin)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[erjiaqing](https://github.com/erjiaqing)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[hey-kong](https://github.com/hey-kong)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[jacklightChen](https://github.com/jacklightChen)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[k-ye](https://github.com/k-ye)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[pingyu](https://github.com/pingyu)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[Rustin-Liu](https://github.com/Rustin-Liu)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[spongedu](https://github.com/spongedu)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[TennyZhuang](https://github.com/TennyZhuang)| +|[execution](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-exec)|[xiekeyi98](https://github.com/xiekeyi98)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[reafans](https://github.com/reafans)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[Rustin-Liu](https://github.com/Rustin-Liu)| +|[ddl](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-ddl)|[spongedu](https://github.com/spongedu)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[Deardrops](https://github.com/Deardrops)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[foreyes](https://github.com/foreyes)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[lonng](https://github.com/lonng)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[SeaRise](https://github.com/SeaRise)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[tiancaiamao](https://github.com/tiancaiamao)| +|[planner](https://github.com/pingcap/community/tree/master/special-interest-groups/sig-planner)|[wshwsh12](https://github.com/wshwsh12)| diff --git a/daily-check.md b/daily-check.md new file mode 100644 index 000000000000..c77846134eb9 --- /dev/null +++ b/daily-check.md @@ -0,0 +1,87 @@ +--- +title: 日常巡检 +summary: 介绍 TiDB 集群需要常关注的性能指标。 +category: reference +aliases: ['/docs-cn/stable/daily-inspection/'] +--- + +# 日常巡检 + +TiDB 作为分布式数据库,对比单机数据库机制更加复杂,其自带的监控项也很丰富。为了更便捷地运维 TiDB,本文介绍了运维 TiDB 集群需要常关注的关键性能指标。 + +## Dashboard 关键指标 + +从 4.0 版本开始,TiDB 提供了一个新的 Dashboard 运维管理工具,集成在 PD 组件上,默认地址为 `http://${pd-ip}:${pd_port}/dashboard`。 + +使用 TiDB Dashboard,简化了对 TiDB 数据库的运维,可在一个界面查看整个分布式数据库集群的运行状况。下面举例说明。 + +### 实例面板 + +![实例面板](/media/instance-status-panel.png) + +以上实例面板的各指标说明如下: + ++ **状态**:用于查看实例状态是否正常,如果在线可忽略此项。 ++ **启动时间**:是关键指标。如果有发现启动时间有变动,那么需要排查组件重启的原因。 ++ **版本**、**部署路径**、**Git 哈希值**:通过查看这三个指标可以避免有部署路径和版本不一致或者错误的情况。 + +### 主机面板 + +![主机面板](/media/host-panel.png) + +通过主机面板可以查看 CPU、内存、磁盘使用率。当任何资源的使用率超过 80% 时,推荐扩容对应组件。 + +### SQL 分析面板 + +![SQL 分析面板](/media/sql-analysis-panel.png) + +通过 SQL 分析面板可以分析对集群影响较大的慢 SQL,然后进行对应的 SQL 优化。 + +### Region 信息面板 + +![Region 信息面板](/media/region-panel.png) + +以上 Region 信息面板说明如下: + ++ `miss-peer-region-count`:缺副本的 Region 数量,不会一直大于 0。 ++ `extra-peer-region-count`:多副本的 Region 数量,调度过程中会产生。 ++ `empty-region-count`:空 Region 的数量,一般是 `TRUNCATE TABLE`/`DROP TABLE` 语句导致。如果数量较多,可以考虑开启跨表 Region merge。 ++ `pending-peer-region-count`:Raft log 落后的 Region 数量。由于调度产生少量的 pending peer 是正常的,但是如果持续很高,可能有问题。 ++ `down-peer-region-count`:Raft leader 上报有不响应 peer 的 Region 数量。 ++ `offline-peer-region-count`:peer 下线过程中的 Region 数量。 + +原则上来说,该监控面板偶尔有数据是符合预期的。但长期有数据,需要排查是否存在问题。 + +### KV Request Duration + +![TiKV 相应时间](/media/kv-duration-panel.png) + +TiKV 当前 .99(百分位)的响应时间。如果发现有明显高的节点,可以排查是否有热点,或者相关节点性能较差。 + +### PD TSO Wait Duration + +![TiDB 从 PD 获取 TSO 的时间](/media/pd-duration-panel.png) + +TiDB 从 PD 获取 TSO 的时间。如果相关响应时间较高,一般常见原因如下: + ++ TiDB 到 PD 的网络延迟较高,可以手动 Ping 一下网络延迟。 ++ TiDB 压力较高,导致获取较慢。 ++ PD 服务器压力较高,导致获取较慢。 + +### Overview 面板 + +![Overview 面板](/media/overview-panel.png) + +以上面板展示常见的负载、内存、网络、IO 监控。发现有瓶颈时,推荐扩容或者优化集群拓扑,优化 SQL、集群参数等。 + +### 异常监控面板 + +![异常监控面板](/media/failed-query-panel.png) + +以上面板展示每个 TiDB 实例上,执行 SQL 语句发生的错误,并按照错误类型进行统计,例如语法错误、主键冲突等。 + +### GC 状态面板 + +![GC 状态面板](/media/garbage-collation-panel.png) + +以上面板展示最后 GC(垃圾清理)的时间,观察 GC 是否正常。如果 GC 发生异常,可能会造成历史数据存留过多,影响访问效率。 diff --git a/dashboard/dashboard-access.md b/dashboard/dashboard-access.md new file mode 100644 index 000000000000..bcc445c684cc --- /dev/null +++ b/dashboard/dashboard-access.md @@ -0,0 +1,60 @@ +--- +title: 访问 TiDB Dashboard +category: how-to +--- + +# 访问 TiDB Dashboard + +通过浏览器访问 (将 `127.0.0.1:2379` 替换为实际 PD 实例的地址和端口)即可打开 TiDB Dashboard。 + +## 多 PD 实例访问 + +当集群中部署有多个 PD 实例、且您可以直接访问到**每个** PD 实例地址和端口时,可以简单地将 地址中的 `127.0.0.1:2379` 替换为集群中**任意一个** PD 实例的地址和端口进行访问。 + +> **注意:** +> +> 当处于防火墙或反向代理等环境下、无法直接访问每个 PD 实例时,可能会无法访问 TiDB Dashboard。这通常是防火墙或反向代理没有正确配置导致的。可参阅[通过反向代理使用 TiDB Dashboard](/dashboard/dashboard-ops-reverse-proxy.md) 或[提高 TiDB Dashboard 安全性](/dashboard/dashboard-ops-security.md)章节了解如何在多 PD 实例情况下正确配置防火墙或反向代理规则。 + +## 浏览器兼容性 + +TiDB Dashboard 可在常见的、更新及时的桌面浏览器中使用,具体版本号为: + +- Chrome >= 77 +- Firefox >= 68 +- Edge >= 17 + +> **注意:** +> +> 若使用旧版本浏览器或其他浏览器访问 TiDB Dashboard,部分界面可能不能正常工作。 + +## 登录 + +首次访问 TiDB Dashboard 将会显示用户登录界面,如下图所示,可使用 TiDB root 账号登录。 + +![登录界面](/media/dashboard/dashboard-access-login.png) + +如果存在以下情况,则可能会登录失败: + +- TiDB root 用户不存在 +- PD 未启动或无法访问 +- TiDB 未启动或无法访问 +- root 密码错误 + +登录后,24 小时内将保持自动登录状态。参见[登出](#登出)章节了解如何登出用户。 + +## 切换语言 + +TiDB Dashboard 目前支持以下语言: + +- 简体中文 +- 英文 + +在登录界面中,可点击 Switch Language 下拉框切换界面显示语言: + +![切换语言](/media/dashboard/dashboard-access-switch-language.png) + +## 登出 + +登录后,在左侧导航处点击登录用户名,可切换到用户页面。在用户页面点击 **登出**(Logout)按钮即可登出当前用户。登出后,需重新输入用户名密码。 + +![登出](/media/dashboard/dashboard-access-logout.png) diff --git a/dashboard/dashboard-cluster-info.md b/dashboard/dashboard-cluster-info.md new file mode 100644 index 000000000000..8a9d1b96f13c --- /dev/null +++ b/dashboard/dashboard-cluster-info.md @@ -0,0 +1,70 @@ +--- +title: TiDB Dashboard 集群信息页面 +summary: 查看整个集群中 TiDB、TiKV、PD、TiFlash 组件的运行状态及其所在主机的运行状态 +category: how-to +--- + +# TiDB Dashboard 集群信息页面 + +该页面上允许用户查看整个集群中 TiDB、TiKV、PD、TiFlash 组件的运行状态及其所在主机的运行状态。 + +## 访问 + +可以通过以下两种方法访问集群信息页面: + +- 登录后,左侧导航条点击**集群信息**: + + ![访问](/media/dashboard/dashboard-cluster-info-access.png) + +- 在浏览器中访问 (将 `127.0.0.1:2379` 替换为实际 PD 实例地址和端口)。 + +## 实例列表 + +点击**实例**可查看实例列表: + +![实例](/media/dashboard/dashboard-cluster-info-instances.png) + +实例列表列出了该集群中 TiDB、TiKV、PD 和 TiFlash 组件所有实例的概况信息。 + +表格包含以下列: + +- 地址:实例地址 +- 状态:实例的运行状态 +- 启动时间:实例的启动时间 +- 版本:实例版本号 +- 部署路径:实例二进制文件所在目录路径 +- Git 哈希值:实例二进制对应的 Git 哈希值 + +实例的运行状态有: + +- 在线 (Up):实例正常运行。 +- 离线 (Down) 或无法访问 (Unreachable):实例未启动或对应主机存在网络问题。 +- 已缩容下线 (Tombstone):实例上的数据已被完整迁出并缩容完毕。仅 TiKV 或 TiFlash 实例存在该状态。 +- 下线中 (Offline):实例上的数据正在被迁出并缩容。仅 TiKV 或 TiFlash 实例存在该状态。 +- 未知 (Unknown):未知的实例运行状态。 + +> **注意:** +> +> 表格中部分列仅在实例处于在线状态时能显示。 + +## 主机列表 + +点击**主机**可查看主机列表: + +![主机](/media/dashboard/dashboard-cluster-info-hosts.png) + +主机列表列出了该集群中 TiDB、TiKV、PD 和 TiFlash 组件所有实例对应主机的运行情况。 + +表格包含以下列: + +- 地址:主机 IP 地址 +- CPU:主机 CPU 逻辑核心数 +- CPU 使用率:主机当前 1 秒的用户态和内核态 CPU 使用率 +- 物理内存:主机总计的物理内存大小 +- 内存使用率:主机当前内存使用率 +- 部署磁盘:主机上运行实例所在磁盘的文件系统和磁盘挂载路径 +- 磁盘使用率:主机上运行实例所在磁盘的空间使用率 + +> **注意:** +> +> 主机列表信息由各个实例进程给出,因此当主机上所有实例都处于离线状态时,该主机信息将无法显示。 diff --git a/dashboard/dashboard-diagnostics-access.md b/dashboard/dashboard-diagnostics-access.md new file mode 100644 index 000000000000..0a3c534c437a --- /dev/null +++ b/dashboard/dashboard-diagnostics-access.md @@ -0,0 +1,61 @@ +--- +title: TiDB Dashboard 集群诊断页面 +category: how-to +--- + +# TiDB Dashboard 集群诊断页面 + +集群诊断是在指定的时间范围内,对集群可能存在的问题进行诊断,并将诊断结果和一些集群相关的负载监控信息汇总成一个诊断报告。诊断报告是网页形式,通过浏览器保存后可离线浏览和传阅。 + +> **注意:** +> +> 集群诊断功能依赖于集群中部署有 Prometheus 监控组件,参见 [TiUP](/tiup/tiup-overview.md) 或 [TiDB Ansible](/online-deployment-using-ansible.md) 部署文档了解如何部署监控组件。若集群中没有部署监控组件,生成的诊断报告中将提示生成失败。 + +## 访问 + +可以通过以下两种方法访问集群诊断页面: + +* 登录后,左侧导航条点击**集群诊断**(Cluster Diagnose): + + ![访问](/media/dashboard/dashboard-diagnostics-access.png) + +* 在浏览器中访问 [http://127.0.0.1:2379/dashboard/#/diagnose](http://127.0.0.1:2379/dashboard/#/diagnose)(将 `127.0.0.1:2379` 替换为任意实际 PD 地址和端口)。 + +## 生成诊断报告 + +如果想对一个时间范围内的集群进行诊断,查看集群的负载等情况,可以使用以下步骤来生成一段时间范围的诊断报告: + +1. 设置区间的开始时间,例如 2020-05-21 14:40:00。 +2. 设置区间长度。例如 10 min 。 +3. 点击开始。 + +![生成单个时间段的诊断报告](/media/dashboard/dashboard-diagnostics-gen-report.png) + +> **注意:** +> +> 建议生成报告的时间范围在 1 min ~ 60 min 内,目前不建议生成超过 1 小时范围的报告。 + +以上操作会生成 2020-05-21 14:40:00 至 2020-05-21 14:50:00 时间范围的诊断报告。点击**开始** (start) 后,会看到以下界面,**生成进度** (progress) 是生成报告的进度条,生成报告完成后,点击**查看报告** (View Full Report) 即可。 + +![生成报告的进度](/media/dashboard/dashboard-diagnostics-gen-process.png) + +## 生成对比诊断报告 + +如果系统在某个时间点发生异常,如 QPS 抖动或者延迟变高,可以生成一份异常时间范围和正常时间范围的对比报告,例如: + +* 系统异常时间段:2020-05-21 14:40:00 ~ 2020-05-21 14:45:00,系统异常时间。 +* 系统正常时间段:2020-05-21 14:30:00 ~ 2020-05-21 14:35:00,系统正常时间。 + +生成以上两个时间范围的对比报告的步骤如下: + +1. 设置区间的开始时间,即异常时间段的开始时间,如 2020-05-21 14:40:00。 +2. 设置区间长度。一般只系统异常的持续时间,例如 5 min。 +3. 开启与基线区间对比开关。 +4. 设置基线开始时间,即想要对比的系统正常时段的开始时间,如 2020-05-21 14:30:00。 +5. 点击开始。 + +![生成对比报告](/media/dashboard/dashboard-diagnostics-gen-compare-report.png) + +然后同样等报告生成完成后点击**查看报告** (View Full Report) 即可。 + +另外,已生成的诊断报告会显式在诊断报告主页的列表里面,可以点击查看之前生成的报告,不用重复生成。 diff --git a/dashboard/dashboard-diagnostics-report.md b/dashboard/dashboard-diagnostics-report.md new file mode 100644 index 000000000000..045d5a7d52e9 --- /dev/null +++ b/dashboard/dashboard-diagnostics-report.md @@ -0,0 +1,364 @@ +--- +title: TiDB Dashboard 诊断报告 +category: how-to +--- + +# TiDB Dashboard 诊断报告 + +本文档主要介绍诊断报告的内容以及查看技巧,访问集群诊断和生成报告请参考 [诊断报告访问文档](/dashboard/dashboard-diagnostics-access.md) + +## 查看报告 + +诊断报告由以下几部分组成: + +* 基本信息:包括生成报告的时间范围,集群的硬件信息,集群的拓扑版本信息。 +* 诊断信息:显示自动诊断的结果。 +* 负载信息:包括服务器,TIDB/PD/TiKV 相关的 CPU,内存等负载信息 +* 概览信息:包括 TiDB/PD/TiKV 的各个模块的耗时信息和错误信息。 +* TiDB/PD/TiKV 监控信息:包括各个组件的监控信息。 +* 配置信息:包括各个组件的配置信息。 + +报告中报表示例如下: + +![示例报表](/media/dashboard/dashboard-diagnostics-example-table.png) + +上图中,最上面蓝框内的 **Total Time Consume** 是报表名字。下面红框内的内容是对这个报表意义的解释,以及报表中各个字段的含义。 + +报表内容中,有几个小按钮的作用如下: + +* **i** 图标:鼠标移动到 i 图标会显示该行的说明注释。 +* **expand**:点击 **expand** 会看到这项监控更加详细的信息,如是上图中 `tidb_get_token` 的详细信息包括各个 TiDB 实例的延迟监控信息。 +* **fold**:和 **expand** 相反,用于把监控的详细信息折叠起来。 + +所有监控基本上和 TiDB Grafna 监控面板上的监控内容相对应,发现某个模块异常后,可以在 TiDB Grafna 监控面板上查看更多详细的监控信息。 + +另外,报表中统计的 `TOTAL_TIME` 和 `TOTAL_COUNT` 由于是从 Prometheus 读取的监控数据,其统计会有一些计算上的精度误差。 + +下面逐个介绍报告各个部分的报告内容。 + +### 基本信息 + +#### Report Time Range + +生成报告的时间范围,包括开始时间和结束时间。 + +![report time range 报表](/media/dashboard/dashboard-diagnostics-report-time-range.png) + +#### Cluster Hardware + +集群中各服务器的硬件信息,包括 CPU、Memory、磁盘等信息。 + +![Cluster Hardware 报表](/media/dashboard/dashboard-diagnostics-cluster-hardware.png) + +上表中各个字段含义如下: + +* HOST: 服务器的 IP 地址。 +* INSTANCE: 该服务器部署的实例数量,如 `pd * 1` 代表这台服务器部署了 1 个 PD; 如 `tidb * 2 pd * 1` 表示这台服务器部署了 2 个 TiDB 和 1 个 PD。 +* CPU_CORES:表示服务器 CPU 的核心数,物理核心/逻辑核心。 +* MEMORY: 表示服务器的内存大小,单位是 GB。 +* DISK: 表示服务器磁盘大小,单位是 GB。 +* UPTIME: 服务器的启动时间,单位是 DAY。 + +#### cluster info + +集群拓扑信息。表中信息来自 TiDB 的 [information_schema.cluster_info](/system-tables/system-table-cluster-info.md) 系统表。 + +![Cluster Hardware 报表](/media/dashboard/dashboard-diagnostics-cluster-info.png) + +上表中各个字段含义如下: + +* TYPE:节点类型。 +* INSTANCE:实例地址,为 IP:PORT 格式的字符串。 +* STATUS_ADDRESS:HTTP API 的服务地址。 +* VERSION:对应节点的语义版本号。 +* GIT_HASH:编译节点版本时的 Git Commit Hash,用于识别两个节点是否是绝对一致的版本。 +* START_TIME:对应节点的启动时间。 +* UPTIME:对应节点已经运行的时间。 + +### 诊断信息 + +TiDB 内置自动诊断的结果,具体各字段含义以及介绍可以参考 [information_schema.inspection-result](/system-tables/system-table-inspection-result.md) 系统表的内容。 + +### 负载信息 + +#### Node Load Info + +服务器节点的负载信息,包括时间范围内,服务器以下指标的平均值(AVG),最大值(MAX),最小值(MIN): + +* cpu 使用率,最大值是 100% +* memory 使用率 +* 磁盘 I/O 使用率 +* 磁盘写延迟 +* 磁盘读延迟 +* 磁盘每秒的读取字节数 +* 磁盘每秒的写入字节数 +* 节点网络每分钟收到的字节数 +* 节点网络每分钟发送的字节数 +* 节点正在使用的 TCP 连接数 +* 节点所有的 TCP 连接数 + +![Server Load Info 报表](/media/dashboard/dashboard-diagnostics-node-load-info.png) + +#### Instance cpu usage + +各个 TiDB/PD/TiKV 进程的 CPU 使用率的平均值(AVG),最大值(MAX),最小值(MIN),这里进程 CPU 使用率最大值是 100% * CPU 逻辑核心数。 + +![Instance CPU Usage 报表](/media/dashboard/dashboard-diagnostics-process-cpu-usage.png) + +#### Instance Memory Usage + +各个 TiDB/PD/TiKV 进程的占用内存字节数的平均值(AVG),最大值(MAX),最小值(MIN)。 + +![Instance memory usage 报表](/media/dashboard/dashboard-diagnostics-process-memory-usage.png) + +#### TiKV Thread CPU Usage + +TiKV 内部各个模块线程的 CPU 使用率的平均值(AVG),最大值(MAX),最小值(MIN)。这里进程 CPU 使用率最大值为 100% * 对应配置的线程数量。 + +![TiKV Thread CPU Usage 报表](/media/dashboard/dashboard-diagnostics-thread-cpu-usage.png) + +上表中, + +* `CONFIG_KEY`:表示对应模块的相关线程数配置,`` +* `CURRENT_CONFIG_VALUE`:表示配置在生成报表时刻的当前值。 + +> **注意:** +> +> `CURRENT_CONFIG_VALUE` 是生成报告时的值,并不是报告时间范围内的值,目前不能获取历史时间某些配置的值。 + +#### TiDB/PD goroutines count + +TiDB/PD 的 goroutines 数量的平均值 (AVG),最大值 (MAX),最小值 (MIN)。如果 goroutines 数量超过 2000,说明该进程并发太高,会对整体请求的延迟有影响。 + +![TiDB/PD goroutines count 报表](/media/dashboard/dashboard-diagnostics-goroutines-count.png) + +### 概览信息 + +#### Time Consumed by Each Component + +包括集群中 TiDB、PD、TiKV 的各个模块的监控控耗时以及各项耗时的占比。默认时间单位是秒。可以用该表快速定位哪些模块的耗时较多。 + +![Total Time Consume 报表](/media/dashboard/dashboard-diagnostics-total-time-consume.png) + +上表各列的字段含义如下: + +* METRIC_NAME:监控项的名称 +* Label: 监控的 label 信息,点击 expand 后可以查看该项监控更加详细的各项 label 的监控信息。 +* TIME_RATIO:该项监控消耗的总时间和 TIME_RATIO 为 1 的监控行总时间比例。如 kv_request 的总耗时占 tidb_query 总耗时的 1.65 = 38325.58/23223.86。因为 KV 请求会并行执行,所以所有 KV 请求的总时间是有可能超过总查询 (tidb_query) 的执行时间。 +* TOTAL_TIME: 该项监控的总耗时。 +* TOTAL_COUNT: 该项监控执行的总次数。 +* P999: 该项监控的 P999 最大时间。 +* P99: 该项监控的 P99 最大时间。 +* P90: 该项监控的 P90 最大时间。 +* P80: 该项监控的 P80 最大时间。 + +以上监控中相关模块的耗时关系如下所示: + +![各个模块耗时关系图](/media/dashboard/dashboard-diagnostics-time-relation.png) + +上图中,黄色部分是 TiDB 相关的监控,蓝色部分是 TiKV 相关的监控,灰色部分暂时没有具体对应的监控项。 + +上图中,tidb_query 的耗时包括 4 部分的耗时 + +* get_token +* parse +* compile +* execute + +其中 execute 的耗时包括以下部分: + +* wait_start_tso +* TiDB 层的执行时间,目前暂无监控 +* KV 请求的时间 +* KV_backoff 的时间,这是 KV 请求失败后进行 backoff 的时间 + +其中,KV 请求时间包含以下部分: + +* 请求的网络发送以及接收耗时,目前该项暂无监控,可以大致用 KV 请求时间 减去 tikv_grpc_message 的时间 +* tikv_grpc_message 耗时 + +其中,tikv_grpc_message 耗时包含以下部分: + +* Coprocessor request 耗时,指用于处理 COP 类型的请求,该耗时包括以下部分: + * tikv_cop_wait,请求排队等待的耗时 + * Coprocessor handle,处理 Cop 请求的耗时 +* tikv_scheduler_command 耗时,该耗时包含以下部分: + * tikv_scheduler_processing_read,处理读请求的耗时 + * tikv_storage_async_request 中获取 snapshot 的耗时(snapshot 是该项监控的 label) + * 处理写请求的耗时,该耗时包括以下部分: + * tikv_scheduler_latch_wait,等待 latch 的耗时 + * tikv_storage_async_request 中 write 的耗时(write 是改监控的 label) + +其中,tikv_storage_async_request 中的 write 耗时是指 raft kv 写入的耗时,包括以下部分: + +* tikv_raft_propose_wait +* tikv_raft_process,该耗时主要时间包括: + * tikv_raft_append_log +* tikv_raft_commit_log +* tikv_raft_apply_wait +* tikv_raft_apply_log + +用户可以根据上述耗时之间的关系,利用 TOTAL_TIME 以及 P999,P99 的时间大致定位哪些模块耗时比较久,然后再看相关的监控。 + +> 注意:由于 raft kv 可能会对多个请求作为一个 batch 来写入,所以用 TOTAL_TIME 来衡量各个模块的耗时时,对 raft kv 的写入相关监控项不适用,具体是:tikv_raft_process,tikv_raft_append_log,tikv_raft_commit_log,tikv_raft_apply_wait,tikv_raft_apply_log,这里用 P999,P99 的时间来对比各个模块的耗时更加合理。 +> +> 原因是,假如有 10 个 async write 请求,raft kv 内部将 10 个请求打包成一个 batch 执行,执行时间为 1 秒,所以每个请求的执行时间为 1 秒,10 个请求的总时间是 10 秒,但是 raft kv 处理的总时间是1秒。如果用 TOTAL_TIME 来衡量,用户可能会弄不懂剩余的 9 秒耗时在哪儿。这里从总请求数(TOTAL_COUNT )也能看出 raft kv 的监控和之前其他监控的差异。 + +#### Errors Occurred in Each Component + +包括 TiDB , TiKV 出现错误的总数,如写 binlog 失败,tikv server is busy, TiKV channel full, tikv write stall 等错误,具体各项错误含义可以看行注释。 + +![Errors Occurred in Each Component 报表](/media/dashboard/dashboard-diagnostics-error.png) + +#### TiDB/PD/TiKV 的具体监控信息 + +这部分包括了 TiDB/PD/TiKV 更多的具体的监控信息。 + +#### TiDB 相关监控信息 + +##### Time Consumed by TiDB Component + +TiDB 的各项监控耗时以及各项耗时的占比。和 overview 中的 time consume 表类似,但是这个表的 label 信息会更丰富,能看到更多细节。 + +##### TiDB Server Connections + +TiDB 各个实例的客户端连接数。 + +##### TiDB Transaction + +TiDB 事务相关的监控。 + +![Transaction 报表](/media/dashboard/dashboard-diagnostics-tidb-txn.png) + +* TOTAL_VALUE: 该项监控在报告时间段内所有值的和(SUM)。 +* TOTAL_COUNT:该项监控出现的总次数。 +* P999: 该项监控的 P999 最大值。 +* P99: 该项监控的 P99 最大值。 +* P90: 该项监控的 P90 最大值。 +* P80: 该项监控的 P80 最大值。 + +示例: + +上表中,在报告时间范围内,tidb_txn_kv_write_size:一共约有 181296 次事务的 kv 写入,总 kv 写入大小是 266.772 MB, 其中单次事务的 KV 写入的 P999, P99, P90, P80 的最大值分别为 116.913 KB , 1.996 KB, 1.905 KB, 1.805 KB。 + +##### DDL Owner + +![TiDB DDL Owner 报表](/media/dashboard/dashboard-diagnostics-tidb-ddl.png) + +上表表示从 2020-05-21 14:40:00 开始,集群的 ddl-owner 在 10.0.1.13:10080 节点,如果 owner 发生变更,上表会有多行数据,其中 MinTime 列表示已知对应 Owner 的最小时间。 + +> 如果 owner 信息为空,不代表这个时间段内一定没有 owner, 因为这里是依靠 ddl_worker 的监控信息来判断 DDL owner 的,也可能是这个时间段内 ddl_worker 没有做任何 DDL job 导致这里信息为空。 + +TiDB 中其他监控表如下,这里不再一一列举: + +* Statistics Info:TiDB 统计信息的相关监控。 +* Top 10 Slow Query:报表时间范围内 Top 10 的慢查询信息。 +* Top 10 Slow Query Group By Digest:报表时间范围内 Top 10 的慢查询信息,并按照 SQL 指纹聚合。 +* Slow Query With Diff Plan:报表时间范围内执行计划发生变更的 SQL 语句。 + +#### PD 相关监控信息 + +PD 模块相关监控的报表如下: + +* Time Consumed by PD Component,PD 中相关模块的耗时监控 +* Blance Leader/Region,报表时间范围内集群发生的 balance-region, balance leader 监控,比如从 tikv_note_1 上调度走了多少个 leader,调度进了多少个 leader。 +* Cluster Status,集群的状态信息,包括总 TiKV 数量,总集群存储容量,region 数量,离线 TiKV 的数量等信息。 +* Store Status,记录各个 TiKV 节点的状态信息,包括 region score, leader score,region/leader 的数量。 +* Etcd Status,PD 内部的 ETCD 相关信息。 + +#### TiKV 相关监控信息 + +TIKV 模块的相关监控报表如下: + +* Time Consumed by TiKV Component,TiKV 中相关模块的耗时监控 +* Time Consumed by RocksDB,TiKV 中 RocksDB 的耗时监控 +* TiKV Error,TiKV 中各个模块相关的 error 信息 +* TiKV Engine Size,TiKV 中各个节点 column family 的存储数据大小 +* Coprocessor Info,TiKV 中 coprocessor 模块相关的监控。 +* Raft Info,TiKV 中 raft 模块的相关监控信息 +* Snapshot Info,TiKV 中 snapshot 相关监控信息 +* GC Info,TiKV 中 GC 相关的监控信息 +* Cache Hit,TiKV 中 Rocksdb 的各个缓存的命中率监控信息 + +### 配置信息 + +配置信息中,部分模块的配置信息可以显示报告时间范围内的配置值,有部分配置则因为无法获取到历史的配置值,所以是生成报告时刻的当前配置值。 + +在报告时间范围内,以下表包括部分配置的在报告时间范围的开始时间的值: + +* Scheduler Initial Config:PD 调度相关配置在报告开始时间的初始值 +* TiDB GC Initial Config:TiDB GC 相关配置在报告开始时间的初始值 +* TiKV RocksDB Initial Config:TiKV RocksDB 相关配置在报告开始时间的初始值 +* TiKV RaftStore Initial Config:TiKV RaftStore 相关配置在报告开始时间的初始值 + +在报表时间范围内,如若有些配置被修改过,以下表包括部分配置被修改的记录: + +* Scheduler Config Change History +* TiDB GC Config Change History +* TiKV RocksDB Config Change History +* TiKV RaftStore Config Change History + +示例: + +![Scheduler Config Change History 报表](/media/dashboard/dashboard-diagnostics-config-change.png) + +上面报表显示,leader-schedule-limit 配置参数在报告时间范围内有被修改过: + +* 2020-05-22T20:00:00+08:00,即报告的开始时间 leader-schedule-limit 的配置值为 4,这里并不是指该配置被修改了,只是说明在报告时间范围的开始时间其配置值是 4。 +* 2020-05-22T20:07:00+08:00,leader-schedule-limit 的配置值为 8,说明在 2020-05-22T20:07:00+08:00 左右,该配置的值被修改了。 + +下面的报表是生成报告时,TiDB、PD、TiKV 的在生成报告时刻的当前配置: + +* TiDB's Current Config +* PD's Current Config +* TiKV's Current Config + +## 对比报告 + +生成 2 个时间段的对比报告,其内容和单个时间段的报告是一样的,只是加入了对比列显示两个时间段的差别。下面主要介绍对比报告中的一些特有表以及如何查看对比报表。 + +首先在 基本信息中的 `Compare Report Time Range` 报表会显示出对比的两个时间段: + +![Compare Report Time Range 报表](/media/dashboard/dashboard-diagnostics-compare-time.png) + +其中 t1 是正常时间段,或者叫参考时间段,t2 是异常时间段。 + +下面是一些慢查询相关的报表: + +* Slow Queries In Time Range t2:仅出现在 t2 时间段但没有出现在 t1 时间段的慢查询 +* Top 10 slow query in time range t1:t1 时间段的 Top10 慢查询 +* Top 10 slow query in time range t2:t2 时间段的 Top10 慢查询 + +### DIFF_RATIO 介绍 + +这里以 `Instance CPU usage` 为例子介绍 `DIFF_RATIO`。 + +![Compare Instance CPU Usage 报表](/media/dashboard/dashboard-diagnostics-compare-instance-cpu-usage.png) + +* t1.AVG, t1.MAX, t1.Min 分别是 t1 时间段内 CPU 使用率的 平均值,最大值,最小值。 +* t2.AVG, t2.MAX, t2.Min 分别是 t2 时间段内 CPU 使用率的 平均值,最大值,最小值。 +* AVG_DIFF_RATIO 表示 t1 和 t2 时间段平均值的 DIFF_RATIO +* MAX_DIFF_RATIO 表示 t1 和 t2 时间段最大值的 DIFF_RATIO +* MIN_DIFF_RATIO 表示 t1 和 t2 时间段最小值的 DIFF_RATIO + +DIFF_RATIO:表示2个时间段的差异大小,有以下几个取值方式: + +* 如果该监控仅在 t2 时间内才有值,t1 时间段没有,则 DIFF_RATIO 取值为 1 +* 如果监控项仅在 t1 时间内才有值,t1 时间段没有,则 DIFF_RATIO 取值为 -1 +* 如果 t2 时间段的值比 t1 时间段的值大,则 DIFF_RATIO = (t2.value / t1.value) - 1 +* 如果 t2 时间段的值比 t1 时间段的值小,则 DIFF_RATIO = 1 - (t1.value / t2.value) + +例如上表中,`tidb` 节点的平均 CPU 使用率在 t2 时间段比 t1 时间段高 2.02 倍。`2.02 = 1240/410 - 1`。 + +### Maximum Different Item 报表介绍 + +`Maximum Different Item` 的报表是对比 2 个时间段的监控项后,按照监控项的差异大小排序,通过这个表可以很快发现 2 个时间段哪些监控的差异最大。示例如下: + +![Maximum Different Item 报表](/media/dashboard/dashboard-diagnostics-maximum-different-item.png) + +* Table: 表示这个监控项来自于对比报告中的哪个报表,如 `TiKV, coprocessor_info` 表示是 TiKV 组件下的 `coprocessor_info` 报表。 +* METRIC_NAME: 监控项名,点击 `expand` 可以查看该监控的不同 label 的差异对比。 +* LABEL:监控项对应的 label。比如 `TiKV Coprocessor scan` 监控项有 2 个 label,分别是 instance, req, tag, sql_type,分别表示为 TiKV 地址,请求类型,操作类型 和 操作的 column famaly。 +* MAX_DIFF:差异大小,取值为 t1.VALUE 和 t2.VALUE 的 DIFF_RATIO 计算。 + +可以从上表中发现,t2 时间段比 t1 时间段多出了很多倍的 coprocessor 请求,TiDB 的解析SQL (parse) 时间也变多了很多倍等等。 diff --git a/dashboard/dashboard-diagnostics-usage.md b/dashboard/dashboard-diagnostics-usage.md new file mode 100644 index 000000000000..7ea7b40fb4e6 --- /dev/null +++ b/dashboard/dashboard-diagnostics-usage.md @@ -0,0 +1,114 @@ +--- +title: 使用 TiDB Dashboard 诊断报告定位问题 +category: how-to +--- + +# 使用 TiDB Dashboard 诊断报告定位问题 + +本文介绍如何使用 TiDB Dashboard 诊断报告定位问题。 + +## 对比诊断功能示例 + +对比报告中有一个对比诊断的功能,通过对比两个时间段的监控项差异来尝试帮助 DBA 定位问题。先看几个示例。 + +### 大查询/写入导致 QPS 抖动或延迟上升诊断 + +#### 示例 1 + +![QPS 图](/media/dashboard/dashboard-diagnostics-usage1.png) + +上图中,是在跑 go-ycsb 的压测,可以发现,在 2020-03-10 13:24:30 时,QPS 突然开始下降,3 分钟后,QPS 开始恢复正常,这是为什么呢? + +生成以下 2 个时间范围的对比报告: + +T1: 2020-03-10 13:21:00 ,2020-03-10 13:23:00 ,正常时间段,又叫参考时间段 +T2: 2020-03-10 13:24:30 , 2020-03-10 13:27:30 ,QPS 开始下降的异常时间段 + +这里2个时间间隔都是 3 分钟,因为抖动的影响范围就是 3 分钟。因为诊断时会用一些监控的平均值做对比,所有间隔时间太长会导致平均值差异不明显,然后无法准确定位问题。 + +生成报告后查看 **Compare Diagnose** 报表内容如下: + +![对比诊断结果](/media/dashboard/dashboard-diagnostics-usage2.png) + +上面诊断结果显示,在诊断的时间内可能有大查询,下面的每一行的含义是: + +* tidb_qps 下降 0.93 倍 +* tidb_query_duration, P999的查询延迟上升 1.54 倍 +* tidb_cop_duration,P999 的 cop 请求的处理延迟上升 2.48 倍 +* tidb_kv_write_num,P999 的 tidb 的事务写入 kv 数量上升 7.61 倍 +* tikv_cop_scan_keys_total_nun, TiKV 的 coprocessor 扫描 key/value 的数量分别在 3 台 TiKV 上有很大的提升。 +* pd_operator_step_finish_total_count 中, transfer leader 的数量上升 2.45 倍,说明异常时间段的调度比正常时间段要高。 +* 提示可能有慢查询,并提示用 SQL 查询 TiDB 的慢日志。在 TiDB 中执行结果如下: + +```sql +SELECT * FROM (SELECT count(*), min(time), sum(query_time) AS sum_query_time, sum(Process_time) AS sum_process_time, sum(Wait_time) AS sum_wait_time, sum(Commit_time), sum(Request_count), sum(process_keys), sum(Write_keys), max(Cop_proc_max), min(query),min(prev_stmt), digest FROM information_schema.CLUSTER_SLOW_QUERY WHERE time >= '2020-03-10 13:24:30' AND time < '2020-03-10 13:27:30' AND Is_internal = false GROUP BY digest) AS t1 WHERE t1.digest NOT IN (SELECT digest FROM information_schema.CLUSTER_SLOW_QUERY WHERE time >= '2020-03-10 13:21:00' AND time < '2020-03-10 13:24:00' GROUP BY digest) ORDER BY t1.sum_query_time DESC limit 10\G +***************************[ 1. row ]*************************** +count(*) | 196 +min(time) | 2020-03-10 13:24:30.204326 +sum_query_time | 46.878509117 +sum_process_time | 265.924 +sum_wait_time | 8.308 +sum(Commit_time) | 0.926820886 +sum(Request_count) | 6035 +sum(process_keys) | 201453000 +sum(Write_keys) | 274500 +max(Cop_proc_max) | 0.263 +min(query) | delete from test.tcs2 limit 5000; +min(prev_stmt) | +digest | 24bd6d8a9b238086c9b8c3d240ad4ef32f79ce94cf5a468c0b8fe1eb5f8d03df +``` + +可以发现,从 13:24:30 开始有一个批量删除的大写入,一共执行了 196 次,每次删除 5000 行数据,总共耗时 46.8 秒。 + +#### 示例2 + +如果大查询一直没执行完,就不会记录慢日志,这个时候也能诊断吗?下面再看一个例子。 + +![QPS 图](/media/dashboard/dashboard-diagnostics-usage3.png) + +上图中,也是在跑 go-ycsb 的压测,可以发现,在 2020-03-08 01:46:30 时,QPS 突然开始下降,并且一直没有恢复。 + +生成以下 2 个时间范围的对比报告: + +T1: 2020-03-08 01:36:00 ,2020-03-08 01:41:00 ,正常时间段,又叫参考时间段 +T2: 2020-03-08 01:46:30 ,2020-03-08 01:51:30 ,QPS 开始下降的异常时间段 + +生成报告后看 `Compare Diagnose` 报表的内容如下: + +![对比诊断结果](/media/dashboard/dashboard-diagnostics-usage4.png) + +上面诊断结果和例 1 类似,这里不再重复赘述,直接看最后一行,提示可能有慢查询,并提示用 SQL 查询 TiDB 日志中的 expensive query。在 TiDB 中执行结果如下: + +```sql +> SELECT * FROM information_schema.cluster_log WHERE type='tidb' AND time >= '2020-03-08 01:46:30' AND time < '2020-03-08 01:51:30' AND level = 'warn' AND message LIKE '%expensive_query%'\G +TIME | 2020/03/08 01:47:35.846 +TYPE | tidb +INSTANCE | 172.16.5.40:4009 +LEVEL | WARN +MESSAGE | [expensivequery.go:167] [expensive_query] [cost_time=60.085949605s] [process_time=2.52s] [wait_time=2.52s] [request_count=9] [total_keys=996009] [process_keys=996000] [num_cop_tasks=9] [process_avg_time=0.28s] [process_p90_time=0.344s] [process_max_time=0.344s] [process_max_addr=172.16.5.40:20150] [wait_avg_time=0.000777777s] [wait_p90_time=0.003s] [wait_max_time=0.003s] [wait_max_addr=172.16.5.40:20150] [stats=t_wide:pseudo] [conn_id=19717] [user=root] [database=test] [table_ids="[80,80]"] [txn_start_ts=415132076148785201] [mem_max="23583169 Bytes (22.490662574768066 MB)"] [sql="select count(*) from t_wide as t1 join t_wide as t2 where t1.c0>t2.c1 and t1.c2>0"] +``` + +上面查询结果显示,在 172.16.5.40:4009 这台 TiDB 上,2020/03/08 01:47:35.846 有一个已经执行了 60s,但还没有执行完的 的 expensive_query,这个query 是个笛卡尔积的 join , 应该是有用户手抖了。 + +## 用对比报告定位问题 + +诊断有可能是误诊,使用对比报告或许可以帮助 DBA 更快速的定位问题。参考以下示例。 + +![QPS 图](/media/dashboard/dashboard-diagnostics-usage5.png) + +上图中,也是在跑 go-ycsb 的压测,可以发现,在 2020-05-22 22:14:00 时,QPS 突然开始下降,大概在持续 3 分钟后恢复。 + +生成以下2个时间范围的对比报告: + +T1: 2020-05-22 22:11:00 ,2020-05-22 22:14:00 ,正常时间段 +T2: 2020-05-22 22:14:00 ,2020-05-22 22:17:00 ,QPS 开始下降的异常时间段 + +生成对比报告后,查看 **Max diff item** 报表,它是对比2个时间段的监控项后,按照监控项的差异大小排序,这个表的结果如下: + +![对比结果](/media/dashboard/dashboard-diagnostics-usage6.png) + +从上面结果可以看出,T2 时间段新增了很多倍的 Coprocessor 请求,可以猜测可能是 T2 时间段出现了一些大查询,或者是查询较多的负载。 + +实际上,在 t1 ~ t2 整个时间段内都在跑 `go-ycsb` 的压测,然后在 t2 时间段跑了 20 个 `tpch` 的查询,所以是因为 `tpch` 大查询导致了出现很多的 cop 请求。 + +这种大查询执行时间超过慢日志的阈值后也会记录在慢日志里面,可以继续查看 `Slow Queries In Time Range t2` 报表查看是否有一些慢查询。不过有一点主要注意的是,有些仅出现在 T2 时间段的慢查询,也可能是这种查询在 T1 时间段也存在,但是由于 T2 时间段的其他负载影响导致其执行变慢。 diff --git a/dashboard/dashboard-faq.md b/dashboard/dashboard-faq.md new file mode 100644 index 000000000000..769bf69a5f94 --- /dev/null +++ b/dashboard/dashboard-faq.md @@ -0,0 +1,55 @@ +--- +title: TiDB Dashboard 常见问题 +category: how-to +--- + +# TiDB Dashboard 常见问题 + +本文汇总了使用 TiDB Dashboard 过程中的常见问题与解决办法。 + +## 访问 + +### 已配置防火墙或反向代理,但访问后被跳转到一个内部地址无法访问 TiDB Dashboard + +集群部署有多个 PD 实例的情况下,只有其中某一个 PD 实例会真正运行 TiDB Dashbaord 服务,访问其他 PD 实例时会发生浏览器端重定向。若防火墙或反向代理没有为此进行正确配置,就可能出现访问后被重定向到一个被防火墙或反向代理保护的内部地址的情况。 + +- 参阅 [TiDB Dashboard 多 PD 实例部署](/dashboard/dashboard-ops-deploy.md#多-PD-实例部署)章节了解多 PD 实例下 TiDB Dashboard 的工作原理。 +- 参阅[通过反向代理使用 TiDB Dashboard](/dashboard/dashboard-ops-reverse-proxy.md) 章节了解如何正确配置反向代理。 +- 参阅[提高 TiDB Dashboard 安全性](/dashboard/dashboard-ops-security.md)章节了解如何正确配置防火墙。 + +### 双网卡部署时无法通过另一个网卡访问 TiDB Dashboard + +PD 中的 TiDB Dashboard 出于安全考虑仅监听部署时所指定的 IP 地址(即只监听在一个网卡上),而非 `0.0.0.0`,因此当主机上安装了多个网卡时,通过另一个网卡将无法访问。 + +当你使用 `tiup cluster` 或 `tiup playground` 命令部署时,目前尚没有方法改变该行为。推荐使用反向代理将 TiDB Dashboard 安全地暴露给另一个网卡,具体参见[通过反向代理使用 TiDB Dashboard](/dashboard/dashboard-ops-reverse-proxy.md) 章节。 + +## 界面功能 + +### 概况页面中 QPS 及 Latency 显示 `prometheus_not_found` 错误 + +QPS 及 Latency 监控依赖于集群中已正常部署 Prometheus 监控实例,没有部署的情况下就会显示为错误。向集群中新部署 Prometheus 实例即可解决该问题。 + +若已经部署 Prometheus 监控实例但仍然显示为错误,可能的原因是您使用的部署工具(TiUP、tidb-operator 或 TiDB Ansible)版本比较旧,没有自动汇报监控地址,导致 TiDB Dashboard 无法感知并查询监控数据。可以升级到最新的部署工具并重试。 + +以下给出 TiUP 部署工具的操作方法,对于其他部署工具,请参阅工具对应文档。 + +1. 升级 TiUP、TiUP Cluster: + + ```bash + tiup update --self + tiup update cluster --force + ``` + +2. 升级后,部署包含监控节点的新集群时,应当能正常显示监控。 + +3. 对于现有集群,可通过再次启动集群的方法汇报监控地址(将 `CLUSTER_NAME` 替换为实际集群名称): + + ```bash + tiup cluster start CLUSTER_NAME + ``` + + 即使集群已经启动,请仍然执行该命令。该命令不会影响集群上正常的业务,但会刷新并上报监控地址,从而能让监控在 TiDB Dashbaord 中正常显示。 + +### 概况页面中 Top SQL 语句、最近慢查询显示 `invalid connection` 错误 + +可能的原因是你开启了 TiDB 的 `prepared-plan-cache` 功能。作为实验性功能,`prepared-plan-cache` 在某些版本的 TiDB 中存在一些缺陷,开启后可能会导致 TiDB Dashboard(及其他应用)出现该问题。请依据[文档](/tidb-configuration-file.md#prepared-plan-cache)关闭 `prepared-plan-cache` 功能。 diff --git a/dashboard/dashboard-intro.md b/dashboard/dashboard-intro.md new file mode 100644 index 000000000000..1f0a6386a971 --- /dev/null +++ b/dashboard/dashboard-intro.md @@ -0,0 +1,66 @@ +--- +title: TiDB Dashboard 介绍 +category: how-to +--- + +# TiDB Dashboard 介绍 + +> **注意:** +> +> 该功能目前为实验特性,不建议在生产环境中使用。 + +TiDB Dashboard 是 TiDB 自 4.0 版本起提供的图形化界面,可用于监控及诊断 TiDB 集群。TiDB Dashboard 内置于 TiDB 的 PD 组件中,无需独立部署。 + +![界面](/media/dashboard/dashboard-intro.gif) + +TiDB Dashboard 在 GitHub 上[开源](https://github.com/pingcap-incubator/tidb-dashboard)。 + +以下列出了 TiDB Dashboard 的主要功能,可分别点击小节内的链接进一步了解详情。 + +## 了解集群整体运行概况 + +查看集群整体 QPS 数值、执行耗时、消耗资源最多的几类 SQL 语句等概况信息。 + +参阅[概况页面](/dashboard/dashboard-overview.md)了解详情。 + +## 查看组件及主机运行状态 + +查看整个集群中 TiDB、TiKV、PD、TiFlash 组件的运行状态及其所在主机的运行状态。 + +参阅[集群信息页面](/dashboard/dashboard-cluster-info.md)了解详情。 + +## 分析集群读写流量分布及趋势变化 + +通过热力图形式可视化地展示整个集群中读写流量随时间的变化情况,及时发现业务模式的变化,或定位性能不均衡的热点所在。 + +参阅[流量可视化页面](/dashboard/dashboard-key-visualizer.md)了解详情。 + +## 列出所有 SQL 查询的耗时等执行信息 + +列出所有 SQL 语句在集群上执行情况,了解各个阶段的执行时间、总运行次数等信息,帮助用户分析和定位集群中最消耗资源的查询,优化整体性能。 + +参阅 [SQL 语句分析页面](/dashboard/dashboard-statement-list.md)了解详情。 + +## 详细了解耗时较长的 SQL 语句的执行信息 + +列出所有耗时较长的 SQL 语句文本及其执行信息,帮助用户定位 SQL 语句性能缓慢或发生性能抖动的原因。 + +参阅[慢查询页面](/dashboard/dashboard-slow-query.md)了解详情。 + +## 诊断常见集群问题并生成报告 + +自动判断集群中是否存在一些常见的风险(如配置不一致)或问题,生成报告并给出操作建议,或对比集群在不同时间段的各个指标状态,供用户分析可能存在问题的方向。 + +参阅[集群诊断页面](/dashboard/dashboard-diagnostics-access.md)了解详情。 + +## 查询所有组件日志 + +按关键字、时间范围等条件快速搜索集群中所有运行实例的日志,并可打包下载到本地。 + +参阅[日志搜索页面](/dashboard/dashboard-log-search.md)了解详情。 + +## 收集分析各个组件的性能数据 + +高级调试功能:无需第三方工具,在线地对各个组件进行性能分析,剖析组件实例在分析时间段内执行的各种内部操作及比例。 + +参阅[实例性能分析页面](/dashboard/dashboard-profiling.md)了解详情。 diff --git a/dashboard/dashboard-key-visualizer.md b/dashboard/dashboard-key-visualizer.md new file mode 100644 index 000000000000..43eb87f9f9af --- /dev/null +++ b/dashboard/dashboard-key-visualizer.md @@ -0,0 +1,177 @@ +--- +title: TiDB Dashboard 流量可视化页面 +category: how-to +aliases: ['/docs-cn/stable/how-to/monitor/key-visualizer/','/docs-cn/stable/key-visualizer-monitoring-tool/'] +--- + +# TiDB Dashboard 流量可视化页面 + +流量可视化页面 (Key Visualizer) 可用于分析 TiDB 集群的使用模式和排查流量热点。该页面可视化地呈现了 TiDB 集群一段时间的流量情况。 + +## 访问页面 + +可以通过以下两种方法访问 Key Visualizer 流量可视化页面: + +* 登录 TiDB Dashboard 后,点击左侧导航条的 **Key Visualizer**(流量可视化): + +![访问](/media/dashboard/dashboard-keyviz-access.png) + +* 在浏览器中访问 `http://127.0.0.1:2379/dashboard/#/keyviz`(将 `127.0.0.1:2379` 替换为实际 PD 实例地址和端口)。 + +## 界面示例 + +流量可视化页面示例如下: + +![Key Visualizer 示例图](/media/dashboard/dashboard-keyviz-overview.png) + +从以上流量可视化界面可以观察到以下信息: + ++ 一个大型热力图,显示整体访问流量随时间的变化情况。 ++ 热力图某个坐标的详细信息。 ++ 左侧为表、索引等标识信息。 + +## 基本概念 + +本节介绍流量可视化涉及的一些基本概念。 + +### Region + +在 TiDB 集群中,数据以分布式的方式存储在所有的 TiKV 实例中。TiKV 在逻辑上是一个巨大且有序的 KV Map。整个 Key-Value 空间分成很多 Region,每一个 Region 是一系列连续的 Key。 + +> **注意:** +> +> 关于 Region 的详细介绍,请参考[三篇文章了解 TiDB 技术内幕 - 说存储](https://pingcap.com/blog-cn/tidb-internal-1/#region) + +### 热点 + +在使用 TiDB 的过程中,热点是一个典型的现象,它表现为大量的流量都在读写一小块数据。由于连续的数据往往由同一个 TiKV 实例处理,因此热点对应的 TiKV 实例的性能就成为了整个业务的性能瓶颈。常见的热点场景有使用自增主键连续写入相邻数据导致的写入表数据热点、时间索引下写入相邻时间数据导致的写入表索引热点等。 + +> **注意:** +> +> 热点问题详情请参阅 [TiDB 热点问题详解](https://asktug.com/t/topic/358)。 + +### 热力图 + +热力图是流量可视化页面的核心,它显示了一个指标随时间的变化。热力图的横轴 X 是时间,纵轴 Y 则是按 Key 排序的连续 Region,横跨 TiDB 集群上所有数据库和数据表。颜色越暗 (cold) 表示该区域的 Region 在这个时间段上读写流量较低,颜色越亮 (hot) 表示读写流量越高,即越热。 + +### Region 压缩 + +一个 TiDB 集群中,Region 的数量可能多达数十万。在屏幕上是难以显示这么多 Region 信息的。因此,在一张热力图中,Region 会被压缩到约 1500 个连续范围,每个范围称为 Bucket。在一个热力图上,热的实例更需要关注,因此 Region 压缩总是倾向于将流量较小的大量 Region 压缩为一个 Bucket,而尽量让高流量的 Region 独立成 Bucket。 + +## 使用介绍 + +本节介绍如何使用流量可视化页面。 + +### 设置 + +首次使用流量可视化页面需要先通过**设置**页面手动开启此功能。参考页面指引,点击 **Open Settings**(打开设置)即可打开设置页面: + +![功能未开启](/media/dashboard/dashboard-keyviz-not-enabled.png) + +在功能已经开启时,可通过右上角的设置图标打开设置页面: + +![设置按钮](/media/dashboard/dashboard-keyviz-settings-button.png) + +设置页面如下图所示: + +![设置页面](/media/dashboard/dashboard-keyviz-settings.png) + +通过开关设定好是否开启收集,并点击 **Save**(保存)后生效。开启后,在界面上观察到工具栏已经可以使用: + +![工具栏](/media/dashboard/dashboard-keyviz-toolbar.png) + +功能开启后,后台会持续收集数据,稍等一段时间即可看到热力图。 + +### 观察某一段时间或者 Region 范围 + +打开流量可视化页面时,默认会显示最近六小时整个数据库内的热力图。其中,越靠近右侧(当前时间)时,每列 Bucket 对应的时间间隔会越小。如果你想观察某个特定时间段或者特定的 Region 范围,则可以通过放大来获得更多细节。具体操作描述如下: + +* 在热力图中向上或向下滚动。 +* 点击 **Select & Zoom**(框选)按钮,然后点击并拖动以选择要放大的区域。 + +![框选](/media/dashboard/dashboard-keyviz-select-zoom.gif) + +* 点击 **Reset**(重置)按钮,将 Region 范围重置为整个数据库。 +* 点击「时间选择框」(界面的 **6 hours** 处),重新选择观察时间段。 + +![时间选择](/media/dashboard/dashboard-keyviz-select-time.png) + +> **注意:** +> +> 进行后三种操作,将引起热力图的重新绘制。你可能观察到热力图与放大前有较大差异。这是一个正常的现象,可能是由于在进行局部观察时,Region 压缩的粒度发生了变化,或者是局部范围内,“热”的基准发生了改变。 + +### 调整亮度 + +热力图使用颜色的明暗来表达一个 Bucket 的流量高低,颜色越暗 (cold) 表示该区域的 Region 在这个时间段上读写流量较低,颜色越亮 (hot) 表示读写流量越高,即越热。如果热力图中的颜色太亮或太暗,则可能很难观察到细节。此时,可以点击 **Brightness**(调整亮度)按钮,然后通过滑块来调节页面的亮度。 + +> **注意:** +> +> 在显示一个区域内的热力图时,会根据区域内的流量情况来界定冷热。当整个区域流量较为平均时,即使整体流量在数值上很低,你依然有可能观察到较大的亮色区域。请注意一定要结合数值一起分析。 + +### 选择指标 + +![指标选择](/media/dashboard/dashboard-keyviz-select-type.png) + +你可以通过「指标选择框」(以上界面中 **Write (bytes)** 处)来查看你关心的指标: + +* `Read (bytes)`:读取字节量 +* `Write (bytes)`:读取字节量 +* `Read (keys)`:读取次数 +* `Write (keys)`:写入次数 +* `All`:所有(读写流量的总和) + +### 刷新与自动刷新 + +可以通过点击 **Refresh**(刷新)按钮来重新获得基于当前时间的热力图。当需要实时观察数据库的流量分布情况时,可以点击按钮右侧的向下箭头,选择一个固定的时间间隔让热力图按此间隔自动刷新。 + +> **注意:** +> +> 如果进行了时间范围或者 Region 范围的调整,自动刷新会被关闭。 + +### 查看详情 + +可以将鼠标悬停在你所关注的 Bucket 上,来查看这个区域的详细信息: + +![Bucket 详细信息](/media/dashboard/dashboard-keyviz-tooltip.png) + +如果需要复制某个信息,可以进行点击 Bucket。此时相关详细信息的页面会被暂时钉住。点击你关注的信息,即可将其复制到剪切板: + +![复制 Bucket 详细信息](/media/dashboard/dashboard-keyviz-tooltip-copy.png) + +## 常见热力图解读 + +本章节选取了 Key Visualizer 中常见的四种热力图进行解读。 + +### 均衡:期望结果 + +![均衡结果图](/media/dashboard/dashboard-keyviz-well-dist.png) + +如上图所示,热力图颜色均匀或者深色和亮色混合良好,说明读取或写入在时间和 Region 空间范围上都分布得比较均衡,访问压力均匀地分摊在所有的机器上。这种负载是最适合分布式数据库的。 + +### X 轴明暗交替:需要关注高峰期的资源情况 + +![X 轴明暗交替](/media/dashboard/dashboard-keyviz-period.png) + +如上图所示,热力图在 X 轴(时间)上表现出明暗交替,但 Y 轴 (Region) 则比较均匀,说明读取或写入负载具有周期性的变化。这种情况可能出现在周期性的定时任务场景,如大数据平台每天定时从 TiDB 中抽取数据。一般来说可以关注一下使用高峰时期资源是否充裕。 + +## Y 轴明暗交替:需要关注产生的热点聚集程度 + +![Y 轴明暗交替](/media/dashboard/dashboard-keyviz-continue.png) + +如上图所示,热力图包含几个明亮的条纹,从 Y 轴来看条纹周围都是暗的,这表明明亮条纹区域的 Region 有很高的读写流量,可以从业务角度观察一下是否符合预期。例如,所有业务都关联用户表的情况下,用户表的整体流量就会很高,那么在热力图中表现为亮色区域就非常合理。 + +另外,明亮区域的高度(Y 轴方向的粗细)非常关键。由于 TiKV 自身拥有以 Region 为单位的热点平衡机制,因此涉及热点的 Region 越多其实越能有利于在所有 TiKV 实例上均衡流量。明亮条纹越粗、数量越多则意味着热点越分散、更多的 TiKV 能得到利用;明亮条纹越细、数量越少意味着热点越集中、热点 TiKV 越显著、越需要人工介入并关注。 + +### 明亮斜线:需要关注业务模式 + +![明亮斜线](/media/dashboard/dashboard-keyviz-sequential.png) + +如上图所示,热力图显示了明亮的斜线,表明读写的 Region 是连续的。这种场景常常出现在带索引的数据导入或者扫描阶段。例如,向自增 ID 的表进行连续写入等等。图中明亮部分对应的 Region 是读写流量的热点,往往会成为整个集群的性能问题所在。这种时候,可能需要业务重新调整主键,尽可能打散以将压力分散在多个 Region 上,或者选择将业务任务安排在低峰期。 + +> **注意:** +> +> 这里只是列出了几种常见的热力图模式。流量可视化页面中实际展示的是整个集群上所有数据库、数据表的热力图,因此非常有可能在不同的区域观察到不同的热力图模式,也可能观察到多种热力图模式的混合结果。使用的时候应当视实际情况灵活判断。 + +## 解决热点问题 + +TiDB 内置了不少帮助缓解常见热点问题的功能,深入了解请参考 [TiDB 高并发写入场景最佳实践](/best-practices/high-concurrency-best-practices.md)。 diff --git a/dashboard/dashboard-log-search.md b/dashboard/dashboard-log-search.md new file mode 100644 index 000000000000..e98b6d50fdc2 --- /dev/null +++ b/dashboard/dashboard-log-search.md @@ -0,0 +1,72 @@ +--- +title: TiDB Dashboard 日志搜索页面 +summary: 在集群中搜索所有节点上的日志 +category: how-to +--- + +# TiDB Dashboard 日志搜索页面 + +该页面上允许用户在集群中搜索所有节点上的日志,在页面上预览搜索结果和下载日志。 + +## 访问 + +登录 Dashboard 后点击左侧导航的**日志搜索**可以进入此功能页面: + +![日志搜索首页](/media/dashboard/dashboard-log-search-home.png) + +该页面提供 4 个搜索参数,包括: + +- 时间范围:限定搜索时间范围内的日志,默认值为最近 30 分钟 +- 日志等级:限定最低日志等级,搜索该日志等级以上的所有日志,默认值为 INFO 等级 +- 关键词:任何合法的任何字符串,可选,关键词之间以空格分割,支持正则表达式(大小写不敏感) +- 组件:选择要搜索的集群组件,多选,非空,默认选中所有组件 + +点击**搜索**按钮后,会进入搜索结果的详情页。 + +## 搜索结果详情 + +搜索结果详情页面如下图所示: + +![搜索结果](/media/dashboard/dashboard-log-search-result.png) + +整个页面分为三个部分: + +- 搜索参数选项:与搜索页面的参数选项相同,可以在表单中重新选择参数并开始一次新的搜索(对应上图中框选的区域 1) +- 搜索进度:在页面右侧,展示当前搜索的进度,包括每个节点日志搜索状态和统计等(对应上图中框选的区域 2) +- 搜索结果(对应上图中框选的区域 3): + - 时间:日志产生的时间,时区与前端用户所处时区相同 + - 日志等级:日志等级 + - 组件类型:显示组件名及其地址 + - 日志:每条日志记录的正文部分,不包含日志的时间和日志等级。过长的日志会自动截断,鼠标单击该行可以展开查看完整内容,完整日志最长显示 512 个字符 + +> **注意:** +> +> 在该页面上最多只显示 500 条搜索结果,完整的搜索结果可以通过下载得到。 + +### 搜索进度 + +在搜索进度区域中,对一个节点的搜索称为一次搜索任务,对搜索任务的状态分为: + +- 运行中:开始搜索后,所有任务会进入**运行中**状态 +- 成功:任务完成后自动转到**成功**,此时日志已缓存在 Dashboard 后端所在的本地磁盘中,可以提供给前端下载 +- 失败:用户主动取消,或者某种原因报错退出的任务进入**失败**状态。任务失败时会自动清理本地临时文件 + +搜索进度区域包含三个控制按钮: + +- 下载选中日志:下载被勾选组件的日志(只有已完成的才能被勾选),返回 tar 文件,解压得到一个或多个 zip 文件(每个组件对应一个 zip 文件),解压 zip 得到 log 文本文件 +- 取消:取消所有正在运行的任务,只能在有运行中的任务时才能点击 +- 重试:重试所有失败的任务,只有在有失败任务且无正在运行的任务时才能点击 + +## 搜索历史列表 + +在日志搜索首页点击**查看搜索历史**链接,进入搜索历史列表页面: + +![搜索历史入口](/media/dashboard/dashboard-log-search-history-entry.png) + +![搜索历史列表](/media/dashboard/dashboard-log-search-history.png) + +该列表显示每次搜索的日志的时间范围、日志等级、组件、关键字以及搜索状态等信息。点击**操作**列的**查看详情**链接将跳转到此次搜索的结果详情页面。 + +可以对不再需要的搜索历史执行删除操作,点击右上角的**删除全部任务**,或者先选中需要删除的某些行后再点击**删除选中的任务**进行删除: + +![删除搜索历史](/media/dashboard/dashboard-log-search-delete-history.png) diff --git a/dashboard/dashboard-ops-deploy.md b/dashboard/dashboard-ops-deploy.md new file mode 100644 index 000000000000..10238254195d --- /dev/null +++ b/dashboard/dashboard-ops-deploy.md @@ -0,0 +1,124 @@ +--- +title: 部署 TiDB Dashboard +category: how-to +--- + +# 部署 TiDB Dashboard + +TiDB Dashboard 界面内置于 TiDB 4.0 或更高版本的 PD 组件中,无需额外部署。只需部署标准 TiDB 集群,TiDB Dashboard 就会原生集成。 + +请参阅下列文档了解如何部署标准 TiDB 集群: + ++ [快速试用 TiDB 集群](/quick-start-with-tidb.md#第二种使用-tiup-playground-快速部署本地测试环境) ++ [生产环境部署](/production-deployment-using-tiup.md) ++ [Kubernetes 环境部署](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/access-dashboard/) + +> **注意:** +> +> TiDB Dashboard 目前不能在低于 4.0 版本的集群中部署或使用。 + +## 多 PD 实例部署 + +当集群中部署了多个 PD 实例时,其中仅有一个 PD 实例会固定地提供 TiDB Dashboard 服务。 + +各个 PD 首次运行时会自动协商出其中某一个实例提供 TiDB Dashboard 服务。协商完毕后,无论重启或扩容,都会固定在这个实例上运行 TiDB Dashboard 服务,除非该实例被手动缩容。其他 PD 实例不会运行 TiDB Dashboard 服务。这个协商过程无需用户介入,会自动完成。 + +当用户访问不提供 TiDB Dashboard 服务的 PD 实例时,浏览器将会收到重定向指令,自动引导用户重新访问提供了 TiDB Dashboard 服务的 PD 实例,从而能正常使用。流程如下图所示。 + +![流程示意](/media/dashboard/dashboard-ops-multiple-pd.png) + +> **注意:** +> +> 提供 TiDB Dashboard 服务的 PD 实例不一定与 PD leader 一致。 + +### 查询实际运行 TiDB Dashboard 服务的 PD 实例 + +使用 TiUP 部署时,对于已启动的集群,可通过 `tiup cluster display` 命令查看哪个 PD 节点提供了 TiDB Dashboard 服务(将 `CLUSTER_NAME` 替换为集群名称): + +```bash +tiup cluster display CLUSTER_NAME --dashboard +``` + +输出样例如下: + +``` +http://192.168.0.123:2379/dashboard/ +``` + +> **注意:** +> +> 该功能仅在较新版本的 `tiup cluster` 部署工具中提供。可通过以下命令升级 `tiup cluster`: +> +> ```bash +> tiup update --self +> tiup update cluster --force +> ``` + +### 切换其他 PD 实例提供 TiDB Dashboard 服务 + +使用 TiUP 部署时,对于已启动的集群,可使用 `tiup ctl pd` 命令切换其他 PD 实例运行 TiDB Dashboard,或在禁用 TiDB Dashboard 的情况下重新指定一个 PD 实例运行 TiDB Dashboard: + +```bash +tiup ctl pd -u http://127.0.0.1:2379 config set dashboard-address http://9.9.9.9:2379 +``` + +其中: + +- 将 `127.0.0.1:2379` 替换为任意 PD 实例的 IP 和端口 +- 将 `9.9.9.9:2379` 替换为想运行 TiDB Dashboard 服务的新 PD 实例的 IP 和端口 + +修改完毕后,可使用 `tiup cluster display` 命令确认修改是否生效(将 `CLUSTER_NAME` 替换为集群名称): + +```bash +tiup cluster display CLUSTER_NAME --dashboard +``` + +> **警告:** +> +> 切换 TiDB Dashboard 将会丢失之前 TiDB Dashboard 实例所存储的本地数据,包括流量可视化历史、历史搜索记录等。 + +## 禁用 TiDB Dashboard + +使用 TiUP 部署时,对于已启动的集群,可使用 `tiup ctl pd` 命令在所有 PD 实例上禁用 TiDB Dashboard(将 `127.0.0.1:2379` 替换为任意 PD 实例的 IP 和端口): + +```bash +tiup ctl pd -u http://127.0.0.1:2379 config set dashboard-address none +``` + +禁用 TiDB Dashboard 后,查询哪个 PD 实例提供 TiDB Dashboard 服务将会失败: + +``` +Error: TiDB Dashboard is disabled +``` + +浏览器访问任意 PD 实例的 TiDB Dashboard 地址也将提示失败: + +``` +Dashboard is not started. +``` + +## 重新启用 TiDB Dashboard + +使用 TiUP 部署时,对于已启动的集群,可使用 `tiup ctl pd` 命令,要求 PD 重新协商出某一个实例运行 TiDB Dashboard(将 `127.0.0.1:2379` 替换为任意 PD 实例的 IP 和端口): + +```bash +tiup ctl pd -u http://127.0.0.1:2379 config set dashboard-address auto +``` + +修改完毕后,使用 `tiup cluster display` 命令查看 PD 自动协商出的 TiDB Dashboard 实例地址(将 `CLUSTER_NAME` 替换为集群名称): + +```bash +tiup cluster display CLUSTER_NAME --dashboard +``` + +还可以通过手动指定哪个 PD 实例运行 TiDB Dashboard 服务的方式重新启用 TiDB Dashboard,具体操作参见上文[切换其他 PD 实例提供 TiDB Dashboard 服务](#切换其他-PD-实例提供-TiDB-Dashboard-服务)。 + +> **警告:** +> +> 若新启用的 TiDB Dashboard 实例与禁用前的实例不一致,将会丢失之前 TiDB Dashboard 实例所存储的本地数据,包括流量可视化历史、历史搜索记录等。 + +## 下一步 + +- 参阅[访问 TiDB Dashboard](/dashboard/dashboard-access.md) 章节了解如何访问及登录集群上的 TiDB Dashboard 界面。 + +- 参阅[提高 TiDB Dashboard 安全性](/dashboard/dashboard-ops-security.md) 章节了解如何增强 TiDB Dashboard 的安全性,如配置防火墙等。 diff --git a/dashboard/dashboard-ops-reverse-proxy.md b/dashboard/dashboard-ops-reverse-proxy.md new file mode 100644 index 000000000000..aef2e6bac6f5 --- /dev/null +++ b/dashboard/dashboard-ops-reverse-proxy.md @@ -0,0 +1,174 @@ +--- +title: 通过反向代理使用 TiDB Dashboard +category: how-to +--- + +# 通过反向代理使用 TiDB Dashboard + +你可以使用反向代理将 TiDB Dashboard 服务安全从内部网络提供给外部网络。 + +## 操作步骤 + +### 第 1 步:获取实际 TiDB Dashboard 地址 + +当集群中部署有多个 PD 实例时,其中仅有一个 PD 实例会真正运行 TiDB Dashboard,因此需要确保反向代理的上游 (Upstream) 指向了正确的地址。关于该机制的详情,可参阅 [TiDB Dashboard 多 PD 实例部署](/dashboard/dashboard-ops-deploy.md#多-PD-实例部署) 章节。 + +使用 TiUP 部署工具时,操作命令如下(将 `CLUSTER_NAME` 替换为集群名称): + +```bash +tiup cluster display CLUSTER_NAME --dashboard +``` + +输出即为实际 TiDB Dashboard 地址。样例如下: + +``` +http://192.168.0.123:2379/dashboard/ +``` + +> **注意:** +> +> 该功能仅在较新版本的 `tiup cluster` 部署工具中提供。可通过以下命令升级 `tiup cluster`: +> +> ```bash +> tiup update --self +> tiup update cluster --force +> ``` + +### 第 2 步:配置反向代理 + +#### NGINX + +[NGINX](https://nginx.org/) 作为反向代理时,方法如下。 + +1. 以在 80 端口反向代理 TiDB Dashboard 为例,在 NGINX 配置文件中,新增如下配置: + + ```nginx + server { + listen 80; + location /dashboard/ { + proxy_pass http://192.168.0.123:2379/dashboard/; + } + } + ``` + + 配置 `proxy_pass` 中填写的 URL 即为[第 1 步:获取实际 TiDB Dashboard 地址](#第-1-步获取实际-TiDB-Dashboard-地址)中取得的 TiDB Dashboard 实际地址。 + + > **警告:** + > + > 请务必保留 `proxy_pass` 指令中的 `/dashboard/` 路径,确保只有该路径下的服务会被反向代理,否则将引入安全风险。参见[提高 TiDB Dashboard 安全性](/dashboard/dashboard-ops-security.md)。 + +2. 重启 NGINX,以使配置生效。 + +3. 测试反向代理是否生效:访问 NGINX 所在机器的 80 端口下 `/dashboard/` 地址,如 ,即可访问 TiDB Dashboard。 + +## 自定义路径前缀 + +TiDB Dashboard 默认在 `/dashboard/` 路径下提供服务,即使是反向代理也是如此,例如 `http://example.com/dashboard/`。若要配置反向代理以非默认的路径提供 TiDB Dashboard 服务,例如 `http://example.com/foo` 或 `http://example.com/`,可参考以下步骤。 + +### 第 1 步:修改 PD 配置指定 TiDB Dashboard 服务路径前缀 + +修改 PD 配置中 `[dashboard]` 类别的 `public-path-prefix` 配置项,可指定服务路径前缀。该配置修改后需要重启 PD 实例生效。 + +以 TiUP 部署且希望运行在 `http://example.com/foo` 为例,可指定以下配置: + +```yaml +server_configs: + pd: + dashboard.public-path-prefix: /foo +``` + +若要全新部署集群,可在 TiUP 拓扑文件 `topology.yaml` 中加入上述配置项后进行部署,具体步骤参阅 [TiUP 部署文档](/production-deployment-using-tiup.md#第-3-步编辑初始化配置文件)。 + +对于已部署的集群: + +1. 以编辑模式打开该集群的配置文件(将 `CLUSTER_NAME` 替换为集群名称) + + ```bash + tiup cluster edit-config CLUSTER_NAME + ``` + +2. 在 `server_configs` 的 `pd` 配置下修改或新增配置项,若没有 `server_configs` 请在最顶层新增: + + ```yaml + server_configs: + pd: + dashboard.public-path-prefix: /foo + ``` + + > 修改完成后的配置文件类似于: + > + > ```yaml + > server_configs: + > pd: + > dashboard.public-path-prefix: /foo + > global: + > user: tidb + > ... + > ``` + > + > 或 + > + > ```yaml + > monitored: + > ... + > server_configs: + > tidb: ... + > tikv: ... + > pd: + > dashboard.public-path-prefix: /foo + > ... + > ``` + +3. 滚动重启所有 PD 实例生效配置(将 `CLUSTER_NAME` 替换为集群名称) + + ```bash + tiup cluster reload CLUSTER_NAME -R pd + ``` + +详情请参阅 [TiUP 常见运维操作 - 修改配置参数](/maintain-tidb-using-tiup.md#修改配置参数)。 + +若希望运行在根路径(如 `http://example.com/`)下,相应的配置为: + +```yaml +server_configs: + pd: + dashboard.public-path-prefix: / +``` + +> **警告:** +> +> 修改自定义路径前缀生效后,直接访问将不能正常使用 TiDB Dashboard,您只能通过和路径前缀匹配的反向代理访问。 + +### 第 2 步:修改反向代理配置 + +#### NGINX + +以 `http://example.com/foo` 为例,相应的 NGINX 配置为: + +```nginx +server { + listen 80; + location /foo/ { + proxy_pass http://192.168.0.123:2379/dashboard/; + } +} +``` + +> **警告:** +> +> 请务必保留 `proxy_pass` 指令中的 `/dashboard/` 路径,确保只有该路径下的服务会被反向代理,否则将引入安全风险。参见 [提高 TiDB Dashboard 安全性](/dashboard/dashboard-ops-security.md)。 + +请调整配置中 `http://192.168.0.123:2379/dashboard/` 为[第 1 步:获取实际 TiDB Dashboard 地址](#第-1-步获取实际-TiDB-Dashboard-地址)中取得的 TiDB Dashboard 实际地址。 + +若希望运行在根路径(如 `http://example.com/`),NGINX 配置为: + +```nginx +server { + listen 80; + location / { + proxy_pass http://192.168.0.123:2379/dashboard/; + } +} +``` + +修改配置并重启 NGINX 后即可生效。 diff --git a/dashboard/dashboard-ops-security.md b/dashboard/dashboard-ops-security.md new file mode 100644 index 000000000000..7ebe4e04baba --- /dev/null +++ b/dashboard/dashboard-ops-security.md @@ -0,0 +1,76 @@ +--- +title: 提高 TiDB Dashboard 安全性 +category: how-to +--- + +# 提高 TiDB Dashboard 安全性 + +尽管访问 TiDB Dashboard 需要登录,但它被设计为默认供可信的用户实体访问。当你希望将 TiDB Dashboard 提供给外部网络用户或不可信用户访问时,需要注意采取以下措施以避免安全漏洞。 + +## 为 TiDB `root` 用户设置强密码 + +TiDB Dashboard 的账号体系与 TiDB SQL 用户一致。默认部署情况下,TiDB 的 `root` 用户没有密码,因而访问 TiDB Dashboard 也不需要密码验证。这将会给恶意访问者极大的集群权限,包括执行特权 SQL 等。 + +建议的措施: + +- 为 TiDB `root` 用户设置一个强密码。请参见 [TiDB 用户账户管理](/user-account-management.md) 了解详情。 + +## 使用防火墙阻止不可信访问 + +TiDB Dashboard 通过 PD Client 端口提供服务,默认为 。尽管 TiDB Dashboard 需要验证身份,但 PD Client 端口上承载的其他 PD 内部特权接口不需要验证身份,且能进行特权操作,例如 。因此,将 PD Client 端口直接暴露给外部网络具有极大的风险。 + +建议的措施: + +1. 使用防火墙禁止组件外部网络或不可信网络访问**任何** PD 组件的 Client 端口。 + + 注意,TiDB、TiKV 等组件需要通过 PD Client 端口与 PD 组件进行通信,因此请勿对组件内部网络阻止访问,这将导致集群不可用。 + +2. 参见[通过反向代理使用 TiDB Dashboard](/dashboard/dashboard-ops-reverse-proxy.md) 了解如何配置反向代理将 TiDB Dashboard 服务在另一个端口上安全地提供给外部网络。 + +### 如何在多 PD 实例部署时开放 TiDB Dashboard 端口访问 + +> **警告:** +> +> 本章节描述了一个不安全的访问方案,仅供测试环境使用。在生产环境中,不要使用本方案。请参见本文的其余章节。 + +在测试环境中,您可能需要配置防火墙开放 TiDB Dashboard 端口供外部访问。 + +当部署了多个 PD 实例时,其中仅有一个 PD 实例会真正运行 TiDB Dashboard,访问其他 PD 实例时会发生浏览器重定向,因此需要确保防火墙配置了正确的 IP 地址。关于该机制的详情,可参阅 [TiDB Dashboard 多 PD 实例部署](/dashboard/dashboard-ops-deploy.md#多-PD-实例部署) 章节。 + +使用 TiUP 部署工具时,可使用以下命令查看实际运行 TiDB Dashboard 的 PD 实例地址(将 `CLUSTER_NAME` 替换为集群名称): + +```bash +tiup cluster display CLUSTER_NAME --dashboard +``` + +输出即为实际 TiDB Dashboard 地址。 + +> **注意:** +> +> 该功能仅在较新版本的 `tiup cluster` 部署工具中提供。可通过以下命令升级 `tiup cluster`: +> +> ```bash +> tiup update --self +> tiup update cluster --force +> ``` + +以下是一个样例输出: + +``` +http://192.168.0.123:2379/dashboard/ +``` + +在这个样例中,需要为防火墙配置开放 IP `192.168.0.123` 的 `2379` 端口入站访问,并通过 访问 TiDB Dashboard。 + +## 反向代理仅代理 TiDB Dashboard + +如前文所述,PD Client 端口下提供的服务不仅有 TiDB Dashboard(位于 ),还有其他 PD 内部特权接口(如 )。因此,使用反向代理将 TiDB Dashboard 提供给外部网络时,应当确保仅提供 `/dashboard` 前缀下的服务,而非该端口下所有服务,避免外部网络能通过反向代理访问到 PD 内部特权接口。 + +建议的措施: + +- 参见 [通过反向代理使用 TiDB Dashboard](/dashboard/dashboard-ops-reverse-proxy.md) 了解安全且推荐的反向代理配置。 + +## 其他建议的安全措施 + +- [为 TiDB 组件间通信开启加密传输](/enable-tls-between-components.md) +- [为 TiDB 客户端服务端间通信开启加密传输](/enable-tls-between-clients-and-servers.md) diff --git a/dashboard/dashboard-overview.md b/dashboard/dashboard-overview.md new file mode 100644 index 000000000000..5df1b0e184c8 --- /dev/null +++ b/dashboard/dashboard-overview.md @@ -0,0 +1,94 @@ +--- +title: TiDB Dashboard 概况页面 +category: how-to +--- + +# TiDB Dashboard 概况页面 + +该页面显示了整个集群的概况,包含以下信息: + +- 整个集群的 QPS +- 整个集群的查询延迟 +- 最近一段时间内累计耗时最多的若干 SQL 语句 +- 最近一段时间内运行时间超过一定阈值的慢查询 +- 各个实例的节点数和状态 +- 监控及告警信息 + +## 访问 + +登录 TiDB Dashboard 后默认进入该页面,也可以左侧导航条点击**概况**(Overview)进入: + +![访问](/media/dashboard/dashboard-overview-access.png) + +## QPS + +该区域显示最近一小时整个集群的每秒成功和失败查询数量: + +![界面](/media/dashboard/dashboard-overview-qps.png) + +> **注意:** +> +> 该功能仅在部署了 Prometheus 监控组件的集群上可用,未部署监控组件的情况下会显示为失败。 + +## 延迟 + +该区域显示最近一小时整个集群中 99.9%、99% 和 90% 查询的延迟: + +![界面](/media/dashboard/dashboard-overview-latency.png) + +> **注意:** +> +> 该功能仅在部署了 Prometheus 监控组件的集群上可用,未部署监控组件的情况下会显示为失败。 + +## Top SQL 语句 + +该区域显示最近一段时间内整个群集中累计耗时最长的 10 类 SQL 语句。查询参数不一样但结构一样的 SQL 会归为同一类 SQL 语句,在同一行中显示: + +![界面](/media/dashboard/dashboard-overview-top-statements.png) + +该区域显示的内容与 [SQL 语句分析页面](/dashboard/dashboard-statement-list.md)一致,可点击 **Top SQL 语句** (Top SQL Statements) 标题查看完整列表。关于该表格中各列详情,见 [SQL 语句分析页面](/dashboard/dashboard-statement-list.md)。 + +> **注意:** +> +> 该功能仅在开启了 SQL 语句分析功能的集群上可用。 + +## 最近的慢查询 + +该区域默认显示最近 30 分钟内整个集群中最新的 10 条慢查询: + +![界面](/media/dashboard/dashboard-overview-slow-query.png) + +默认情况下运行时间超过 300ms 的SQL 查询即会被计为慢查询并显示在该表格中。可通过调整 [tidb_slow_log_threshold](/tidb-specific-system-variables.md#tidb_slow_log_threshold) 变量或 TiDB [slow-threshold](/tidb-configuration-file.md#slow-threshold) 参数调整阈值。 + +该区域显示的内容与[慢查询页面](/dashboard/dashboard-slow-query.md)一致,可点击**最近的慢查询** (Recent Slow Queries) 标题查看完整列表。关于该表格中各列详情,见[慢查询页面](/dashboard/dashboard-slow-query.md)。 + +> **注意:** +> +> 该功能仅在配置开启了慢查询日志的集群中可用,使用 TiUP 或 Ansible 部署的集群默认开启慢查询日志。 + +## 实例 + +该区域汇总显示了整个集群中 TiDB、TiKV、PD、TiFlash 的总实例数量及异常实例数量: + +![界面](/media/dashboard/dashboard-overview-instances.png) + +状态描述如下: + +- Up:实例运行正常(含下线中的存储实例)。 +- Down:实例运行异常,例如网络无法连接、进程已崩溃等。 + +点击**实例**标题可进入[集群信息页面](/dashboard/dashboard-cluster-info.md)查看各个实例的详细运行状态。 + +## 监控和告警 + +该区域提供了便捷的链接方便用户查看详细监控或告警: + +![界面](/media/dashboard/dashboard-overview-monitor.png) + +- **查看监控**链接:点击后跳转至 Grafana 页面,可查看集群详细监控信息。关于 Grafana 监控面板中各个详细监控指标的解释,参见[监控指标](/grafana-overview-dashboard.md)文档。 +- **查看告警**链接:点击后跳转至 AlertManager 页面,可查看集群详细告警信息。当集群中已有告警时,告警数量将会直接显示在链接文本上。 +- **运行诊断**链接:点击后跳转至集群诊断页面,参见[集群诊断页面](/dashboard/dashboard-diagnostics-access.md)了解详情。 + +> **注意:** +> +> **查看监控**链接仅在集群中部署了 Grafana 节点时可用,**查看告警**链接仅在集群中部署了 AlertManager 节点时可用。 diff --git a/dashboard/dashboard-profiling.md b/dashboard/dashboard-profiling.md new file mode 100644 index 000000000000..048f2f24d0ad --- /dev/null +++ b/dashboard/dashboard-profiling.md @@ -0,0 +1,52 @@ +--- +title: TiDB Dashboard 实例性能分析页面 +category: how-to +--- + +# TiDB Dashboard 实例性能分析页面 + +该功能允许用户对各个 TiDB、TiKV、PD 实例在不重启的情况下进行内部性能数据收集。收集到的性能数据可显示为火焰图或有向无环图,直观展现实例在性能收集的时间段内执行的各种内部操作及比例,快速了解该实例 CPU 资源消耗的主要内容。 + +## 访问 + +可以通过以下两种方法访问实例性能分析页面: + +- 登录后,左侧导航条点击 **高级调试** → **实例性能分析**: + + ![访问](/media/dashboard/dashboard-profiling-access.png) + +- 在浏览器中访问 (将 `127.0.0.1:2379` 替换为实际 PD 实例地址和端口)。 + +## 开始性能分析 + +在实例性能分析页面,选择至少一个想要分析的目标实例,点击**开始分析**(Start Profiling)按钮即可开始性能分析: + +![界面](/media/dashboard/dashboard-profiling-start.png) + +在开始性能分析前可以修改性能分析时长。性能分析所需时间取决于分析时长,默认为 30 秒。30 秒的性能分析大约需要 30 秒完成。 + +## 查看性能分析状态 + +开始性能分析后,可以看到实时性能分析状态和进度: + +![界面](/media/dashboard/dashboard-profiling-view-progress.png) + +性能分析会在后台运行,刷新或退出当前页面不会终止已经运行的性能分析任务。 + +## 下载性能分析结果 + +所有实例的性能分析都完成后,可点击右上角下载按钮(Download Profiling Result)打包下载所有性能分析结果: + +![界面](/media/dashboard/dashboard-profiling-download.png) + +也可以点击列表中的单个实例,直接查看其性能分析结果: + +![界面](/media/dashboard/dashboard-profiling-view-single.png) + +## 查看性能分析历史 + +在性能分析页面下方,列出了性能分析历史。点击任意一行,即可查看其状态详情: + +![界面](/media/dashboard/dashboard-profiling-history.png) + +关于状态详情页的操作,参见[查看性能分析状态](#查看性能分析状态)章节。 diff --git a/dashboard/dashboard-slow-query.md b/dashboard/dashboard-slow-query.md new file mode 100644 index 000000000000..62dafdb5fd0a --- /dev/null +++ b/dashboard/dashboard-slow-query.md @@ -0,0 +1,61 @@ +--- +title: TiDB Dashboard 慢查询页面 +summary: 了解如何在 TiDB Dashboard 中查看慢查询。 +category: how-to +--- + +# TiDB Dashboard 慢查询页面 + +该页面上能检索和查看集群中所有慢查询。 + +默认情况下,执行时间超过 300ms 的 SQL 查询就会被视为慢查询,被记录到[慢查询日志](/identify-slow-queries.md)中,并可通过本功能对记录到的慢查询进行查询。可调整 [`tidb_slow_log_threshold`](/tidb-specific-system-variables.md#tidb_slow_log_threshold) SESSION 变量或 TiDB [`slow-threshold`](/tidb-configuration-file.md#slow-threshold) 参数调整慢查询阈值。 + +> **注意:** +> +> 若关闭了慢查询日志,则本功能不可用。慢查询日志默认开启,可通过修改 TiDB 配置 [`enable-slow-log`](/tidb-configuration-file.md#enable-slow-log) 开启或禁用。 + +## 访问列表页面 + +可以通过以下两种方法访问慢查询页面: + +* 登录后,左侧导航条点击**慢查询** (**Slow Queries**): + +![access 访问页面](/media/dashboard/dashboard-slow-queries-access.png) + +* 在浏览器中访问 (将 `127.0.0.1:2379` 替换为任意实际 PD 地址和端口)。 + +慢查询页面所展示的所有数据都来自于 TiDB 慢查询系统表及慢查询日志,参见[慢查询日志](/identify-slow-queries.md)文档了解详细情况。 + +### 修改列表过滤条件 + +可按时间范围、慢查询语句关联的数据库、SQL 关键字、SQL 类型、显示的慢查询语句数量等条件过滤,筛选慢查询句。如下所示,默认显示 30 分钟内最近 100 条慢查询。 + +![修改列表过滤条件](/media/dashboard/dashboard-slow-queries-list1.png) + +### 显示更多列信息 + +页面顶部**选择列** (**Columns**) 选项中可选择显示更多列,可将鼠标移动到列名右侧的 **(i)** 图标处查看列的说明: + +![显示更多列信息](/media/dashboard/dashboard-slow-queries-list2.png) + +### 修改列表排序依据 + +列表默认以**结束运行时间** (**Finish Time**) 逆序排序,点击不同的列标题可以修改排序依据或切换排序顺序: + +![修改列表排序依据](/media/dashboard/dashboard-slow-queries-list3.png) + +## 查看执行详情 + +在列表中点击任意一行可以显示该慢查询的详细执行信息,包含: + +- SQL:慢查询 SQL 文本(下图中区域 1) +- 执行计划:慢查询的执行计划,参阅[理解 TiDB 执行计划](/query-execution-plan.md)文档了解如何解读执行计划(下图中区域 2) +- 其他分类好的 SQL 执行信息(下图中区域 3) + +![查看执行详情](/media/dashboard/dashboard-slow-queries-detail1.png) + +点击**展开** (**Expand**) 链接可以展开相应项的完整内容,点击**复制** (**Copy**) 链接可以复制完整内容到剪贴板。 + +点击标签页标题可切换显示不同分类的 SQL 执行信息: + +![显示不同分类执行信息](/media/dashboard/dashboard-slow-queries-detail2.png) diff --git a/dashboard/dashboard-statement-details.md b/dashboard/dashboard-statement-details.md new file mode 100644 index 000000000000..5a2bec4bc00e --- /dev/null +++ b/dashboard/dashboard-statement-details.md @@ -0,0 +1,62 @@ +--- +title: TiDB Dashboard SQL 语句分析执行详情页面 +summary: 查看单个 SQL 语句执行的详细情况 +category: how-to +aliases: ['/docs-cn/stable/dashboard/dashboard-statement-detail/'] +--- + +# TiDB Dashboard SQL 语句分析执行详情页面 + +在列表中点击任意一行可以进入该 SQL 语句的详情页查看更详细的信息,这此信息包括三大部分: + +- SQL 语句概况:包括 SQL 模板,SQL 模板 ID,当前查看的时间范围,执行计划个数以及执行所在的数据库(下图区域 1) +- 执行计划列表:如果该 SQL 语句有多个执行计划,则显示该列表,可以选择不同的执行计划,在列表下方会显示选中的执行计划详情;如果只有一个执行计划,则该列表不显示(下图区域 2) +- 执行计划详情:显示选中的执行计划的详细信息,具体见下一小节(下图区域 3) + +![详情](/media/dashboard/dashboard-statement-detail.png) + +## 执行计划详情 + +执行计划详情包括以下内容: + +- SQL 样本:该计划对应的实际执行的某一条 SQL 语句文本。时间范围内任何出现过的 SQL 都可能作为 SQL 样本。 +- 执行计划:执行计划的完整内容,参阅[理解 TiDB 执行计划](/query-execution-plan.md)文档了解如何解读执行计划。如果选择了多个执行计划,则显示的是其中任意一个。 +- 其他关于该 SQL 的基本信息、执行时间、Coprocessor 读取、事务、慢查询等信息,可点击相应标签页标题切换。 + +![执行计划详情](/media/dashboard/dashboard-statement-plans-detail.png) + +### 基本信息 + +包含关于表名、索引名、执行次数、累计耗时等信息。**描述**(Description)列对各个字段进行了具体描述。 + +![基本信息](/media/dashboard/dashboard-statement-plans-basic.png) + +### 执行时间 + +显示执行计划执行的各阶段所耗费时间。 + +> **注意:** +> +> 由于单个 SQL 语句内部可能有并行执行的操作,因此各阶段累加时间可能超出该 SQL 语句的实际执行时间。 + +![执行时间](/media/dashboard/dashboard-statement-plans-time.png) + +### Coprocessor 读取 + +显示 Coprocessor 读取的相关信息。 + +![Coprocessor 读取](/media/dashboard/dashboard-statement-plans-cop-read.png) + +### 事务 + +显示执行计划与事务相关的信息,比如平均写入 key 个数,最大写入 key 个数等。 + +![事务](/media/dashboard/dashboard-statement-plans-transaction.png) + +### 慢查询 + +如果该执行计划执行过慢,则在慢查询标签页下可以看到其关联的慢查询记录。 + +![慢查询](/media/dashboard/dashboard-statement-plans-slow-queries.png) + +该区域显示的内容结构与慢查询页面一致,详见[慢查询页面](/dashboard/dashboard-slow-query.md)。 diff --git a/dashboard/dashboard-statement-list.md b/dashboard/dashboard-statement-list.md new file mode 100644 index 000000000000..294726dcf3bb --- /dev/null +++ b/dashboard/dashboard-statement-list.md @@ -0,0 +1,68 @@ +--- +title: TiDB Dashboard SQL 语句分析列表页面 +summary: 查看所有 SQL 语句在集群上执行情况 +category: how-to +--- + +# TiDB Dashboard SQL 语句分析执行详情页面 + +该页面可以查看所有 SQL 语句在集群上执行情况,常用于分析总耗时或单次耗时执行耗时较长的 SQL 语句。 + +在该页面中,结构一致的 SQL 查询(即使查询参数不一致)都会被归为同一个 SQL 语句,例如 `SELECT * FROM employee WHERE id IN (1, 2, 3)` 和 `select * from EMPLOYEE where ID in (4, 5)` 都属于同一 SQL 语句 `select * from employee where id in (...)`。 + +## 访问列表页面 + +可以通过以下两种方法访问 SQL 语句分析页面: + +- 登录后,左侧导航条点击**SQL 语句分析**(SQL Statements): + + ![访问](/media/dashboard/dashboard-statement-access.png) + +- 在浏览器中访问 (将 `127.0.0.1:2379` 替换为实际 PD 实例地址和端口)。 + +SQL 语句分析页面所展示的所有数据都来自于 TiDB Statement 系统表,参见 [Statement Summary Tables](/statement-summary-tables.md) 文档了解该系统表的详细情况。 + +### 修改列表过滤条件 + +页面顶部可修改显示的时间范围、按执行 SQL 所在数据库进行过滤,或按 SQL 类型进行过滤,如下所示。默认显示最近一个收集周期(默认最近 30 分钟)内的所有 SQL 语句执行情况。 + +![修改过滤条件](/media/dashboard/dashboard-statement-filter-options.png) + +### 显示其他字段 + +页面顶部**选择列**(Columns)选项中可选择显示更多列,可将鼠标移动到列名右侧的 (i) 图标处查看列的说明: + +![选择列](/media/dashboard/dashboard-statement-columns-selector.png) + +### 修改列表排序依据 + +列表默认以**累计耗时**(Total Latency)从高到低进行排序,点击不同的列标题可以修改排序依据或切换排序顺序: + +![修改列排序](/media/dashboard/dashboard-statement-change-order.png) + +### 修改数据收集设置 + +在列表页面,点击顶部右侧的**设置**(Settings)按钮,即可对 SQL 语句分析功能进行设置: + +![设置入口](/media/dashboard/dashboard-statement-setting-entry.png) + +点击后设置界面如下图所示: + +![设置](/media/dashboard/dashboard-statement-settings.png) + +在设置中可以选择关闭或开启 SQL 语句分析功能。在开启 SQL 语句分析功能时可以修改以下选项: + +- 数据收集周期:默认 30 分钟,每次进行 SQL 语句分析的时间长度。SQL 语句分析功能每次对一段时间范围内的所有 SQL 语句进行汇总统计,如果这个时间范围过长,则统计的粒度粗,不利用定位问题;如果太短,则统计的粒度细,方便定位问题,但会导致在相同的数据保留时间内产生更多的记录,产生更多的内存占用。因此需要根据实际情况调整,在需要定位问题时适当地将值调低。 +- 数据保留时间:默认 1 天,统计信息保留的时间,超过这个时间的数据会被从系统表中删除。 + +参见 [Statement Summary Tables 参数设置](/statement-summary-tables.md#参数配置) 文档了解详细情况。 + +> **注意:** +> +> 由于 Statement 系统表只存放在内存中,关闭此功能后,系统表中的数据会将清空。 +> +> 数据收集周期和保留时间的值会影响内存占用,因此建议根据实际情况调整,保留时间不宜设置过大。 + +## 下一步 + +阅读[查看执行详情](/dashboard/dashboard-statement-details.md)章节了解如何进一步查看 SQL 语句的详细执行情况。 diff --git a/data-type-date-and-time.md b/data-type-date-and-time.md new file mode 100644 index 000000000000..90c0ef6bf43c --- /dev/null +++ b/data-type-date-and-time.md @@ -0,0 +1,355 @@ +--- +title: 日期和时间类型 +category: reference +aliases: ['/docs-cn/stable/reference/sql/data-types/date-and-time/'] +--- + +# 日期和时间类型 + +TiDB 支持 MySQL 所有的日期和时间类型,包括 `DATE`、`TIME`、`DATETIME`、`TIMESTAMP` 以及 `YEAR`。完整信息可以参考 [MySQL 中的时间和日期类型](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-types.html)。 + +每种类型都有有效值范围,值为 0 表示无效值。此外,`TIMESTAMP` 和`DATETIME` 类型能自动生成新的时间值。 + +关于日期和时间值类型,需要注意: + +- 日期部分必须是“年-月-日”的格式(例如 `1998-09-04`),而不是“月-日-年”或“日-月-年”的格式。 +- 如果日期的年份部分是 2 位数,TiDB 会根据[年份为两位数的具体规则](#年份为两位数)进行转换。 +- 如果格式必须是数值类型,TiDB 会自动将日期或时间值转换为数值类型。例如: + + {{< copyable "sql" >}} + + ```sql + SELECT NOW(), NOW()+0, NOW(3)+0; + ``` + + ```sql + +---------------------+----------------+--------------------+ + | NOW() | NOW()+0 | NOW(3)+0 | + +---------------------+----------------+--------------------+ + | 2012-08-15 09:28:00 | 20120815092800 | 20120815092800.889 | + +---------------------+----------------+--------------------+ + ``` + +- TiDB 可以自动将无效值转换同一类型的零值。是否进行转换取决于 SQL 模式的设置。比如: + + {{< copyable "sql" >}} + + ```sql + show create table t1; + ``` + + ```sql + +-------+---------------------------------------------------------------------------------------------------------+ + | Table | Create Table | + +-------+---------------------------------------------------------------------------------------------------------+ + | t1 | CREATE TABLE `t1` ( + `a` time DEFAULT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin | + +-------+---------------------------------------------------------------------------------------------------------+ + 1 row in set (0.00 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + select @@sql_mode; + ``` + + ```sql + +-------------------------------------------------------------------------------------------------------------------------------------------+ + | @@sql_mode | + +-------------------------------------------------------------------------------------------------------------------------------------------+ + | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | + +-------------------------------------------------------------------------------------------------------------------------------------------+ + 1 row in set (0.00 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + insert into t1 values (`2090-11-32:22:33:44`); + ``` + + ```sql + ERROR 1292 (22007): Truncated incorrect time value: `2090-11-32:22:33:44` + ``` + + {{< copyable "sql" >}} + + ```sql + set @@sql_mode=``; + ``` + + ```sql + Query OK, 0 rows affected (0.01 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + insert into t1 values (`2090-11-32:22:33:44`); + ``` + + ```sql + Query OK, 1 row affected, 1 warning (0.01 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + select * from t1; + ``` + + ```sql + +----------+ + | a | + +----------+ + | 00:00:00 | + +----------+ + 1 row in set (0.01 sec) + ``` + +- SQL 模式的不同设置,会改变 TiDB 对格式的要求。 +- 如果 SQL 模式的 `NO_ZERO_DATE` 被禁用,TiDB 允许 `DATE` 和 `DATETIME` 列中的月份或日期为零。例如,`2009-00-00` 或 `2009-01-00`。如果使用函数计算这种日期类型,例如使用 `DATE_SUB()` 或 `DATE_ADD()` 函数,计算结果可能不正确。 +- 默认情况下,TiDB 启用 `NO_ZERO_DATE` SQL 模式。该模式可以避免存储像 `0000-00-00` 这样的零值。 + +不同类型的零值如下表所示: + +| 数据类型 | 零值 | +| :------ | :---- | +| DATE | `0000-00-00` | +| TIME | `00:00:00` | +| DATETIME | `0000-00-00 00:00:00` | +| TIMESTAMP | `0000-00-00 00:00:00` | +| YEAR | 0000 | + +如果 SQL 模式允许使用无效的 `DATE`、`DATETIME`、`TIMESTAMP` 值,无效值会自动转换为相应的零值(`0000-00-00` 或 `0000-00-00 00:00:00`)。 + + + +### 自动初始化和更新 `TIMESTAMP` 或 `DATETIME` + +带有 `TIMESTAMP` 或 `DATETIME` 数据类型的列可以自动初始化为或更新为当前时间。 + +对于表中任何带有 `TIMESTAMP` 或 `DATETIME` 数据类型的列,你可以设置默认值,或自动更新为当前时间戳。 + +在定义列的时候,`TIMESTAMP` 和 `DATETIME` 可以通过 `DEFAULT CURRENT_TIMESTAMP` 和 `ON UPDATE CURRENT_TIMESTAMP` 来设置。`DEFAULT` 也可以设置为一个特定的值,例如 `DEFAULT 0` 或 `DEFAULT '2000-01-01 00:00:00'`。 + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1 ( + ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +``` + +除非指定 `DATETIME` 的值为 `NOT NULL`,否则默认 `DATETIME` 的值为 `NULL`。指定 `DATETIME` 的值为 `NOT NULL` 时,如果没有设置默认值,则默认值为 `0`。 + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1 ( + dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP, -- default NULL + dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- default 0 +); +``` + +### 时间值的小数部分 + +`DATETIME` 和 `TIMESTAMP` 值最多可以有 6 位小数,精确到毫秒。如果包含小数部分,值的格式为 `YYYY-MM-DD HH:MM:SS[.fraction]`,小数部分的范围为 `000000` 到`999999`。必须使用小数点分隔小数部分与其他部分。 + ++ 使用 `type_name(fsp)` 可以定义精确到小数的列,其中 `type_name` 可以是`TIME`、`DATETIME` 或 `TIMESTAMP`。例如: + + {{< copyable "sql" >}} + + ```sql + CREATE TABLE t1 (t TIME(3), dt DATETIME(6)); + ``` + + `fsp` 范围是 `0` 到 `6`。 + + `0` 表示没有小数部分。如果省略了 `fsp` ,默认为 `0`。 + ++ 当插入包含小数部分的 `TIME`、`DATETIME` 或 `TIMESTAMP` 时,如果小数部分的位数过少或过多,可能需要进行四舍五入。例如: + + {{< copyable "sql" >}} + + ```sql + CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) ); + ``` + + ```sql + Query OK, 0 rows affected (0.33 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + INSERT INTO fractest VALUES + > ('17:51:04.777', '2014-09-08 17:51:04.777', '2014-09-08 17:51:04.777'); + ``` + + ```sql + Query OK, 1 row affected (0.03 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + SELECT * FROM fractest; + ``` + + ```sql + +-------------|------------------------|------------------------+ + | c1 | c2 | c3 | + +-------------|------------------------|------------------------+ + | 17:51:04.78 | 2014-09-08 17:51:04.78 | 2014-09-08 17:51:04.78 | + +-------------|------------------------|------------------------+ + 1 row in set (0.00 sec) + ``` + +### 日期和时间类型的转换 + +在日期和时间类型之间进行转换时,有些转换可能会导致信息丢失。例如,`DATE`、`DATETIME` 和 `TIMESTAMP` 都有各自的有效值范围。`TIMESTAMP` 不能早于 UTC 时间的 1970 年,也不能晚于 UTC 时间的 `2038-01-19 03:14:07`。根据这个规则,`1968-01-01` 对于 `DATE` 或 `DATETIME` 是有效的,但当 `1968-01-01` 转换为 `TIMESTAMP` 时,就会变成 0。 + +`DATE` 的转换: + ++ 当 `DATE` 转换为 `DATETIME` 或 `TIMESTAMP` 时,会添加时间部分 `00:00:00`,因为 `DATE` 不包含任何时间信息。 ++ 当 `DATE` 转换为 `TIME` 时,结果是 `00:00:00`。 + +`DATETIME` 或 `TIMESTAMP` 的转换: + ++ 当 `DATETIME` 或 `TIMESTAMP` 转换为 `DATE` 时,时间和小数部分将被舍弃。例如,`1999-12-31 23:59:59.499` 被转换为 `1999-12-31`。 ++ 当 `DATETIME` 或 `TIMESTAMP` 转换为 `TIME` 时,时间部分被舍弃,因为 `TIME` 不包含任何时间信息。 + +如果要将 `TIME` 转换为其他时间和日期格式,日期部分会自动指定为 `CURRENT_DATE()`。最终的转换结果是由 `TIME` 和 `CURRENT_DATE()` 组成的日期。也就是说,如果 `TIME` 的值超出了 `00:00:00` 到 `23:59:59` 的范围,那么转换后的日期部分并不表示当前的日期。 + +当 `TIME` 转换为 `DATE` 时,转换过程类似,时间部分被舍弃。 + +使用 `CAST()` 函数可以显式地将值转换为 `DATE` 类型。例如: + +{{< copyable "sql" >}} + +```sql +date_col = CAST(datetime_col AS DATE) +``` + +将 `TIME` 和 `DATETIME` 转换为数字格式。例如: + +{{< copyable "sql" >}} + +```sql +SELECT CURTIME(), CURTIME()+0, CURTIME(3)+0; +``` + +```sql ++-----------|-------------|--------------+ +| CURTIME() | CURTIME()+0 | CURTIME(3)+0 | ++-----------|-------------|--------------+ +| 09:28:00 | 92800 | 92800.887 | ++-----------|-------------|--------------+ +``` + +{{< copyable "sql" >}} + +```sql +SELECT NOW(), NOW()+0, NOW(3)+0; +``` + +```sql ++---------------------|----------------|--------------------+ +| NOW() | NOW()+0 | NOW(3)+0 | ++---------------------|----------------|--------------------+ +| 2012-08-15 09:28:00 | 20120815092800 | 20120815092800.889 | ++---------------------|----------------|--------------------+ +``` + +### 年份为两位数 + +如果日期中包含年份为两位数,这个年份是有歧义的,并不显式地表示实际年份。 + +对于 `DATETIME`、`DATE` 和 `TIMESTAMP` 类型,TiDB 使用如下规则来消除歧义。 + +- 将 01 至 69 之间的值转换为 2001 至 2069 之间的值。 +- 将 70 至 99 之间的值转化为 1970 至 1999 之间的值。 + +上述规则也适用于 `YEAR` 类型,但有一个例外。将数字 `00` 插入到 `YEAR(4)` 中时,结果是 0000 而不是 2000。 + +如果想让结果是 2000,需要指定值为 `2000`。 + +对于 `MIN()` 和 `MAX()` 等函数,年份为两位数时可能会得到错误的计算结果。建议年份为四位数时使用这类函数。 + +## 类型定义 + +### `DATE` 类型 + +`DATE` 类型只包含日期部分,不包含时间部分。`DATE` 类型的格式为 `YYYY-MM-DD`,支持的范围是 `1000-01-01` 到 `9999-12-31`。 + +{{< copyable "sql" >}} + +```sql +DATE +``` + +### `TIME` 类型 + +`TIME` 类型的格式为 `HH:MM:SS[.fraction]`,支持的范围是 `-838:59:59.000000` 到 `838:59:59.000000`。`TIME` 不仅可用于指示一天内的时间,还可用于指两个事件之间的时间间隔。`fsp` 参数表示秒精度,取值范围为:0 ~ 6,默认值为 0。 + +{{< copyable "sql" >}} + +```sql +TIME[(fsp)] +``` + +> **注意:** +> +> 注意 `TIME` 的缩写形式。例如,`11:12` 表示 `11:12:00` 而不是 `00:11:12`。但是,`1112` 表示 `00:11:12`。这些差异取决于 `:` 字符的存在与否。 + +### `DATETIME` 类型 + +`DATETIME` 类型是日期和时间的组合,格式为 `YYYY-MM-DD HH:MM:SS[.fraction]`。支持的范围是 `1000-01-01 00:00:00.000000` 到 `9999-12-31 23:59:59.999999`。`fsp` 参数表示秒精度,取值范围为 0~6,默认值为 0。TiDB 支持字符串或数字转换为 `DATETIME` 类型。 + +{{< copyable "sql" >}} + +```sql +DATETIME[(fsp)] +``` + +### `TIMESTAMP` 类型 + +`TIMESTAMP` 类型是日期和时间的组合,支持的范围是 UTC 时间从 `1970-01-01 00:00:01.000000` 到 `2038-01-19 03:14:07.999999`。`fsp` 参数表示秒精度,取值范围为 0~6,默认值为 0。在 `TIMESTAMP` 中,不允许零出现在月份部分或日期部分,唯一的例外是零值本身 `0000-00-00 00:00:00`。 + +{{< copyable "sql" >}} + +```sql +TIMESTAMP[(fsp)] +``` + +#### 时区处理 + +当存储 `TIMESTAMP` 时,TiDB 会将当前时区的 `TIMESTAMP` 值转换为 UTC 时区。当读取 `TIMESTAMP` 时,TiDB 将存储的 `TIMESTAMP` 值从 UTC 时区转换为当前时区(注意:`DATETIME` 不会这样处理)。每次连接的默认时区是服务器的本地时区,可以通过环境变量 `time_zone` 进行修改。 + +> **警告:** +> +> 和 MySQL 一样,`TIMESTAMP` 数据类型受 [2038 年问题](https://zh.wikipedia.org/wiki/2038%E5%B9%B4%E9%97%AE%E9%A2%98)的影响。如果存储的值大于 2038,建议使用 `DATETIME` 类型。 + +### `YEAR` 类型 + +`YEAR` 类型的格式为 `YYYY`,支持的值范围是 `1901` 到 `2155`,也支持零值 `0000`。 + +{{< copyable "sql" >}} + +```sql +YEAR[(4)] +``` + +`YEAR` 类型遵循以下格式规则: + ++ 如果是四位数的数值,支持的范围是 `1901` 至 `2155`。 ++ 如果是四位数的字符串,支持的范围是 `'1901'` 到 `'2155'`。 ++ 如果是 1~99 之间的一位数或两位数的数字,1~69 换算成 2001~2069,70~99 换算成 1970~1999。 ++ 支持 `'0'` 到 `'99'` 之间的一位数或两位数字符串的范围 ++ 将数值 `0` 转换为 `0000`,将字符串 `'0'` 或 `'00'` 转换为 `'2000'`。 + +无效的 `YEAR` 值会自动转换为 `0000`(如果用户没有使用 `NO_ZERO_DATE` SQL 模式)。 diff --git a/data-type-default-values.md b/data-type-default-values.md new file mode 100644 index 000000000000..ad5cc0a17af2 --- /dev/null +++ b/data-type-default-values.md @@ -0,0 +1,27 @@ +--- +title: 数据类型的默认值 +category: reference +aliases: ['/docs-cn/stable/reference/sql/data-types/default-values/'] +--- + +# 数据类型的默认值 + +在一个数据类型描述中的 `DEFAULT value` 段描述了一个列的默认值。这个默认值必须是常量,不可以是一个函数或者是表达式。但是对于时间类型,可以例外的使用 `NOW`、`CURRENT_TIMESTAMP`、`LOCALTIME`、`LOCALTIMESTAMP` 等函数作为 `DATETIME` 或者 `TIMESTAMP` 的默认值。 + +`BLOB`、`TEXT` 以及 `JSON` 不可以设置默认值。 + +如果一个列的定义中没有 `DEFAULT` 的设置。TiDB 按照如下的规则决定: + +* 如果该类型可以使用 `NULL` 作为值,那么这个列会在定义时添加隐式的默认值设置 `DEFAULT NULL`。 +* 如果该类型无法使用 `NULL` 作为值,那么这个列在定义时不会添加隐式的默认值设置。 + +对于一个设置了 `NOT NULL` 但是没有显式设置 `DEFAULT` 的列,当 `INSERT`、`REPLACE` 没有涉及到该列的值时,TiDB 根据当时的 `SQL_MODE` 进行不同的行为: + +* 如果此时是 `strict sql mode`,在事务中的语句会导致事务失败并回滚,非事务中的语句会直接报错。 +* 如果此时不是 `strict sql mode`,TiDB 会为这列赋值为列数据类型的隐式默认值。 + +此时隐式默认值的设置按照如下规则: + +* 对于数值类型,它们的默认值是 0。当有 `AUTO_INCREMENT` 参数时,默认值会按照增量情况赋予正确的值。 +* 对于除了时间戳外的日期时间类型,默认值会是该类型的“零值”。时间戳类型的默认值会是当前的时间。 +* 对于除枚举以外的字符串类型,默认值会是空字符串。对于枚举类型,默认值是枚举中的第一个值。 diff --git a/data-type-json.md b/data-type-json.md new file mode 100644 index 000000000000..1ba5a9413367 --- /dev/null +++ b/data-type-json.md @@ -0,0 +1,33 @@ +--- +title: JSON 类型 +category: reference +aliases: ['/docs-cn/stable/reference/sql/data-types/json/'] +--- + +# JSON 类型 + +> **警告:** +> +> 当前该功能为实验特性,不建议在生产环境中使用。 + +JSON 类型可以存储 JSON 这种半结构化的数据,相比于直接将 JSON 存储为字符串,它的好处在于: + +1. 使用 Binary 格式进行序列化,对 JSON 的内部字段的查询、解析加快; +2. 多了 JSON 合法性验证的步骤,只有合法的 JSON 文档才可以放入这个字段中; + +JSON 字段本身上,并不能创建索引。相反,可以对 JSON 文档中的某个子字段创建索引。例如: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE city ( + id INT PRIMARY KEY, + detail JSON, + population INT AS (JSON_EXTRACT(detail, '$.population')), + index index_name (population) +); +INSERT INTO city (id,detail) VALUES (1, '{"name": "Beijing", "population": 100}'); +SELECT id FROM city WHERE population >= 100; +``` + +有关 JSON 的更多信息,可以参考[JSON 函数](/functions-and-operators/json-functions.md)和[生成列](/generated-columns.md)。 diff --git a/data-type-numeric.md b/data-type-numeric.md new file mode 100644 index 000000000000..778a96ed6ab0 --- /dev/null +++ b/data-type-numeric.md @@ -0,0 +1,200 @@ +--- +title: 数值类型 +category: reference +aliases: ['/docs-cn/stable/reference/sql/data-types/numeric/'] +--- + +# 数值类型 + +TiDB 支持 MySQL 所有的数值类型,按照精度可以分为: + ++ [整数类型(精确值)](#整数类型) ++ [浮点类型(近似值)](#浮点类型) ++ [定点类型(精确值)](#定点类型) + +## 整数类型 + +TiDB 支持 MySQL 所有的整数类型,包括 `INTEGER`/`INT`、`TINYINT`、`SMALLINT`、`MEDIUMINT` 以及 `BIGINT`,完整信息参考[这篇](https://dev.mysql.com/doc/refman/5.7/en/numeric-type-overview.html)文档。 + +字段说明: + +| 语法元素 | 说明 | +| ---- | --------| +| M | 类型显示宽度,可选 | +| UNSIGNED | 无符号数,如果不加这个标识,则为有符号数 | +| ZEROFILL | 补零标识,如果有这个标识,TiDB 会自动给类型增加 UNSIGNED 标识,但是没有做补零的操作 | + +### 类型定义 + +#### `BIT` 类型 + +比特值类型。M 表示比特位的长度,取值范围从1到64,其默认值是1。 + +{{< copyable "sql" >}} + +```sql +BIT[(M)] +``` + +#### `BOOLEAN` 类型 + +布尔类型,别名为 `BOOL`,和 `TINYINT(1)` 等价。零值被认为是 `False`,非零值认为是 `True`。在 TiDB 内部,`True` 存储为 `1`,`False` 存储为 `0`。 + +{{< copyable "sql" >}} + +```sql +BOOLEAN +``` + +#### `TINYINT` 类型 + +`TINYINT` 类型。有符号数的范围是 `[-128, 127]`。无符号数的范围是 `[0, 255]`。 + +{{< copyable "sql" >}} + +```sql +TINYINT[(M)] [UNSIGNED] [ZEROFILL] +``` + +#### `SMALLINT` 类型 + +`SMALLINT` 类型。有符号数的范围是 `[-32768, 32767]`。无符号数的范围是 `[0, 65535]`。 + +{{< copyable "sql" >}} + +```sql +SMALLINT[(M)] [UNSIGNED] [ZEROFILL] +``` + +#### `MEDIUMINT` 类型 + +`MEDIUMINT` 类型。有符号数的范围是 `[-8388608, 8388607]`。无符号数的范围是 `[0, 16777215]`。 + +{{< copyable "sql" >}} + +```sql +MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] +``` + +### `INTEGER` 类型 + +`INTEGER` 类型,别名 `INT`。有符号数的范围是 `[-2147483648, 2147483647]`。无符号数的范围是 `[0, 4294967295]`。 + +{{< copyable "sql" >}} + +```sql +INT[(M)] [UNSIGNED] [ZEROFILL] +``` + +或者: + +{{< copyable "sql" >}} + +```sql +INTEGER[(M)] [UNSIGNED] [ZEROFILL] +``` + +### `BIGINT` 类型 + +`BIGINT` 类型。有符号数的范围是 `[-9223372036854775808, 9223372036854775807]`。无符号数的范围是 `[0, 18446744073709551615]`。 + +{{< copyable "sql" >}} + +```sql +BIGINT[(M)] [UNSIGNED] [ZEROFILL] +``` + +### 存储空间以及取值范围 + +每种类型对存储空间的需求以及最大/最小值如下表所示: + +| 类型 | 存储空间 | 最小值(有符号/无符号) | 最大值(有符号/无符号) | +| ----------- |----------|-----------------------| --------------------- | +| `TINYINT` | 1 | -128 / 0 | 127 / 255 | +| `SMALLINT` | 2 | -32768 / 0 | 32767 / 65535 | +| `MEDIUMINT` | 3 | -8388608 / 0 | 8388607 / 16777215 | +| `INT` | 4 | -2147483648 / 0 | 2147483647 / 4294967295 | +| `BIGINT` | 8 | -9223372036854775808 / 0 | 9223372036854775807 / 18446744073709551615 | + +## 浮点类型 + +TiDB 支持 MySQL 所有的浮点类型,包括 `FLOAT`、`DOUBLE`,完整信息参考[这篇](https://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html)文档。 + +字段说明: + +| 语法元素 | 说明 | +| -------- | ------------------------------- | +| M | 小数总位数 | +| D | 小数点后位数 | +| UNSIGNED | 无符号数,如果不加这个标识,则为有符号数 | +| ZEROFILL | 补零标识,如果有这个标识,TiDB 会自动给类型增加 UNSIGNED 标识 | + +### 类型定义 + +#### `FLOAT` 类型 + +单精度浮点数。允许的值范围为 -2^128 ~ +2^128,也即 -3.402823466E+38 到 -1.175494351E-38、0 和 1.175494351E-38 到 3.402823466E+38。这些是基于 IEEE 标准的理论限制。实际的范围根据硬件或操作系统的不同可能稍微小些。 + +`FLOAT(p)` 类型中,`p` 表示精度(以位数表示)。只使用该值来确定是否结果列的数据类型为 `FLOAT` 或 `DOUBLE`。如果 `p` 为从 0 到 24,数据类型变为没有 M 或 D 值的 `FLOAT`。如果 `p` 为从 25 到 53,数据类型变为没有 M 或 D 值的 `DOUBLE`。结果列范围与本节前面描述的单精度 `FLOAT` 或双精度 `DOUBLE` 数据类型相同。 + +{{< copyable "sql" >}} + +```sql +FLOAT[(M,D)] [UNSIGNED] [ZEROFILL] +FLOAT(p) [UNSIGNED] [ZEROFILL] +``` + +> **警告:** +> +> 与在 MySQL 中一样,`FLOAT` 数据类型存储近似值。对于货币之类的精确值,建议使用 `DECIMAL` 类型。 + +#### `DOUBLE` 类型 + +双精度浮点数,别名为 `DOUBLE PRECISION`。允许的值范围为:-2^1024 ~ +2^1024,也即是 -1.7976931348623157E+308 到 -2.2250738585072014E-308、0 和 2.2250738585072014E-308 到 1.7976931348623157E+308。这些是基于 IEEE 标准的理论限制。实际的范围根据硬件或操作系统的不同可能稍微小些。 + +{{< copyable "sql" >}} + +```sql +DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL] +DOUBLE PRECISION [(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL] +``` + +> **警告:** +> +> 与在 MySQL 中一样,`DOUBLE` 数据类型存储近似值。对于货币之类的精确值,建议使用 `DECIMAL` 类型。 + +### 存储空间 + +每种类型对存储空间的需求如下表所示: + +| 类型 | 存储空间 | +| ----------- |----------| +| `FLOAT` | 4 | +| `FLOAT(p)` | 如果 0 <= p <= 24 为 4 个字节, 如果 25 <= p <= 53 为 8 个字节| +| `DOUBLE` | 8 | + +## 定点类型 + +TiDB 支持 MySQL 所有的定点类型,包括 `DECIMAL`、`NUMERIC`,完整信息参考[这篇](https://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.html)文档。 + +字段说明: + +| 语法元素 | 说明 | +| -------- | ------------------------------- | +| M | 小数总位数 | +| D | 小数点后位数 | +| UNSIGNED | 无符号数,如果不加这个标识,则为有符号数 | +| ZEROFILL | 补零标识,如果有这个标识,TiDB 会自动给类型增加 UNSIGNED 标识 | + +### 类型定义 + +#### `DECIMAL` 类型 + +定点数,别名为 `NUMERIC`。M 是小数位数(精度)的总数,D 是小数点(标度)后面的位数。小数点和 `-`(负数)符号不包括在 M 中。如果 D 是 0,则值没有小数点或分数部分。如果 D 被省略,默认是 0。如果 M 被省略,默认是 10。 + +{{< copyable "sql" >}} + +```sql +DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL] +NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL] +``` diff --git a/data-type-overview.md b/data-type-overview.md new file mode 100644 index 000000000000..a89bed5c671d --- /dev/null +++ b/data-type-overview.md @@ -0,0 +1,16 @@ +--- +title: 数据类型概述 +category: reference +aliases: ['/docs-cn/stable/reference/sql/data-types/overview/'] +--- + +# 数据类型概述 + +TiDB 支持除空间类型 (`SPATIAL`) 之外的所有 MySQL 数据类型,包括[数值型类型](/data-type-numeric.md)、[字符串类型](/data-type-string.md)、[时间和日期类型](/data-type-date-and-time.md)、[JSON 类型](/data-type-json.md)。 + +数据类型定义一般为 `T(M[, D])`,其中: + +* `T` 表示具体的类型。 +* `M` 在整数类型中表示最大显示长度;在浮点数或者定点数中表示精度;在字符类型中表示最大长度。`M` 的最大值取决于具体的类型。 +* `D` 表示浮点数、定点数的小数位长度。 +* `fsp` 在时间和日期类型里的 `TIME`、`DATETIME` 以及 `TIMESTAMP` 中表示秒的精度,其取值范围是 0 到 6。值为 0 表示没有小数部分。如果省略,则默认精度为 0。 diff --git a/data-type-string.md b/data-type-string.md new file mode 100644 index 000000000000..821b74dff565 --- /dev/null +++ b/data-type-string.md @@ -0,0 +1,211 @@ +--- +title: 字符串类型 +category: reference +aliases: ['/docs-cn/stable/reference/sql/data-types/string/'] +--- + +# 字符串类型 + +TiDB 支持 MySQL 所有的字符串类型,包括 `CHAR`、`VARCHAR`、`BINARY`、`VARBINARY`、`BLOB`、`TEXT`、`ENUM` 以及 `SET`,完整信息参考[这篇](https://dev.mysql.com/doc/refman/5.7/en/string-types.html)文档。 + +## 类型定义 + +### `CHAR` 类型 + +定长字符串。`CHAR` 列的长度固定为创建表时声明的长度。当保存 CHAR 值时,不足固定长度的字符串在后面填充空格,以达到指定的长度。M 表示列长度(字符的个数,不是字节的个数)。长度可以为从 0 到 255 的任何值。 + +{{< copyable "sql" >}} + +```sql +[NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE collation_name] +``` + +### `VARCHAR` 类型 + +变长字符串。M 表示最大列长度(字符的最大个数)。`VARCHAR` 的空间占用大小不得超过 65535 字节。在选择 `VARCHAR` 长度时,应当根据最长的行的大小和使用的字符集确定。 + +对于不同的字符集,单个字符所占用的空间可能有所不同。以下表格是各个字符集下单个字符占用的字节数,以及 `VARCHAR` 列长度的取值范围: + +| 字符集 | 单个字符字节数 | VARCHAR 最大列长度的取值范围 | +| ----- | ---- | ---- | +| ascii | 1 | (0, 65535] | +| latin1 | 1 | (0, 65535] | +| binary | 1 | (0, 65535] | +| utf8 | 3 | (0, 21845] | +| utf8mb4 | 4 | (0, 16383] | + +{{< copyable "sql" >}} + +```sql +[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name] +``` + +### `TEXT` 类型 + +文本串。M 表示最大列长度(字符的最大个数),范围是 0 到 65535。在选择 `TEXT` 长度时,应当根据最长的行的大小和使用的字符集确定。 + +{{< copyable "sql" >}} + +```sql +TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name] +``` + +### `TINYTEXT` 类型 + +类似于 [`TEXT`](#text-类型),区别在于最大列长度为 255。 + +{{< copyable "sql" >}} + +```sql +TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name] +``` + +### `MEDIUMTEXT` 类型 + +类似于 [`TEXT`](#text-类型),区别在于最大列长度为 16,777,215。 + +{{< copyable "sql" >}} + +```sql +MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name] +``` + +### `LONGTEXT` 类型 + +类似于 [`TEXT`](#text-类型),区别在于最大列长度为 4,294,967,295。 + +{{< copyable "sql" >}} + +```sql +LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name] +``` + +### `BINARY` 类型 + +类似于 [`CHAR`](#char-类型),区别在于 `BINARY` 存储的是二进制字符串。 + +{{< copyable "sql" >}} + +```sql +BINARY(M) +``` + +### `VARBINARY` 类型 + +类似于 [`VARCHAR`](#varchar-类型),区别在于 `VARBINARY` 存储的是二进制字符串。 + +{{< copyable "sql" >}} + +```sql +VARBINARY(M) +``` + +### `BLOB` 类型 + +二进制大文件。M 表示最大列长度,单位是字节,范围是 0 到 65535。 + +{{< copyable "sql" >}} + +```sql +BLOB[(M)] +``` + +### `TINYBLOB` 类型 + +类似于 [`BLOB`](#blob-类型),区别在于最大列长度为 255。 + +{{< copyable "sql" >}} + +```sql +TINYBLOB +``` + +### `MEDIUMBLOB` 类型 + +类似于 [`BLOB`](#blob-类型),区别在于最大列长度为 16777215。 + +{{< copyable "sql" >}} + +```sql +MEDIUMBLOB +``` + +### `LONGBLOB` 类型 + +类似于 [`BLOB`](#blob-类型),区别在于最大列长度为 4,294,967,295。 + +{{< copyable "sql" >}} + +```sql +LONGBLOB +``` + +### `ENUM` 类型 + +枚举类型是一个字符串,它只能有一个值的字符串对象。其值必须是从一个固定集合中选取,这个固定集合在创建表的时候定义,语法是: + +{{< copyable "sql" >}} + +```sql +ENUM('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name] +``` + +例如: + +{{< copyable "sql" >}} + +```sql +ENUM('apple', 'orange', 'pear') +``` + +枚举类型的值在 TiDB 内部使用数值来存储,每个值会按照定义的顺序转换为一个数字,比如上面的例子中,每个字符串值都会映射为一个数字: + +| 值 | 数字 | +| ---- | ---- | +| NULL | NULL | +| '' | 0 | +| 'apple' | 1 | +| 'orange' | 2 | +| 'pear' | 3 | + +更多信息参考 [MySQL 枚举文档](https://dev.mysql.com/doc/refman/5.7/en/enum.html)。 + +### `SET` 类型 + +集合类型是一个包含零个或多个值的字符串,其中每个值必须是从一个固定集合中选取,这个固定集合在创建表的时候定义,语法是: + +{{< copyable "sql" >}} + +```sql +SET('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name] +``` + +例如: + +{{< copyable "sql" >}} + +```sql +SET('1', '2') NOT NULL +``` + +上面的例子中,这列的有效值可以是: + +``` +'' +'1' +'2' +'1,2' +``` + +集合类型的值在 TiDB 内部会转换为一个 Int64 数值,每个元素是否存在用一个二进制位的 0/1 值来表示,比如这个例子 `SET('a','b','c','d')`,每一个元素都被映射为一个数字,且每个数字的二进制表示只会有一位是 1: + +| 成员 | 十进制表示 | 二进制表示 | +| ---- | ---- | ------ | +| 'a' | 1 | 0001 | +| 'b' | 2 | 0010 | +| 'c' | 4 | 0100 | +| 'd' | 8 | 1000 | + +这样对于值为 `('a', 'c')` 的元素,其二进制表示即为 0101。 + +更多信息参考 [MySQL 集合文档](https://dev.mysql.com/doc/refman/5.7/en/set.html)。 diff --git a/deploy-monitoring-services.md b/deploy-monitoring-services.md new file mode 100644 index 000000000000..75831b6025e6 --- /dev/null +++ b/deploy-monitoring-services.md @@ -0,0 +1,275 @@ +--- +title: 集群监控部署 +category: how-to +aliases: ['/docs-cn/stable/monitor-a-tidb-cluster/','/docs-cn/stable/how-to/monitor/monitor-a-cluster/'] +--- + +# TiDB 集群监控部署 + +本文档适用于希望手动部署 TiDB 监控报警系统的用户。TiUP 部署方式,会同时自动部署监控报警系统,无需手动部署。 + +## 部署 Prometheus 和 Grafana + +假设 TiDB 的拓扑结构如下: + +| 节点 | 主机 IP | 服务 | +| :-- | :-- | :-------------- | +| Node1 | 192.168.199.113| PD1, TiDB, node_export, Prometheus, Grafana | +| Node2 | 192.168.199.114| PD2, node_export | +| Node3 | 192.168.199.115| PD3, node_export | +| Node4 | 192.168.199.116| TiKV1, node_export | +| Node5 | 192.168.199.117| TiKV2, node_export | +| Node6 | 192.168.199.118| TiKV3, node_export | + +### 第 1 步:下载二进制包 + +下载二进制包: + +{{< copyable "shell-regular" >}} + +```bash +wget https://download.pingcap.org/prometheus-2.8.1.linux-amd64.tar.gz +wget https://download.pingcap.org/node_exporter-0.17.0.linux-amd64.tar.gz +wget https://download.pingcap.org/grafana-6.1.6.linux-amd64.tar.gz +``` + +解压二进制包: + +{{< copyable "shell-regular" >}} + +```bash +tar -xzf prometheus-2.8.1.linux-amd64.tar.gz +tar -xzf node_exporter-0.17.0.linux-amd64.tar.gz +tar -xzf grafana-6.1.6.linux-amd64.tar.gz +``` + +### 第 2 步:在 Node1,Node2,Node3,Node4 上启动 `node_exporter` + +{{< copyable "shell-regular" >}} + +```bash +cd node_exporter-0.17.0.linux-amd64 +``` + +启动 node_exporter 服务: + +{{< copyable "shell-regular" >}} + +```bash +./node_exporter --web.listen-address=":9100" \ + --log.level="info" & +``` + +### 第 3 步:在 Node1 上启动 Prometheus + +编辑 Prometheus 的配置文件: + +{{< copyable "shell-regular" >}} + +```bash +cd prometheus-2.8.1.linux-amd64 && +vi prometheus.yml +``` + +```ini +... + +global: + scrape_interval: 15s + evaluation_interval: 15s + # scrape_timeout 设置为全局默认值 (10s) + external_labels: + cluster: 'test-cluster' + monitor: "prometheus" + +scrape_configs: + - job_name: 'overwritten-nodes' + honor_labels: true # 不要覆盖 job 和实例的 label + static_configs: + - targets: + - '192.168.199.113:9100' + - '192.168.199.114:9100' + - '192.168.199.115:9100' + - '192.168.199.116:9100' + - '192.168.199.117:9100' + - '192.168.199.118:9100' + + - job_name: 'tidb' + honor_labels: true # 不要覆盖 job 和实例的 label + static_configs: + - targets: + - '192.168.199.113:10080' + + - job_name: 'pd' + honor_labels: true # 不要覆盖 job 和实例的 label + static_configs: + - targets: + - '192.168.199.113:2379' + - '192.168.199.114:2379' + - '192.168.199.115:2379' + + - job_name: 'tikv' + honor_labels: true # 不要覆盖 job 和实例的 label + static_configs: + - targets: + - '192.168.199.116:20180' + - '192.168.199.117:20180' + - '192.168.199.118:20180' + +... +``` + +启动 Prometheus 服务: + +{{< copyable "shell-regular" >}} + +```bash +./prometheus \ + --config.file="./prometheus.yml" \ + --web.listen-address=":9090" \ + --web.external-url="http://192.168.199.113:9090/" \ + --web.enable-admin-api \ + --log.level="info" \ + --storage.tsdb.path="./data.metrics" \ + --storage.tsdb.retention="15d" & +``` + +### 第 4 步:在 Node1 上启动 Grafana + +编辑 Grafana 的配置文件: + +```bash +cd grafana-6.1.6 && +vi conf/grafana.ini +``` + +```ini +... + +[paths] +data = ./data +logs = ./data/log +plugins = ./data/plugins +[server] +http_port = 3000 +domain = 192.168.199.113 +[database] +[session] +[analytics] +check_for_updates = true +[security] +admin_user = admin +admin_password = admin +[snapshots] +[users] +[auth.anonymous] +[auth.basic] +[auth.ldap] +[smtp] +[emails] +[log] +mode = file +[log.console] +[log.file] +level = info +format = text +[log.syslog] +[event_publisher] +[dashboards.json] +enabled = false +path = ./data/dashboards +[metrics] +[grafana_net] +url = https://grafana.net + +... + +``` + +启动 Grafana 服务: + +{{< copyable "shell-regular" >}} + +```bash +./bin/grafana-server \ + --config="./conf/grafana.ini" & +``` + +## 配置 Grafana + +本小节介绍如何配置 Grafana。 + +### 第 1 步:添加 Prometheus 数据源 + +1. 登录 Grafana 界面。 + + - 默认地址:`http://localhost:3000` + - 默认账户:admin + - 默认密码:admin + + > **注意:** + > + > **Change Password** 步骤可以选择 **Skip**。 + +2. 点击 Grafana 侧边栏菜单 **Configuration** 中的 **Data Source**。 + +3. 点击 **Add data source**。 + +4. 指定数据源的相关信息: + + - 在 **Name** 处,为数据源指定一个名称。 + - 在 **Type** 处,选择 **Prometheus**。 + - 在 **URL** 处,指定 Prometheus 的 IP 地址。 + - 根据需求指定其它字段。 + +5. 点击 **Add** 保存新的数据源。 + +### 第 2 步:导入 Grafana 面板 + +执行以下步骤,为 PD Server、TiKV Server 和 TiDB Server 分别导入 Grafana 面板: + +1. 点击侧边栏的 Grafana 图标。 + +2. 在侧边栏菜单中,依次点击 **Dashboards** > **Import** 打开 **Import Dashboard** 窗口。 + +3. 点击 **Upload .json File** 上传对应的 JSON 文件(下载 [TiDB Grafana 配置文件](https://github.com/pingcap/tidb-ansible/tree/master/scripts))。 + + > **注意:** + > + > TiKV、PD 和 TiDB 面板对应的 JSON 文件分别为 `tikv_summary.json`,`tikv_details.json`,`tikv_trouble_shooting.json`,`pd.json`,`tidb.json`,`tidb_summary.json`。 + +4. 点击 **Load**。 + +5. 选择一个 Prometheus 数据源。 + +6. 点击 **Import**,Prometheus 面板即导入成功。 + +## 查看组件 metrics + +在顶部菜单中,点击 **New dashboard**,选择要查看的面板。 + +![view dashboard](/media/view-dashboard.png) + +可查看以下集群组件信息: + ++ **TiDB Server:** + + query 处理时间,可以看到延迟和吞吐 + + ddl 过程监控 + + TiKV client 相关的监控 + + PD client 相关的监控 + ++ **PD Server:** + + 命令执行的总次数 + + 某个命令执行失败的总次数 + + 某个命令执行成功的耗时统计 + + 某个命令执行失败的耗时统计 + + 某个命令执行完成并返回结果的耗时统计 + ++ **TiKV Server:** + + GC 监控 + + 执行 KV 命令的总次数 + + Scheduler 执行命令的耗时统计 + + Raft propose 命令的总次数 + + Raft 执行命令的耗时统计 + + Raft 执行命令失败的总次数 + + Raft 处理 ready 状态的总次数 diff --git a/deploy-test-cluster-using-docker-compose.md b/deploy-test-cluster-using-docker-compose.md new file mode 100644 index 000000000000..16ae7d9564de --- /dev/null +++ b/deploy-test-cluster-using-docker-compose.md @@ -0,0 +1,207 @@ +--- +title: 使用 Docker Compose 快速构建 TiDB 集群 +category: how-to +aliases: ['/docs-cn/stable/how-to/get-started/deploy-tidb-from-docker-compose/'] +--- + +# 使用 Docker Compose 快速构建 TiDB 集群 + +> **警告:** +> +> 本文提供的 Docker Compose 部署方案已停止维护。如果只是为了测试 TiDB,推荐参考[TiDB 数据库快速上手指南](/quick-start-with-tidb.md)进行部署。对于**生产环境**,不要使用 Docker Compose 进行部署,而应[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)。 + +本文档介绍如何在单机上通过 Docker Compose 快速一键部署一套 TiDB 测试集群。[Docker Compose](https://docs.docker.com/compose/overview) 可以通过一个 YAML 文件定义多个容器的应用服务,然后一键启动或停止。 + +## 准备环境 + +确保你的机器上已安装: + +- Docker(17.06.0 及以上版本) +- Docker Compose +- Git + +## 快速部署 + +1. 下载 `tidb-docker-compose` + + {{< copyable "shell-regular" >}} + + ```bash + git clone https://github.com/pingcap/tidb-docker-compose.git + ``` + +2. 创建并启动集群 + + 获取最新 Docker 镜像: + + {{< copyable "shell-regular" >}} + + ```bash + cd tidb-docker-compose && docker-compose pull && docker-compose up -d + ``` + +3. 访问集群 + + {{< copyable "shell-regular" >}} + + ```bash + mysql -h 127.0.0.1 -P 4000 -u root + ``` + + 访问集群 Grafana 监控页面: 默认用户名和密码均为 admin。 + + [集群数据可视化](https://github.com/pingcap/tidb-vision): + +## 自定义集群 + +在完成快速部署后,以下组件已默认部署:3 个 PD,3 个 TiKV,1 个 TiDB 和监控组件 Prometheus,Pushgateway,Grafana 以及 tidb-vision。 + +如果想自定义集群,可以直接修改 `docker-compose.yml`,但是手动修改比较繁琐而且容易出错,强烈建议使用 [Helm](https://helm.sh) 模板引擎生成 `docker-compose.yml` 文件。 + +1. 安装 Helm + + [Helm](https://helm.sh) 可以用作模板渲染引擎,只需要下载其 binary 文件即可以使用。确保你的 Helm 版本为 2.9.0 ≤ Helm < 3.0.0。 + + {{< copyable "shell-regular" >}} + + ```bash + curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash + ``` + + 如果是 Mac 系统,也可以通过 Homebrew 安装: + + {{< copyable "shell-regular" >}} + + ```bash + brew install helm@2 + brew link --force helm@2 + ``` + +2. 下载 `tidb-docker-compose` + + {{< copyable "shell-regular" >}} + + ```bash + git clone https://github.com/pingcap/tidb-docker-compose.git + ``` + +3. 自定义集群 + + {{< copyable "shell-regular" >}} + + ```bash + cd tidb-docker-compose && + cp compose/values.yaml values.yaml && + vim values.yaml + ``` + + 修改 `values.yaml` 里面的配置,例如集群规模,TiDB 镜像版本等。 + + [tidb-vision](https://github.com/pingcap/tidb-vision) 是 TiDB 集群可视化页面,可以可视化地显示 PD 对 TiKV 数据的调度。如果不想部署该组件,可以将 `tidbVision` 项留空。 + + PD,TiKV,TiDB 和 tidb-vision 支持从 GitHub 源码或本地文件构建 Docker 镜像,供开发测试使用。 + + - 如果希望从本地已编译好的 binary 文件构建 PD,TiKV 或 TiDB 镜像,需要将其 `image` 字段留空,并将已编译好的 binary 拷贝到对应的 `pd/bin/pd-server`,`tikv/bin/tikv-server`,`tidb/bin/tidb-server`。 + + - 如果希望从本地构建 tidb-vision 镜像,需要将其 `image` 字段留空,并将 tidb-vision 项目拷贝到 `tidb-vision/tidb-vision`。 + +4. 生成 `docker-compose.yml` 文件 + + {{< copyable "shell-regular" >}} + + ```bash + helm template -f values.yaml compose > generated-docker-compose.yml + ``` + +5. 使用生成的 `docker-compose.yml` 创建并启动集群 + + 获取最新 Docker 镜像: + + {{< copyable "shell-regular" >}} + + ```bash + docker-compose -f generated-docker-compose.yml pull + ``` + + {{< copyable "shell-regular" >}} + + ```bash + docker-compose -f generated-docker-compose.yml up -d + ``` + +6. 访问集群 + + {{< copyable "shell-regular" >}} + + ```bash + mysql -h 127.0.0.1 -P 4000 -u root + ``` + + 访问集群 Grafana 监控页面: 默认用户名和密码均为 admin。 + + 如果启用了 tidb-vision,可以通过 查看。 + +## 访问 Spark shell 并加载 TiSpark + +向 TiDB 集群中插入一些样本数据: + +{{< copyable "shell-regular" >}} + +```bash +docker-compose exec tispark-master bash && +cd /opt/spark/data/tispark-sample-data && +mysql -h tidb -P 4000 -u root < dss.ddl +``` + +当样本数据加载到 TiDB 集群之后,可以使用 `docker-compose exec tispark-master /opt/spark/bin/spark-shell` 来访问 Spark shell。 + +{{< copyable "shell-regular" >}} + +```bash +docker-compose exec tispark-master /opt/spark/bin/spark-shell +``` + +``` +... +Spark context available as 'sc' (master = local[*], app id = local-1527045927617). +Spark session available as 'spark'. +Welcome to + ____ __ + / __/__ ___ _____/ /__ + _\ \/ _ \/ _ `/ __/ '_/ + /___/ .__/\_,_/_/ /_/\_\ version 2.1.1 + /_/ + +Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_172) +Type in expressions to have them evaluated. +Type :help for more information. +``` + +```shell +scala> import org.apache.spark.sql.TiContext +... +scala> val ti = new TiContext(spark) +... +scala> ti.tidbMapDatabase("TPCH_001") +... +scala> spark.sql("select count(*) from lineitem").show +``` + +``` ++--------+ +|count(1)| ++--------+ +| 60175| ++--------+ +``` + +你也可以通过 Python 或 R 来访问 Spark: + +{{< copyable "shell-regular" >}} + +```bash +docker-compose exec tispark-master /opt/spark/bin/pyspark && +docker-compose exec tispark-master /opt/spark/bin/sparkR +``` + +更多关于 TiSpark 的信息,参见 [TiSpark 的详细文档](/get-started-with-tispark.md)。 diff --git a/differences-from-standard-sql.md b/differences-from-standard-sql.md new file mode 100644 index 000000000000..4140a0571267 --- /dev/null +++ b/differences-from-standard-sql.md @@ -0,0 +1,3 @@ +--- +draft: true +--- \ No newline at end of file diff --git a/download-ecosystem-tools.md b/download-ecosystem-tools.md new file mode 100644 index 000000000000..959e48ed28ac --- /dev/null +++ b/download-ecosystem-tools.md @@ -0,0 +1,76 @@ +--- +title: TiDB 工具下载 +category: reference +aliases: ['/docs-cn/stable/reference/tools/download/'] +--- + +# TiDB 工具下载 + +本页面汇总了 TiDB 周边工具官方维护版本的下载链接。 + +## TiDB Binlog + +如需下载最新版本的 [TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md),直接下载 TiDB 安装包即可,因为 TiDB Binlog 包含在 TiDB 安装包中。 + +以下表格中也提供了 Kafka 版本的 TiDB Binlog 下载链接。 + +| 安装包 | 操作系统 | 架构 | SHA256 校验和 | +|:---|:---|:---|:---| +| `https://download.pingcap.org/tidb-{version}-linux-amd64.tar.gz` (TiDB Binlog) | Linux | amd64 | `https://download.pingcap.org/tidb-{version}-linux-amd64.sha256` | +| `https://download.pingcap.org/tidb-binlog-kafka-linux-amd64.tar.gz`(Kafka 版本的 TiDB Binlog)| Linux | amd64 | `https://download.pingcap.org/tidb-binlog-kafka-linux-amd64.sha256` | + +> **注意:** +> +> 下载链接中的 `{version}` 为 TiDB 的版本号。例如,`v3.0.5` 版本的下载链接为 `https://download.pingcap.org/tidb-v3.0.5-linux-amd64.tar.gz`。 + +## TiDB Lightning + +使用下表中的链接下载 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md): + +| 安装包 | 操作系统 | 架构 | SHA256 校验和 | +|:---|:---|:---|:---| +| `https://download.pingcap.org/tidb-toolkit-{version}-linux-amd64.tar.gz` | Linux | amd64 | `https://download.pingcap.org/tidb-toolkit-{version}-linux-amd64.sha256` | + +> **注意:** +> +> 下载链接中的 `{version}` 为 TiDB Lightning 的版本号。例如,`v3.0.5` 版本的下载链接为 `https://download.pingcap.org/tidb-toolkit-v3.0.5-linux-amd64.tar.gz`。 + +## 快速备份和恢复(BR) + +使用下表中的链接下载 [快速备份和恢复(BR)](/br/backup-and-restore-tool.md): + +| 安装包 | 操作系统 | 架构 | SHA256 校验和 | +|:---|:---|:---|:---| +| `https://download.pingcap.org/tidb-toolkit-{version}-linux-amd64.tar.gz` | Linux | amd64 | `https://download.pingcap.org/tidb-toolkit-{version}-linux-amd64.sha256` | + +> **注意:** +> +> 下载链接中的 `{version}` 为 BR 的版本号。例如,`v3.1.0-beta` 版本的下载链接为 `https://download.pingcap.org/tidb-toolkit-v3.1.0-beta-linux-amd64.tar.gz`。 + +## TiDB DM (Data Migration) + +使用下表中的链接下载 [DM](https://pingcap.com/docs-cn/tidb-data-migration/stable/overview/): + +| 安装包 | 操作系统 | 架构 | SHA256 校验和 | +|:---|:---|:---|:---| +| `https://download.pingcap.org/dm-{version}-linux-amd64.tar.gz` | Linux | amd64 | `https://download.pingcap.org/dm-{version}-linux-amd64.sha256` | + +> **注意:** +> +> 下载链接中的 `{version}` 为 DM 的版本号。例如,`v1.0.1` 版本的下载链接为 `https://download.pingcap.org/dm-v1.0.1-linux-amd64.tar.gz`。可以通过 [DM Release](https://github.com/pingcap/dm/releases) 查看当前已发布版本。 + +## Syncer,Loader 和 Mydumper + +如需下载最新版本的 [Syncer](/syncer-overview.md),[Loader](/loader-overview.md) 或 [Mydumper](/mydumper-overview.md),直接下载 tidb-enterprise-tools 安装包即可,因为这些工具均包含在此安装包中。 + +| 安装包 | 操作系统 | 架构 | SHA256 校验和 | +|:---|:---|:---|:---| +| [tidb-enterprise-tools-nightly-linux-amd64.tar.gz](https://download.pingcap.org/tidb-enterprise-tools-nightly-linux-amd64.tar.gz) | Linux | amd64 | [tidb-enterprise-tools-nightly-linux-amd64.sha256](https://download.pingcap.org/tidb-enterprise-tools-nightly-linux-amd64.sha256) | + +tidb-enterprise-tools 安装包包含以下工具: + +- Syncer +- Loader +- Mydumper +- ddl_checker +- [sync-diff-inspector](/sync-diff-inspector/sync-diff-inspector-overview.md) diff --git a/ecosystem-tool-user-case.md b/ecosystem-tool-user-case.md new file mode 100644 index 000000000000..02da680343fc --- /dev/null +++ b/ecosystem-tool-user-case.md @@ -0,0 +1,39 @@ +--- +title: TiDB 生态工具适用场景 +category: reference +summary: 本文档介绍 TiDB 生态工具的常见适用场景与工具选择。 +--- + +# TiDB 生态工具适用场景 + +本文档从生态工具的适用场景出发,介绍部分常见场景下的生态工具选择。 + +## 从 CSV 导入数据到 TiDB + +当需要将其他工具导出的格式兼容的 CSV files 导入到 TiDB 时,可使用 [TiDB Lightning](/tidb-lightning/migrate-from-csv-using-tidb-lightning.md)。 + +## 从 MySQL/Aurora 导入全量数据 + +当需要从 MySQL/Aurora 导入全量数据时,可先使用 [Dumpling](/export-or-backup-using-dumpling.md) 将数据导出为 SQL dump files,然后再使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 将数据导入到 TiDB 集群。 + +## 从 MySQL/Aurora 迁移数据 + +当既需要从 MySQL/Aurora 导入全量数据,又需要迁移增量数据时,可使用 [TiDB Data Migration (DM)](https://pingcap.com/docs-cn/tidb-data-migration/stable/overview/) 完成全量数据和增量数据的迁移。 + +如果全量数据量较大(TB 级别),则可先使用 [Dumpling](/export-or-backup-using-dumpling.md) 与 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 完成全量数据的迁移,再使用 DM 完成增量数据的迁移。 + +## TiDB 集群备份与恢复 + +当需要对 TiDB 集群进行备份或在之后对 TiDB 集群进行恢复时,可使用 [BR](/br/backup-and-restore-tool.md)。 + +另外,BR 也可以对 TiDB 的数据进行[增量备份](/br/backup-and-restore-tool.md#增量备份)和[增量恢复](/br/backup-and-restore-tool.md#增量恢复)。 + +## 迁出数据到 MySQL/TiDB + +当需要将 TiDB 集群的数据迁出到 MySQL 或其他 TiDB 集群时,可使用 [Dumpling](/export-or-backup-using-dumpling.md) 从 TiDB 将全量数据导出为 SQL dump files,然后再使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 将数据导入到 MySQL/TiDB。 + +如果还需要执行增量数据的迁移,则可使用 [TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md)。 + +## TiDB 增量数据订阅 + +当需要订阅 TiDB 增量数据的变更时,可使用 [TiDB Binlog](/tidb-binlog/binlog-slave-client.md)。 diff --git a/ecosystem-tool-user-guide.md b/ecosystem-tool-user-guide.md new file mode 100644 index 000000000000..f7a04f1d5f1f --- /dev/null +++ b/ecosystem-tool-user-guide.md @@ -0,0 +1,85 @@ +--- +title: TiDB 生态工具功能概览 +category: reference +aliases: ['/docs-cn/stable/reference/tools/user-guide/'] +--- + +# TiDB 生态工具功能概览 + +本文档从生态工具的功能出发,介绍部分生态工具的功能以及它们之间的替代关系。 + +## 全量导出 + +[Dumpling](/export-or-backup-using-dumpling.md) 是一个用于从 MySQL/TiDB 进行全量逻辑导出的工具。 + +基本信息: + +- Dumpling 的输入:MySQL/TiDB 集群 +- Dumpling 的输出:SQL/CSV 文件 +- 适用 TiDB 版本:所有版本 +- Kubernetes 支持:尚未支持 + +## 全量导入 + +[TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 是一个用于将全量数据导入到 TiDB 集群的工具。 + +使用 TiDB Lightning 导入数据到 TiDB 时,有两种模式: + +- `importer` 模式:以 TiKV-importer 作为后端,这种模式一般用于导入大量的数据(TB 级别)到新集群,但在数据导入过程中集群无法提供正常的服务。 +- `tidb` 模式:以 TiDB/MySQL 作为后端,这种模式相比 `importer` 模式的导入速度较慢,但是可以在线导入,同时也支持将数据导入到 MySQL。 + +基本信息: + +- Lightning 的输入: + - Dumpling 输出文件 + - 其他格式兼容的 CSV 文件 +- 适用 TiDB 版本:v2.1 及以上 +- Kubernetes 支持:[使用 TiDB Lightning 快速恢复 Kubernetes 上的 TiDB 集群数据](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/restore-data-using-tidb-lightning/) + +> **注意:** +> +> 原 Loader 工具已停止维护,不再推荐使用。相关场景请使用 TiDB Lightning 的 `tidb` 模式进行替代,详细信息请参考 [TiDB Lightning TiDB-backend 文档](/tidb-lightning/tidb-lightning-tidb-backend.md#从-loader-迁移到-tidb-lightning-tidb-backend)。 + +## 备份和恢复 + +[BR](/br/backup-and-restore-tool.md) 是一个对 TiDB 进行分布式备份和恢复的工具,可以高效地对大数据量的 TiDB 集群进行数据备份和恢复。 + +基本信息: + +- [备份输出和恢复输入的文件类型](/br/backup-and-restore-tool.md#备份文件类型):SST + `backupmeta` 文件 +- 适用 TiDB 版本:v3.1 及 v4.0 +- Kubernetes 支持:[使用 BR 工具备份 TiDB 集群数据到兼容 S3 的存储](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/backup-to-aws-s3-using-br/), [使用 BR 工具恢复 S3 兼容存储上的备份数据](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/restore-from-aws-s3-using-br/) + +## TiDB 增量日志同步 + +[TiDB Binlog](/tidb-binlog/tidb-binlog-overview.md) 是收集 TiDB 的增量 binlog 数据,并提供准实时同步和备份的工具。该工具可用于 TiDB 集群间的增量数据同步,如将其中一个 TiDB 集群作为另一个 TiDB 集群的从集群。 + +基本信息: + +- TiDB Binlog 的输入:TiDB 集群 +- TiDB Binlog 的输出:TiDB 集群、MySQL、Kafka 或者增量备份文件 +- 适用 TiDB 版本:v2.1 及以上 +- Kubernetes 支持:[TiDB Binlog 运维文档](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-tidb-binlog/),[Kubernetes 上的 TiDB Binlog Drainer 配置](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/configure-tidb-binlog-drainer/) + +## 数据迁入 + +[TiDB Data Migration (DM)](https://pingcap.com/docs-cn/tidb-data-migration/stable/overview/) 是将 MySQL/MariaDB 数据迁移到 TiDB 的工具,支持全量数据和增量数据的迁移。 + +基本信息: + +- DM 的输入:MySQL/MariaDB +- DM 的输出:TiDB 集群 +- 适用 TiDB 版本:所有版本 +- Kubernetes 支持:开发中 + +如果数据量在 TB 级别以下,推荐直接使用 DM 迁移 MySQL/MariaDB 数据到 TiDB(迁移的过程包括全量数据的导出导入和增量数据的同步)。 + +如果数据量在 TB 级别,推荐的迁移步骤如下: + +1. 使用 [Dumpling](/export-or-backup-using-dumpling.md) 导出 MySQL/MariaDB 全量数据。 +2. 使用 [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md) 将全量导出数据导入 TiDB 集群。 +3. 使用 DM 迁移 MySQL/MariaDB 增量数据到 TiDB。 + +> **注意:** +> +> - 原 Syncer 工具已停止维护,不再推荐使用,相关场景请使用 DM 的增量迁移模式进行替代。 diff --git a/enable-tls-between-clients-and-servers.md b/enable-tls-between-clients-and-servers.md new file mode 100644 index 000000000000..dd531bd2b008 --- /dev/null +++ b/enable-tls-between-clients-and-servers.md @@ -0,0 +1,183 @@ +--- +title: 为 TiDB 客户端服务端间通信开启加密传输 +category: how-to +aliases: ['/docs-cn/stable/how-to/secure/enable-tls-clients/','/docs-cn/stable/encrypted-connections-with-tls-protocols/','/docs-cn/stable/enable-tls-between-clients/'] +--- + +# 为 TiDB 客户端服务端间通信开启加密传输 + +TiDB 服务端与客户端之间默认采用非加密连接,因而具备监视信道流量能力的第三方可以知悉 TiDB 服务端与客户端之间发送和接受的数据,包括但不限于查询语句内容、查询结果等。若信道是不可信的,例如客户端是通过公网连接到 TiDB 服务端的,则非加密连接容易造成信息泄露,建议使用加密连接确保安全性。 + +TiDB 服务端支持启用基于 TLS(传输层安全)协议的加密连接,协议与 MySQL 加密连接一致,现有 MySQL 客户端如 MySQL 运维工具和 MySQL 驱动等能直接支持。TLS 的前身是 SSL,因而 TLS 有时也被称为 SSL,但由于 SSL 协议有已知安全漏洞,TiDB 实际上并未支持。TiDB 支持的 TLS/SSL 协议版本为 TLS 1.0、TLS 1.1、TLS 1.2、TLS 1.3。 + +使用加密连接后,连接将具有以下安全性质: + +- 保密性:流量明文无法被窃听; +- 完整性:流量明文无法被篡改; +- 身份验证(可选):客户端和服务端能验证双方身份,避免中间人攻击。 + +TiDB 的加密连接支持默认是关闭的,必须在 TiDB 服务端通过配置开启加密连接的支持后,才能在客户端中使用加密连接,要使用加密连接必须同时满足以下两个条件: + +1. TiDB 服务端配置开启加密连接的支持 +2. 客户端指定使用加密连接 + +另外,与 MySQL 一致,TiDB 加密连接是以单个连接为单位的,默认情况下是可选的。因而对于开启了加密连接支持的 TiDB 服务端,客户端既可以选择通过加密连接安全地连接到该 TiDB 服务端,也可以选择使用普通的非加密连接。如需强制要求客户端使用加密连接可以通过以下两种方式进行配置: + ++ 通过在启动参数中配置 `--require-secure-transport` 要求所有用户必须使用加密连接来连接到 TiDB。 ++ 通过在创建用户 (`create user`),赋予权限 (`grant`) 或修改已有用户 (`alter user`) 时指定 `require ssl` 要求指定用户必须使用加密连接来连接 TiDB。以创建用户为例: + + ```sql + create user 'u1'@'%' require ssl; + ``` + +> **注意:** +> +> 如果登录用户已配置使用 [TiDB 证书鉴权功能](/certificate-authentication.md#配置登陆时需要校验的用户证书信息)校验用户证书,也会隐式要求对应用户必须使用加密连接连接 TiDB。 + +## 配置 TiDB 启用加密连接支持 + +在启动 TiDB 时,至少需要在配置文件中同时指定 `ssl-cert` 和 `ssl-key` 参数,才能使 TiDB 服务端接受加密连接。还可以指定 `ssl-ca` 参数进行客户端身份验证(请参见[配置启用身份验证](#配置启用身份验证)章节)。 + +- [`ssl-cert`](/tidb-configuration-file.md#ssl-cert):指定 SSL 证书文件路径 +- [`ssl-key`](/tidb-configuration-file.md#ssl-key):指定证书文件对应的私钥 +- [`ssl-ca`](/tidb-configuration-file.md#ssl-ca):可选,指定受信任的 CA 证书文件路径 + +参数指定的文件都为 PEM 格式。另外目前 TiDB 尚不支持加载有密码保护的私钥,因此必须提供一个没有密码的私钥文件。若提供的证书或私钥无效,则 TiDB 服务端将照常启动,但并不支持客户端加密连接到 TiDB 服务端。 + +上述证书及密钥可以使用 OpenSSL 签发和生成,也可以使用 MySQL 自带的工具 `mysql_ssl_rsa_setup` 快捷生成: + +{{< copyable "shell-regular" >}} + +```bash +mysql_ssl_rsa_setup --datadir=./certs +``` + +以上命令将在 `certs` 目录下生成以下文件: + +``` +certs +├── ca-key.pem +├── ca.pem +├── client-cert.pem +├── client-key.pem +├── private_key.pem +├── public_key.pem +├── server-cert.pem +└── server-key.pem +``` + +对应的 TiDB 配置文件参数为: + +```toml +[security] +ssl-cert = "certs/server-cert.pem" +ssl-key = "certs/server-key.pem" +``` + +若证书参数无误,则 TiDB 在启动时将会输出 `secure connection is enabled`,否则 TiDB 会输出 `secure connection is NOT ENABLED`。 + +## 配置 MySQL 客户端使用加密连接 + +MySQL 5.7 及以上版本自带的客户端默认尝试使用安全连接,若服务端不支持安全连接则自动退回到使用非安全连接;MySQL 5.7 以下版本自带的客户端默认采用非安全连接。 + +可以通过命令行参数修改客户端的连接行为,包括: + +- 强制使用安全连接,若服务端不支持安全连接则连接失败 (`--ssl-mode=REQUIRED`) +- 尝试使用安全连接,若服务端不支持安全连接则退回使用不安全连接 +- 使用不安全连接 (`--ssl-mode=DISABLED`) + +详细信息请参阅 MySQL 文档中关于[客户端配置安全连接](https://dev.mysql.com/doc/refman/5.7/en/using-encrypted-connections.html#using-encrypted-connections-client-side-configuration)的部分。 + +## 配置启用身份验证 + +若在 TiDB 服务端或 MySQL 客户端中未指定 `ssl-ca` 参数,则默认不会进行客户端或服务端身份验证,无法抵御中间人攻击,例如客户端可能会“安全地”连接到了一个伪装的服务端。可以在服务端和客户端中配置 `ssl-ca` 参数进行身份验证。一般情况下只需验证服务端身份,但也可以验证客户端身份进一步增强安全性。 + +- 若要使 MySQL 客户端验证 TiDB 服务端身份,TiDB 服务端需至少配置 `ssl-cert` 和 `ssl-key` 参数,客户端需至少指定 `--ssl-ca` 参数,且 `--ssl-mode` 至少为 `VERIFY_CA`。必须确保 TiDB 服务端配置的证书(`ssl-cert`)是由客户端 `--ssl-ca` 参数所指定的 CA 所签发的,否则身份验证失败。 +- 若要使 TiDB 服务端验证 MySQL 客户端身份,TiDB 服务端需配置 `ssl-cert`、`ssl-key`、`ssl-ca` 参数,客户端需至少指定 `--ssl-cert`、`--ssl-key` 参数。必须确保服务端配置的证书和客户端配置的证书都是由服务端配置指定的 `ssl-ca` 签发的。 +- 若要进行双向身份验证,请同时满足上述要求。 + +默认情况,服务端对客户端的身份验证是可选的。若客户端在 TLS 握手时未出示自己的身份证书,也能正常建立 TLS 连接。但也可以通过在创建用户 (`create user`),赋予权限 (`grant`) 或修改已有用户 (`alter user`) 时指定 `require 509` 要求客户端需进行身份验证,以创建用户为例: + +```sql +create user 'u1'@'%' require x509; +``` + +> **注意:** +> +> 如果登录用户已配置使用 [TiDB 证书鉴权功能](/certificate-authentication.md#配置登陆时需要校验的用户证书信息)校验用户证书,也会隐式要求对应用户需进行身份验证。 + +## 检查当前连接是否是加密连接 + +可以通过 `SHOW STATUS LIKE "%Ssl%";` 了解当前连接的详细情况,包括是否使用了安全连接、安全连接采用的加密协议、TLS 版本号等。 + +以下是一个安全连接中执行该语句的结果。由于客户端支持的 TLS 版本号和加密协议会有所不同,执行结果相应地也会有所变化。 + +{{< copyable "sql" >}} + +```sql +SHOW STATUS LIKE "%Ssl%"; +``` + +``` +...... +| Ssl_verify_mode | 5 | +| Ssl_version | TLSv1.2 | +| Ssl_cipher | ECDHE-RSA-AES128-GCM-SHA256 | +...... +``` + +除此以外,对于 MySQL 自带客户端,还可以使用 `STATUS` 或 `\s` 语句查看连接情况: + +{{< copyable "sql" >}} + +```sql +\s +``` + +``` +... +SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256 +... +``` + +## 支持的 TLS 版本及密钥交换协议和加密算法 + +TiDB 支持的 TLS 版本及密钥交换协议和加密算法由 Golang 官方库决定。 + +### 支持的 TLS 版本 + +- TLS 1.0 +- TLS 1.1 +- TLS 1.2 +- TLS 1.3 + +### 支持的密钥交换协议及加密算法 + +- TLS\_RSA\_WITH\_AES\_128\_CBC\_SHA +- TLS\_RSA\_WITH\_AES\_256\_CBC\_SHA +- TLS\_RSA\_WITH\_AES\_128\_CBC\_SHA256 +- TLS\_RSA\_WITH\_AES\_128\_GCM\_SHA256 +- TLS\_RSA\_WITH\_AES\_256\_GCM\_SHA384 +- TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_CBC\_SHA +- TLS\_ECDHE\_ECDSA\_WITH\_AES\_256\_CBC\_SHA +- TLS\_ECDHE\_RSA\_WITH\_AES\_128\_CBC\_SHA +- TLS\_ECDHE\_RSA\_WITH\_AES\_256\_CBC\_SHA +- TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_CBC\_SHA256 +- TLS\_ECDHE\_RSA\_WITH\_AES\_128\_CBC\_SHA256 +- TLS\_ECDHE\_RSA\_WITH\_AES\_128\_GCM\_SHA256 +- TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_GCM\_SHA256 +- TLS\_ECDHE\_RSA\_WITH\_AES\_256\_GCM\_SHA384 +- TLS\_ECDHE\_ECDSA\_WITH\_AES\_256\_GCM\_SHA384 +- TLS\_AES\_128\_GCM\_SHA256 +- TLS\_AES\_256\_GCM\_SHA384 +- TLS\_CHACHA20\_POLY1305\_SHA256 + +## 重加载证书、密钥和 CA + +在需要替换证书、密钥或 CA 时,可以在完成对应文件替换后,对运行中的 TiDB 实例执行 [`ALTER INSTANCE RELOAD TLS`](/sql-statements/sql-statement-alter-instance.md) 语句从原配置的证书 ([`ssl-cert`](/tidb-configuration-file.md#ssl-cert))、密钥 ([`ssl-key`](/tidb-configuration-file.md#ssl-key)) 和 CA ([`ssl-ca`](/tidb-configuration-file.md#ssl-ca)) 的路径重新加证书、密钥和 CA,而无需重启 TiDB 实例。 + +新加载的证书密钥和 CA 将在语句执行成功后对新建立的连接生效,不会影响语句执行前已建立的连接。 + +## 另请参阅 + +- [为 TiDB 组件间通信开启加密传输](/enable-tls-between-components.md) diff --git a/enable-tls-between-components.md b/enable-tls-between-components.md new file mode 100644 index 000000000000..de4348db00eb --- /dev/null +++ b/enable-tls-between-components.md @@ -0,0 +1,138 @@ +--- +title: 为 TiDB 组件间通信开启加密传输 +category: how-to +aliases: ['/docs-cn/stable/how-to/secure/enable-tls-between-components/'] +--- + +# 为 TiDB 组件间通信开启加密传输 + +本部分介绍如何为 TiDB 集群内各部组件间开启加密传输,一旦开启以下组件间均将使用加密传输: + +- TiDB 与 TiKV、PD +- TiKV 与 PD +- TiDB Control 与 TiDB,TiKV Control 与 TiKV,PD Control 与 PD +- TiKV、PD、TiDB 各自集群内内部通讯 + +目前暂不支持只开启其中部分组件的加密传输。 + +## 配置开启加密传输 + +1. 准备证书。 + + 推荐为 TiDB、TiKV、PD 分别准备一个 Server 证书,并保证可以相互验证,而它们的 Control 工具则可选择共用 Client 证书。 + + 有多种工具可以生成自签名证书,如 `openssl`,`easy-rsa`,`cfssl`。 + + 这里提供一个使用 `openssl` 生成证书的示例:[生成自签名证书](/generate-self-signed-certificates.md)。 + +2. 配置证书。 + + - TiDB + + 在 `config` 文件或命令行参数中设置: + + ```toml + [security] + # Path of file that contains list of trusted SSL CAs for connection with cluster components. + cluster-ssl-ca = "/path/to/ca.pem" + # Path of file that contains X509 certificate in PEM format for connection with cluster components. + cluster-ssl-cert = "/path/to/tidb-server.pem" + # Path of file that contains X509 key in PEM format for connection with cluster components. + cluster-ssl-key = "/path/to/tidb-server-key.pem" + ``` + + - TiKV + + 在 `config` 文件或命令行参数中设置,并设置相应的 URL 为 https: + + ```toml + [security] + # set the path for certificates. Empty string means disabling secure connectoins. + ca-path = "/path/to/ca.pem" + cert-path = "/path/to/tikv-server.pem" + key-path = "/path/to/tikv-server-key.pem" + ``` + + - PD + + 在 `config` 文件或命令行参数中设置,并设置相应的 URL 为 https: + + ```toml + [security] + # Path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty + cacert-path = "/path/to/ca.pem" + # Path of file that contains X509 certificate in PEM format. + cert-path = "/path/to/pd-server.pem" + # Path of file that contains X509 key in PEM format. + key-path = "/path/to/pd-server-key.pem" + ``` + + 此时 TiDB 集群各个组件间已开启加密传输。 + + > **注意:** + > + > 若 TiDB 集群各个组件间开启加密传输后,在使用 tidb-ctl、tikv-ctl 或 pd-ctl 工具连接集群时,需要指定 client 证书,示例: + + {{< copyable "shell-regular" >}} + + ```bash + ./tidb-ctl -u https://127.0.0.1:10080 --ca /path/to/ca.pem --ssl-cert /path/to/client.pem --ssl-key /path/to/client-key.pem + ``` + + {{< copyable "shell-regular" >}} + + ```bash + ./pd-ctl -u https://127.0.0.1:2379 --cacert /path/to/ca.pem --cert /path/to/client.pem --key /path/to/client-key.pem + ``` + + {{< copyable "shell-regular" >}} + + ```bash + ./tikv-ctl --host="127.0.0.1:20160" --ca-path="/path/to/ca.pem" --cert-path="/path/to/client.pem" --key-path="/path/to/clinet-key.pem" + ``` + +## 认证组件调用者身份 + +通常被调用者除了校验调用者提供的密钥、证书和 CA 有效性外,还需要校验调用方身份以防止拥有有效证书的非法访问者进行访问(例如:TiKV 只能被 TiDB 访问,需阻止拥有合法证书但非 TiDB 的其他访问者访问 TiKV)。 + +如希望进行组件调用者身份认证,需要在生证书时通过 `Common Name` 标识证书使用者身份,并在被调用者配置检查证书 `Common Name` 列表来检查调用者身份。 + +- TiDB + + 在 `config` 文件或命令行参数中设置: + + ```toml + [security] + cluster-verify-cn = [ + "TiDB-Server", + "TiKV-Control", + ] + ``` + +- TiKV + + 在 `config` 文件或命令行参数中设置: + + ```toml + [security] + cert-allowed-cn = [ + "TiDB-Server", "PD-Server", "TiKV-Control", "RawKvClient1", + ] + ``` + +- PD + + 在 `config` 文件或命令行参数中设置: + + ```toml + [security] + cert-allowed-cn = ["TiKV-Server", "TiDB-Server", "PD-Control"] + ``` + +## 证书重加载 + +TiDB、PD 和 TiKV 和各种 Client 都会在每次新建相互通讯的连接时重新读取当前的证书和密钥文件内容,实现证书和密钥的重加载。目前暂不支持 CA 的重加载。 + +## 另请参阅 + +- [为 TiDB 客户端服务端间通信开启加密传输](/enable-tls-between-clients-and-servers.md) diff --git a/error-codes.md b/error-codes.md new file mode 100644 index 000000000000..91b8584c0c8c --- /dev/null +++ b/error-codes.md @@ -0,0 +1,350 @@ +--- +title: 错误码与故障诊断 +category: reference +aliases: ['/docs-cn/stable/reference/error-codes/'] +--- + +# 错误码与故障诊断 + +本篇文档描述在使用 TiDB 过程中会遇到的问题以及解决方法。 + +## 错误码 + +TiDB 兼容 MySQL 的错误码,在大多数情况下,返回和 MySQL 一样的错误码。关于 MySQL 的错误码列表,详见 [Server Error Message Reference](https://dev.mysql.com/doc/refman/5.7/en/server-error-reference.html)。另外还有一些 TiDB 特有的错误码: + +> **注意:** +> +> 有一部分错误码属于内部错误,正常情况下 TiDB 会自行处理不会直接返回给用户,故没有在此列出。 +> +> 如果您遇到了这里没有列出的错误码,请向 PingCAP 工程师或通过官方论坛寻求帮助。 + +* Error Number: 8001 + + 请求使用的内存超过 TiDB 内存使用的阈值限制。出现这种错误,可以通过调整 `mem-quota-query` 来增大单个 SQL 使用的内存上限。 + +* Error Number: 8002 + + 带有 `SELECT FOR UPDATE` 语句的事务,在遇到写入冲突时,为保证一致性无法进行重试,事务将进行回滚并返回该错误。出现这种错误,应用程序可以安全地重新执行整个事务。 + +* Error Number: 8003 + + `ADMIN CHECK TABLE` 命令在遇到行数据跟索引不一致的时候返回该错误,在检查表中数据是否有损坏时常出现。出现该错误时,请向 PingCAP 工程师或通过官方论坛寻求帮助。 + +* Error Number: 8004 + + 单个事务过大,原因及解决方法请参考[这里](/faq/tidb-faq.md#433-transaction-too-large-是什么原因怎么解决) + +* Error Number: 8005 + + 事务在 TiDB 中遇到了写入冲突,原因及解决方法请参考[这里](/faq/tidb-faq.md#九故障排除) + +* Error Number: 8018 + + 当执行重新载入插件时,如果之前插件没有载入过,则会出现该错误。出现该错误,进行插件首次载入即可。 + +* Error Number: 8019 + + 重新载入的插件版本与之前的插件版本不一致,无法重新载入插件并报告该错误。可重新载入插件,确保插件的版本与之前载入的插件版本一致。 + +* Error Number: 8020 + + 当表被加锁时,如果对该表执行写入操作,将出现该错误。请将表解锁后,再进行尝试写入。 + +* Error Number: 8021 + + 当向 TiKV 读取的 key 不存在时将出现该错误,该错误用于内部使用,对外表现为读到的结果为空。 + +* Error Number: 8022 + + 事务提交失败,已经回滚,应用程序可以安全的重新执行整个事务。 + +* Error Number: 8023 + + 在事务内,写入事务缓存时,设置了空值,将返回该错误。这是一个内部使用的错误,将由内部进行处理,不会返回给应用程序。 + +* Error Number: 8024 + + 非法的事务。当事务执行时,发现没有获取事务的 ID (Start Timestamp),代表正在执行的事务是一个非法的事务,将返回该错误。通常情况下不会出现该问题,当发生时,请向 PingCAP 工程师或通过官方论坛寻求帮助。 + +* Error Number: 8025 + + 写入的单条键值对过大。TiDB 最大支持 6MB 的单个键值对,超过该限制需要将过大的单行数据进行人工处理,以满足 6MB 限制。 + +* Error Number: 8026 + + 使用了没有实现的接口函数。该错误仅用于数据库内部,应用程序不会收到这个错误。 + +* Error Number: 8027 + + 表结构版本过期。TiDB 使用 F1 的在线 Schema 变更算法来执行 DDL。当 TiDB server 表结构版本落后于整个系统的时,执行 SQL 将遇到该错误。遇到该错误,请检查该 TiDB server 与 PD leader 之间的网络。 + +* Error Number: 8028 + + TiDB 没有表锁(在 MySQL 中称为元数据锁,在其他数据库中可能称为意向锁)。当事务执行时,TiDB 表结构发生了变化是无法被事务感知到的。因此,TiDB 在事务提交时,会对事务涉及表的结构进行检查。如果事务执行中表结构发生了变化,则事务将提交失败,并返回该错误。遇到该错误,应用程序可以安全地重新执行整个事务。 + +* Error Number: 8029 + + 当数据库内部进行数值转换发生错误时,将会出现该错误,该错误仅在内部使用,对外部应用将转换为具体类型的错误。 + +* Error Number: 8030 + + 将值转变为带符号正整数时发生了越界,将结果显示为负数。多在告警信息里出现。 + +* Error Number: 8031 + + 将负数转变为无符号数时,将负数转变为了正数。多在告警信息里出现。 + +* Error Number: 8032 + + 使用了非法的 year 格式。year 只允许 1 位、2 位和 4 位数。 + +* Error Number: 8033 + + 使用了非法的 year 值。year 的合法范围是 (1901, 2155)。 + +* Error Number: 8037 + + week 函数中使用了非法的 mode 格式。mode 必须是一位数字,范围 [0, 7]。 + +* Error Number: 8038 + + 字段无法获取到默认值。一般作为内部错误使用,转换成其他具体错误类型后,返回给应用程序。 + +* Error Number: 8040 + + 尝试进行不支持的操作,比如在 View 和 Sequence 上进行 lock table。 + +* Error Number: 8047 + + 设置了不支持的系统变量值,通常在用户设置了数据库不支持的变量值后的告警信息里出现。 + +* Error Number: 8048 + + 设置了不支持的隔离级别,如果是使用第三方工具或框架等无法修改代码进行适配的情况,可以考虑通过 `tidb_skip_isolation_level_check` + 来绕过这一检查。 + + {{< copyable "sql" >}} + + ```sql + set @@tidb_skip_isolation_level_check = 1; + ``` + +* Error Number: 8050 + + 设置了不支持的权限类型,遇到该错误请参考[TiDB 权限说明](/privilege-management.md#tidb-各操作需要的权限)进行调整。 + +* Error Number: 8051 + + TiDB 在解析客户端发送的 Exec 参数列表时遇到了未知的数据类型。如果遇到这个错误,请检查客户端是否正常,如果客户端正常请向 PingCAP 工程师或通过官方论坛寻求帮助。 + +* Error Number: 8052 + + 来自客户端的数据包的序列号错误。如果遇到这个错误,请检查客户端是否正常,如果客户端正常请向 PingCAP 工程师或通过官方论坛寻求帮助。 + +* Error Number: 8055 + + 当前快照过旧,数据可能已经被 GC。可以调大 `tikv_gc_life_time` 的值来避免该问题。新版本的 TiDB 会自动为长时间运行的事务保留数据,一般不会遇到该错误。 + 有关 GC 的介绍和配置可以参考 [GC 机制简介](/garbage-collection-overview.md)和 [GC 配置](/garbage-collection-configuration.md)文档。 + + {{< copyable "sql" >}} + + ```sql + update mysql.tidb set VARIABLE_VALUE="24h" where VARIABLE_NAME="tikv_gc_life_time"; + ``` + +* Error Number: 8059 + + 自动随机量可用次数用尽无法进行分配。当前没有恢复这类错误的方法。建议在使用 auto random 功能时使用 bigint 以获取最大的可分配次数, + 并尽量避免手动给 auto random 列赋值。相关的介绍和使用建议可以参考 [auto random 功能文档](/auto-random.md)。 + +* Error Number: 8060 + + 非法的自增列偏移量。请检查 `auto_increment_increment` 和 `auto_increment_offset` 的取值是否符合要求。 + +* Error Number: 8061 + + 不支持的 SQL Hint。请参考 [Optimizer Hints](/optimizer-hints.md) 检查和修正 SQL Hint。 + +* Error Number: 8062 + + SQL Hint 中使用了非法的 token,与 Hint 的保留字冲突。请参考 [Optimizer Hints](/optimizer-hints.md) 检查和修正 SQL Hint。 + +* Error Number: 8063 + + SQL Hint 中限制内存使用量超过系统设置的上限,设置被忽略。请参考 [Optimizer Hints](/optimizer-hints.md) 检查和修正 SQL Hint。 + +* Error Number: 8064 + + 解析 SQL Hint 失败。请参考 [Optimizer Hints](/optimizer-hints.md) 检查和修正 SQL Hint。 + +* Error Number: 8065 + + SQL Hint 中使用了非法的整数。请参考 [Optimizer Hints](/optimizer-hints.md) 检查和修正 SQL Hint。 + +* Error Number: 8066 + + JSON_OBJECTAGG 函数的第二个参数是非法参数。 + +* Error Number: 8101 + + 插件 ID 格式错误,正确的格式是 `[name]-[version]` 并且 name 和 version 中不能带有 '-'。 + +* Error Number: 8102 + + 无法读取插件定义信息。请检查插件相关的配置。 + +* Error Number: 8103 + + 插件名称错误,请检查插件的配置。 + +* Error Number: 8104 + + 插件版本不匹配,请检查插件的配置。 + +* Error Number: 8105 + + 插件被重复载入。 + +* Error Number: 8106 + + 插件定义的系统变量名称没有以插件名作为开头,请联系插件的开发者进行修复。 + +* Error Number: 8107 + + 载入的插件未指定版本或指定的版本过低,请检查插件的配置。 + +* Error Number: 8108 + + 不支持的执行计划类型。该错误为内部处理的错误,如果遇到该报错请向 PingCAP 工程师或通过官方论坛寻求帮助。 + +* Error Number: 8109 + + analyze 索引时找不到指定的索引。 + +* Error Number: 8110 + + 不能进行笛卡尔积运算,需要将配置文件里的 `cross-join` 设置为 `true`。 + +* Error Number: 8111 + + execute 语句执行时找不到对应的 prepare 语句。 + +* Error Number: 8112 + + execute 语句的参数个数与 prepare 语句不符合。 + +* Error Number: 8113 + + execute 语句涉及的表结构在 prepare 语句执行后发生了变化。 + +* Error Number: 8115 + + 不支持 prepare 多行语句。 + +* Error Number: 8116 + + 不支持 prepare DDL 语句。 + +* Error Number: 8120 + + 获取不到事务的 start tso,请检查 PD Server 状态/监控/日志以及 TiDB Server 与 PD Server 之间的网络。 + +* Error Number: 8121 + + 权限检查失败,请检查数据库的权限配置。 + +* Error Number: 8122 + + 指定了通配符,但是找不到对应的表名。 + +* Error Number: 8123 + + 带聚合函数的 SQL 中返回非聚合的列,违反了 `only_full_group_by` 模式。请修改 SQL 或者考虑关闭 `only_full_group_by` 模式。 + +* Error Number: 8200 + + 尚不支持的 DDL 语法。请参考 [与 MySQL DDL 的兼容性](/mysql-compatibility.md#ddl)。 + +* Error Number: 8214 + + DDL 操作被 admin cancel 操作终止。 + +* Error Number: 8215 + + Admin Repair 表失败,如果遇到该报错请向 PingCAP 工程师或通过官方论坛寻求帮助。 + +* Error Number: 8216 + + 自动随机列使用的方法不正确,请参考 [auto random 功能文档](/auto-random.md)进行修改。 + +* Error Number: 8223 + + 检测出数据与索引不一致的错误,如果遇到该报错请向 PingCAP 工程师或通过官方论坛寻求帮助。 + +* Error Number: 8224 + + 找不到 DDL job,请检查 restore 操作指定的 job id 是否存在。 + +* Error Number: 8225 + + DDL 已经完成,无法被取消。 + +* Error Number: 8226 + + DDL 几乎要完成了,无法被取消。 + +* Error Number: 8227 + + 创建 Sequence 时使用了不支持的选项,支持的选项的列表可以参考 [Sequence 使用文档](/sql-statements/sql-statement-create-sequence.md#参数说明)。 + +* Error Number: 8228 + + 在 Sequence 上使用 `setval` 时指定了不支持的类型,该函数的示例可以在 [Sequence 使用文档](/sql-statements/sql-statement-create-sequence.md#示例)中找到。 + +* Error Number: 8229 + + 事务超过存活时间,遇到该问题可以提交或者回滚当前事务,开启一个新事务。 + +* Error Number: 8230 + + TiDB 目前不支持在新添加的列上使用 Sequence 作为默认值,如果尝试进行这类操作会返回该错误。 + +* Error Number: 9001 + + 请求 PD 超时,请检查 PD Server 状态/监控/日志以及 TiDB Server 与 PD Server 之间的网络。 + +* Error Number: 9002 + + 请求 TiKV 超时,请检查 TiKV Server 状态/监控/日志以及 TiDB Server 与 TiKV Server 之间的网络。 + +* Error Number: 9003 + + TiKV 操作繁忙,一般出现在数据库负载比较高时,请检查 TiKV Server 状态/监控/日志。 + +* Error Number: 9004 + + 当数据库上承载的业务存在大量的事务冲突时,会遇到这种错误,请检查业务代码。 + +* Error Number: 9005 + + 某个 Raft Group 不可用,如副本数目不足,出现在 TiKV 比较繁忙或者是 TiKV 节点停机的时候,请检查 TiKV Server 状态/监控/日志。 + +* Error Number: 9006 + + GC Life Time 间隔时间过短,长事务本应读到的数据可能被清理了,应增加 GC Life Time。 + +* Error Number: 9007 + + 事务在 TiKV 中遇到了写入冲突,原因及解决方法请参考[这里](/faq/tidb-faq.md#九故障排除)。 + +* Error Number: 9008 + + 同时向 TiKV 发送的请求过多,超过了限制。请调大 `tidb_store_limit` 或将其设置为 `0` 来取消对请求流量的限制。 + +* Error Number: 9010 + + TiKV 无法处理这条 raft log,请检查 TiKV Server 状态/监控/日志。 + +## 故障诊断 + +参见[故障诊断文档](/troubleshoot-tidb-cluster.md)以及 [FAQ](/faq/tidb-faq.md)。 diff --git a/export-or-backup-using-dumpling.md b/export-or-backup-using-dumpling.md new file mode 100644 index 000000000000..af2e8dc54355 --- /dev/null +++ b/export-or-backup-using-dumpling.md @@ -0,0 +1,171 @@ +--- +title: 使用 Dumpling 导出或备份 TiDB 数据 +summary: 使用新的导出工具 Dumpling 导出或者备份数据。 +category: how-to +--- + +# 使用 Dumpling 导出或备份 TiDB 数据 + +本文档介绍如何使用数据导出工具 [Dumpling](https://github.com/pingcap/dumpling)。该工具可以把存储在 TiDB 中的数据导出为 SQL 或者 CSV 格式,可以用于完成逻辑上的全量备份或者导出。 + +如果需要直接备份 SST 文件(KV 对)或者对延迟不敏感的增量备份,请参阅 [BR](/br/backup-and-restore-tool.md)。如果需要实时的增量备份,请参阅 [TiCDC](/ticdc/ticdc-overview.md)。 + +Dumpling 的更多具体用法可以使用 --help 指令查看,或者查看[中文使用手册](https://github.com/pingcap/dumpling/blob/master/docs/cn/user-guide.md)。 + +使用 Dumpling 时,需要在已经启动的集群上执行导出命令。本文假设在 `127.0.0.1:4000` 有一个 TiDB 实例,并且这个 TiDB 实例中有无密码的 root 用户。 + +## 下载地址 + +最新版 Dumpling 的下载地址见[下载链接](https://download.pingcap.org/dumpling-nightly-linux-amd64.tar.gz)。 + +## 从 TiDB 导出数据 + +### 导出到 sql 文件 + +Dumpling 默认导出数据格式为 sql 文件。也可以通过设置 `--filetype sql` 导出数据到 sql 文件: + +{{< copyable "shell-regular" >}} + +```shell +dumpling \ + -u root \ + -P 4000 \ + -h 127.0.0.1 \ + --filetype sql \ + --threads 32 \ + -o /tmp/test \ + -F 256 +``` + +上述命令中,`-h`、`-P`、`-u` 分别是地址,端口,用户。如果需要密码验证,可以用 `-p $YOUR_SECRET_PASSWORD` 传给 Dumpling。 + +### 导出到 csv 文件 + +假如导出数据的格式是 CSV(使用 `--filetype csv` 即可导出 CSV 文件),还可以使用 `--sql ` 导出指定 SQL 选择出来的记录,例如,导出 `test.sbtest1` 中所有 `id < 100` 的记录: + +{{< copyable "shell-regular" >}} + +```shell +./dumpling \ + -u root \ + -P 4000 \ + -h 127.0.0.1 \ + -o /tmp/test \ + --filetype csv \ + --sql 'select * from `test`.`sbtest1` where id < 100' +``` + +> **注意:** +> +> 1. `--sql` 选项暂时仅仅可用于导出 csv 的场景。 +> +> 2. 这里需要在要导出的所有表上执行 `select * from where id < 100` 语句。如果部分表没有指定的字段,那么导出会失败。 + +### 筛选导出的数据 + +#### 使用 `--where` 指令筛选数据 + +默认情况下,除了系统数据库中的表之外,Dumpling 会导出整个数据库的表。你可以使用 `--where ` 来选定要导出的记录。 + +{{< copyable "shell-regular" >}} + +```shell +./dumpling \ + -u root \ + -P 4000 \ + -h 127.0.0.1 \ + -o /tmp/test \ + --where "id < 100" +``` + +上述命令将会导出各个表的 id < 100 的数据。 + +#### 使用 `--filter` 指令筛选数据 + +Dumpling 可以通过 `--filter` 指定 table-filter 来筛选特定的库表。table-filter 的语法与 .gitignore 相似,[详细语法参考](https://github.com/pingcap/tidb-tools/blob/master/pkg/table-filter/README.md)。 + +{{< copyable "shell-regular" >}} + +```shell +./dumpling \ + -u root \ + -P 4000 \ + -h 127.0.0.1 \ + -o /tmp/test \ + --filter "employees.*" \ + --filter "*.WorkOrder" +``` + +上述命令将会导出 `employees` 数据库的所有表,以及所有数据库中的 `WorkOrder` 表。 + +#### 使用 `-B` 或 `-T` 指令筛选数据 + +Dumpling 也可以通过 `-B` 或 `-T` 参数导出特定的数据库/数据表。 + +> **注意:** +> +> 1. `--filter` 参数与 `-T` 参数不可同时使用。 +> +> 2. `-T` 参数只能接受完整的 `库名.表名` 形式,不支持只指定表名。例:Dumpling 无法识别 `-T WorkOrder`。 + +例如通过指定: + +- `-B employees` 导出 `employees` 数据库 +- `-T employees.WorkOrder` 导出 `employees.WorkOrder` 数据表 + +### 通过并发提高 Dumpling 的导出效率 + +默认情况下,导出的文件会存储到 `./export-` 目录下。常用参数如下: + +- `-o` 用于选择存储导出文件的目录。 +- `-F` 选项用于指定单个文件的最大大小,默认单位为 `MiB`。可以接受类似 `5GiB` 或 `8KB` 的输入。 +- `-r` 选项用于指定单个文件的最大记录数(或者说,数据库中的行数),开启后 Dumpling 会开启表内并发,提高导出大表的速度。 + +利用以上参数可以让 Dumpling 的并行度更高。 + +### 调整 Dumpling 的数据一致性选项 + +> **注意:** +> +> 在大多数场景下,用户不需要调整 Dumpling 的默认数据一致性选项。 + +Dumpling 通过 `--consistency ` 标志控制导出数据“一致性保证”的方式。对于 TiDB 来说,默认情况下,会通过获取某个时间戳的快照来保证一致性(即 `--consistency snapshot`)。在使用 snapshot 来保证一致性的时候,可以使用 `--snapshot` 参数指定要备份的时间戳。还可以使用以下的一致性级别: + +- `flush`:使用 [`FLUSH TABLES WITH READ LOCK`](https://dev.mysql.com/doc/refman/8.0/en/flush.html#flush-tables-with-read-lock) 来保证一致性。 +- `snapshot`:获取指定时间戳的一致性快照并导出。 +- `lock`:为待导出的所有表上读锁。 +- `none`:不做任何一致性保证。 +- `auto`:对 MySQL 使用 `flush`,对 TiDB 使用 `snapshot`。 + +一切完成之后,你应该可以在 `/tmp/test` 看到导出的文件了: + +```shell +$ ls -lh /tmp/test | awk '{print $5 "\t" $9}' + +140B metadata +66B test-schema-create.sql +300B test.sbtest1-schema.sql +190K test.sbtest1.0.sql +300B test.sbtest2-schema.sql +190K test.sbtest2.0.sql +300B test.sbtest3-schema.sql +190K test.sbtest3.0.sql +``` + +另外,假如数据量非常大,可以提前调长 GC 时间,以避免因为导出过程中发生 GC 导致导出失败: + +{{< copyable "sql" >}} + +```sql +update mysql.tidb set VARIABLE_VALUE = '720h' where VARIABLE_NAME = 'tikv_gc_life_time'; +``` + +在操作结束之后,再将 GC 时间调回原样(默认是 `10m`): + +{{< copyable "sql" >}} + +```sql +update mysql.tidb set VARIABLE_VALUE = '10m' where VARIABLE_NAME = 'tikv_gc_life_time'; +``` + +最后,所有的这些导出数据都可以用 [Lightning](/tidb-lightning/tidb-lightning-tidb-backend.md) 导入回 TiDB。 diff --git a/expression-syntax.md b/expression-syntax.md new file mode 100644 index 000000000000..a24088cb6009 --- /dev/null +++ b/expression-syntax.md @@ -0,0 +1,35 @@ +--- +title: 表达式语法 +summary: 本文列出 TiDB 的表达式语法。 +category: reference +aliases: ['/docs-cn/stable/reference/sql/language-structure/expression-syntax/'] +--- + +# 表达式语法 (Expression Syntax) + +表达式是一个或多个值、操作符或函数的组合。在 TiDB 中,表达式主要使用在 `SELECT` 语句的各个子句中,包括 Group by 子句、Where 子句、Having 子句、Join 条件以及窗口函数等。此外,部分 DDL 语句也会使用到表达式,例如建表时默认值的设置、生成列的设置,分区规则等。 + +表达式包含几种类型: + ++ 标识符,可参考[模式对象名](/schema-object-names.md)。 ++ 谓词、数值、字符串、日期表达式等,这些类型的[字面值](/literal-values.md)也是表达式。 ++ 函数调用,窗口函数等。可参考[函数和操作符概述](/functions-and-operators/functions-and-operators-overview.md) 和 [窗口函数](/functions-and-operators/window-functions.md)。 ++ 其他,包括 paramMarker(即 `?`)、系统变量和用户变量、CASE 表达式等。 + +以下规则是表达式的语法,该语法基于 TiDB parser 的 [parser.y](https://github.com/pingcap/parser/blob/master/parser.y) 文件中所定义的规则。此外,下列语法图的可导航版本请参考 [TiDB SQL 语法图](https://pingcap.github.io/sqlgram/#Expression)。 + +**Expression:** + +![Expression](/media/sqlgram/Expression.png) + +**PredicateExpr:** + +![PredicateExpr](/media/sqlgram/PredicateExpr.png) + +**BitExpr:** + +![BitExpr](/media/sqlgram/BitExpr.png) + +**SimpleExpr:** + +![SimpleExpr](/media/sqlgram/SimpleExpr.png) diff --git a/faq/deploy-and-maintain-faq.md b/faq/deploy-and-maintain-faq.md new file mode 100644 index 000000000000..c10a71373615 --- /dev/null +++ b/faq/deploy-and-maintain-faq.md @@ -0,0 +1,517 @@ +--- +title: 部署运维 FAQ +summary: 介绍 TiDB 集群运维部署的常见问题、原因及解决方法。 +category: FAQ +--- + +# 部署运维 FAQ + +本文介绍 TiDB 集群运维部署的常见问题、原因及解决方法。 + +## 环境准备 FAQ + +操作系统版本要求如下表: + +| Linux 操作系统平台 | 版本 | +| :--- | :--- | +| Red Hat Enterprise Linux | 7.3 及以上 | +| CentOS | 7.3 及以上 | +| Oracle Enterprise Linux | 7.3 及以上 | + +### 为什么要在 CentOS 7 上部署 TiDB 集群? + +TiDB 作为一款开源分布式 NewSQL 数据库,可以很好的部署和运行在 Intel 架构服务器环境及主流虚拟化环境,并支持绝大多数的主流硬件网络,作为一款高性能数据库系统,TiDB 支持主流的 Linux 操作系统环境,具体可以参考 TiDB 的[官方部署要求](/hardware-and-software-requirements.md)。 + +其中 TiDB 在 CentOS 7.3 的环境下进行大量的测试,同时也有很多这个操作系统的部署最佳实践,因此,我们推荐客户在部署 TiDB 的时候使用 CentOS 7.3+ 以上的Linux 操作系统。 + +## 硬件要求 FAQ + +TiDB 支持部署和运行在 Intel x86-64 架构的 64 位通用硬件服务器平台。对于开发、测试、及生产环境的服务器硬件配置有以下要求和建议: + +### 开发及测试环境 + +| **组件** | **CPU** | **内存** | **本地存储** | **网络** | **实例数量(最低要求)** | +| --- | --- | --- | --- | --- | --- | +| TiDB | 8核+ | 16 GB+ | SAS, 200 GB+ | 千兆网卡 | 1(可与 PD 同机器) | +| PD | 8核+ | 16 GB+ | SAS, 200 GB+ | 千兆网卡 | 1(可与 TiDB 同机器) | +| TiKV | 8核+ | 32 GB+ | SSD, 200 GB+ | 千兆网卡 | 3 | +| | | | | 服务器总计 | 4 | + +### 线上环境 + +| **组件** | **CPU** | **内存** | **硬盘类型** | **网络** | **实例数量(最低要求)** | +| --- | --- | --- | --- | --- | --- | +| TiDB | 16核+ | 48 GB+ | SAS | 万兆网卡(2块最佳) | 2 | +| PD | 8核+ | 16 GB+ | SSD | 万兆网卡(2块最佳) | 3 | +| TiKV | 16核+ | 48 GB+ | SSD | 万兆网卡(2块最佳) | 3 | +| 监控 | 8核+ | 16 GB+ | SAS | 千兆网卡 | 1 | +| | | | | 服务器总计 | 9 | + +### 两块网卡的目的是?万兆的目的是? + +作为一个分布式集群,TiDB 对时间的要求还是比较高的,尤其是 PD 需要分发唯一的时间戳,如果 PD 时间不统一,如果有 PD 切换,将会等待更长的时间。两块网卡可以做 bond,保证数据传输的稳定,万兆可以保证数据传输的速度,千兆网卡容易出现瓶颈,我们强烈建议使用万兆网卡。 + +### SSD 不做 RAID 是否可行? + +资源可接受的话,我们建议做 RAID 10,如果资源有限,也可以不做 RAID。 + +### TiDB 集群各个组件的配置推荐? + +- TiDB 需要 CPU 和内存比较好的机器,参考官网配置要求,如果后期需要开启 TiDB Binlog,根据业务量的评估和 GC 时间的要求,也需要本地磁盘大一点,不要求 SSD 磁盘; +- PD 里面存了集群元信息,会有频繁的读写请求,对磁盘 I/O 要求相对比较高,磁盘太差会影响整个集群性能,推荐 SSD 磁盘,空间不用太大。另外集群 Region 数量越多对 CPU、内存的要求越高; +- TiKV 对 CPU、内存、磁盘要求都比较高,一定要用 SSD 磁盘。 + +详情可参考 [TiDB 软硬件环境需求](/hardware-and-software-requirements.md)。 + +## 安装部署 FAQ + +如果用于生产环境,推荐使用 TiUP [使用 TiUP 部署](/production-deployment-using-tiup.md) TiDB 集群。 + +### 为什么修改了 TiKV/PD 的 toml 配置文件,却没有生效? + +这种情况一般是因为没有使用 `--config` 参数来指定配置文件(目前只会出现在 binary 部署的场景),TiKV/PD 会按默认值来设置。如果要使用配置文件,请设置 TiKV/PD 的 `--config` 参数。对于 TiKV 组件,修改配置后重启服务即可;对于 PD 组件,只会在第一次启动时读取配置文件,之后可以使用 pd-ctl 的方式来修改配置,详情可参考 [PD 配置参数](/command-line-flags-for-pd-configuration.md)。 + +### TiDB 监控框架 Prometheus + Grafana 监控机器建议单独还是多台部署? + +监控机建议单独部署。建议 CPU 8 core,内存 16 GB 以上,硬盘 500 GB 以上。 + +### 有一部分监控信息显示不出来? + +查看访问监控的机器时间跟集群内机器的时间差,如果比较大,更正时间后即可显示正常。 + +### supervise/svc/svstat 服务具体起什么作用? + +- supervise 守护进程 +- svc 启停服务 +- svstat 查看进程状态 + +### inventory.ini 变量参数解读 + +| **变量** | **含义** | +| --- | --- | +| cluster_name | 集群名称,可调整 | +| tidb_version | TiDB 版本,TiDB Ansible 各分支默认已配置 | +| deployment_method | 部署方式,默认为 binary,可选 docker | +| process_supervision | 进程监管方式,默认为 systemd,可选 supervise | +| timezone | 修改部署目标机器时区,默认为 Asia/Shanghai, 可调整,与set_timezone 变量结合使用 | +| set_timezone | 默认为 True,即修改部署目标机器时区,关闭可修改为 False | +| enable_elk | 目前不支持,请忽略 | +| enable_firewalld | 开启防火墙,默认不开启 | +| enable_ntpd | 检测部署目标机器 NTP 服务,默认为 True,请勿关闭 | +| machine_benchmark | 检测部署目标机器磁盘 IOPS,默认为 True,请勿关闭 | +| set_hostname | 根据 IP 修改部署目标机器主机名,默认为 False | +| enable_binlog | 是否部署 pump 并开启 binlog,默认为 False,依赖 Kafka 集群,参见 zookeeper_addrs 变量 | +| zookeeper_addrs | binlog Kafka 集群的 zookeeper 地址 | +| enable_slow_query_log | TiDB 慢查询日志记录到单独文件({{ deploy_dir }}/log/tidb_slow_query.log),默认为 False,记录到 tidb 日志 | +| deploy_without_tidb | KV 模式,不部署 TiDB 服务,仅部署 PD、TiKV 及监控服务,请将 inventory.ini 文件中 tidb_servers 主机组 IP 设置为空。 | + +### TiDB 离线 Ansible 部署方案(4.0 版本后不推荐使用) + +首先这不是我们建议的方式,如果中控机没有外网,也可以通过离线 Ansible 部署方式,详情可参考[离线 TiDB Ansible 部署方案](/offline-deployment-using-ansible.md)。 + +### Docker Compose 快速构建集群(单机部署) + +使用 docker-compose 在本地一键拉起一个集群,包括集群监控,还可以根据需求自定义各个组件的软件版本和实例个数,以及自定义配置文件,这种只限于开发环境,详细可参考[官方文档](/deploy-test-cluster-using-docker-compose.md)。 + +### 如何单独记录 TiDB 中的慢查询日志,如何定位慢查询 SQL? + +1)TiDB 中,对慢查询的定义在 tidb-ansible 的 `conf/tidb.yml` 配置文件中,`slow-threshold: 300`,这个参数是配置慢查询记录阈值的,单位是 ms。 + +慢查询日志默认记录到 tidb.log 中,如果希望生成单独的慢查询日志文件,修改 inventory.ini 配置文件的参数 `enable_slow_query_log` 为 True。 + +如上配置修改之后,需要执行 `ansible-playbook rolling_update.yml --tags=tidb`,对 tidb-server 实例进行滚动升级,升级完成后,tidb-server 将在 `tidb_slow_query.log` +文件中记录慢查询日志。 + +2)如果出现了慢查询,可以从 Grafana 监控定位到出现慢查询的 tidb-server 以及时间点,然后在对应节点查找日志中记录的 SQL 信息。 + +3)除了日志,还可以通过 `admin show slow` 命令查看,详情可参考 [`admin show slow` 命令](/identify-slow-queries.md#admin-show-slow-命令)。 + +### 首次部署 TiDB 集群时,没有配置 tikv 的 Label 信息,在后续如何添加配置 Label? + +TiDB 的 Label 设置是与集群的部署架构相关的,是集群部署中的重要内容,是 PD 进行全局管理和调度的依据。如果集群在初期部署过程中没有设置 Label,需要在后期对部署结构进行调整,就需要手动通过 PD 的管理工具 pd-ctl 来添加 location-labels 信息,例如:`config set location-labels "zone,rack,host"`(根据实际的 label 层级名字配置)。 + +pd-ctl 的使用参考 [PD Control 使用说明](/pd-control.md)。 + +### 为什么测试磁盘的 dd 命令用 `oflag=direct` 这个选项? + +Direct 模式就是把写入请求直接封装成 I/O 指令发到磁盘,这样是为了绕开文件系统的缓存,可以直接测试磁盘的真实的 I/O 读写能力。 + +### 如何用 fio 命令测试 TiKV 实例的磁盘性能? + +- 随机读测试: + + {{< copyable "shell-regular" >}} + + ```bash + ./fio -ioengine=psync -bs=32k -fdatasync=1 -thread -rw=randread -size=10G -filename=fio_randread_test.txt -name='fio randread test' -iodepth=4 -runtime=60 -numjobs=4 -group_reporting --output-format=json --output=fio_randread_result.json + ``` + +- 顺序写和随机读混合测试: + + {{< copyable "shell-regular" >}} + + ```bash + ./fio -ioengine=psync -bs=32k -fdatasync=1 -thread -rw=randrw -percentage_random=100,0 -size=10G -filename=fio_randread_write_test.txt -name='fio mixed randread and sequential write test' -iodepth=4 -runtime=60 -numjobs=4 -group_reporting --output-format=json --output=fio_randread_write_test.json + ``` + +### 使用 TiDB Ansible 部署 TiDB 集群的时候,遇到 `UNREACHABLE! "msg": "Failed to connect to the host via ssh: "` 报错是什么原因? + +有两种可能性: + +- ssh 互信的准备工作未做好,建议严格参照我们的[官方文档步骤](/online-deployment-using-ansible.md)配置互信,并使用命令 `ansible -i inventory.ini all -m shell -a 'whoami' -b` 来验证互信配置是否成功。 + +- 如果涉及到单服务器分配了多角色的场景,例如多组件混合部署或单台服务器部署了多个 TiKV 实例,可能是由于 ssh 复用的机制引起这个报错,可以使用 `ansible … -f 1` 的选项来规避这个报错。 + +## 集群管理 FAQ + +### 集群日常管理 + +#### Ansible 常见运维操作有那些? + +| **任务** | **Playbook** | +| --- | --- | +| 启动集群 | ansible-playbook start.yml | +| 停止集群 | ansible-playbook stop.yml | +| 销毁集群 | ansible-playbook unsafe\_cleanup.yml (若部署目录为挂载点,会报错,可忽略) | +| 清除数据(测试用) | ansible-playbook cleanup\_data.yml | +| 滚动升级 | ansible-playbook rolling\_update.yml | +| 滚动升级 TiKV | ansible-playbook rolling\_update.yml --tags=tikv | +| 滚动升级除 PD 外模块 | ansible-playbook rolling\_update.yml --skip-tags=pd | +| 滚动升级监控组件 | ansible-playbook rolling\_update\_monitor.yml | + +#### TiDB 如何登录? + +和 MySQL 登录方式一样,可以按照下面例子进行登录。 + +`mysql -h 127.0.0.1 -uroot -P4000` + +#### TiDB 如何修改数据库系统变量? + +和 MySQL 一样,TiDB 也分为静态参数和固态参数,静态参数可以直接通过`set global xxx = n`的方式进行修改,不过新参数值只限于该实例生命周期有效。 + +#### TiDB (TiKV) 有哪些数据目录? + +默认在 [`--data-dir`](/command-line-flags-for-tikv-configuration.md#--data-dir) 目录下,其中包括 backup、db、raft、snap 四个目录,分别存储备份、数据、raft 数据及镜像数据。 + +#### TiDB 有哪些系统表? + +和 MySQL 类似,TiDB 中也有系统表,用于存放数据库运行时所需信息,具体信息参考 [TiDB 系统数据库](/system-tables/system-table-overview.md)文档。 + +#### TiDB 各节点服务器下是否有日志文件,如何管理? + +默认情况下各节点服务器会在日志中输出标准错误,如果启动的时候通过 `--log-file` 参数指定了日志文件,那么日志会输出到指定的文件中,并且按天做 rotation。 + +#### 如何规范停止 TiDB? + +如果是用 TiDB Ansible 部署的,可以使用 `ansible-playbook stop.yml` 命令停止 TiDB 集群。如果不是 TiDB Ansible 部署的,可以直接 kill 掉所有服务。如果使用 kill 命令,TiDB 的组件会做 graceful 的 shutdown。 + +#### TiDB 里面可以执行 kill 命令吗? + +- 可以 kill DML 语句,首先使用 `show processlist`,找到对应 session 的 id,然后执行 `kill tidb [session id]`。 +- 可以 kill DDL 语句,首先使用 `admin show ddl jobs`,查找需要 kill 的 DDL job ID,然后执行 `admin cancel ddl jobs 'job_id' [, 'job_id'] ...`。具体可以参考 [admin 操作](/sql-statements/sql-statement-admin.md)。 + +#### TiDB 是否支持会话超时? + +TiDB 暂不支持数据库层面的会话超时,目前想要实现超时,在没 LB(Load Balancing)的时候,需要应用侧记录发起的 Session 的 ID,通过应用自定义超时,超时以后需要到发起 Query 的节点上用 `kill tidb [session id]` 来杀掉 SQL。目前建议使用应用程序来实现会话超时,当达到超时时间,应用层就会抛出异常继续执行后续的程序段。 + +#### TiDB 生产环境的版本管理策略是怎么样的?如何尽可能避免频繁升级? + +TiDB 版本目前逐步标准化,每次 Release 都包含详细的 Change log,版本功能[变化详情](https://github.com/pingcap/TiDB/releases),生产环境是否有必要升级取决于业务系统,建议升级之前详细了解前后版本的功能差异。 + +版本号说明参考:Release Version: `v1.0.3-1-ga80e796` + +- `v1.0.3` 表示 GA 标准版 +- `1` 表示该版本 commit 1 次 +- `ga80e796` 代表版本的 `git-hash` + +#### 分不清 TiDB master 版本之间的区别,经常用错 TiDB Ansible 版本? + +TiDB 目前社区非常活跃,在 1.0 GA 版本发布后,还在不断的优化和修改 BUG,因此 TiDB 的版本更新周期比较快,会不定期有新版本发布,请关注我们的[新版本发布官方网站](https://pingcap.com/weekly/)。此外 TiDB 安装推荐[使用 TiUP 进行安装](/production-deployment-using-tiup.md)。此外,在 TiDB 1.0 GA 版本后,对 TiDB 的版本号进行了统一管理,TiDB 的版本可以通过以下两种方式进行查看: + +- 通过 `select tidb_version()` 进行查看 +- 通过执行 `tidb-server -V` 进行查看 + +#### 有没有图形化部署 TiDB 的工具? + +暂时没有。 + +#### TiDB 如何进行水平扩展? + +当您的业务不断增长时,数据库可能会面临三方面瓶颈,第一是存储空间,第二是计算资源,第三是读写容量,这时可以对 TiDB 集群做水平扩展。 + +- 如果是存储资源不够,可以通过添加 TiKV Server 节点来解决,新节点启动后,PD 会自动将其他节点的部分数据迁移过去,无需人工介入。 +- 如果是计算资源不够,可以查看 TiDB Server 和 TiKV Server 节点的 CPU 消耗情况,再考虑添加 TiDB Server 节点或者是 TiKV Server 节点来解决,如添加 TiDB Server 节点,将其添加到前端 Load Balancer 配置之中即可。 +- 如果是容量跟不上,一般可以考虑同时增加 TiDB Server 和 TiKV Server 节点。 + +#### Percolator 用了分布式锁,crash 的客户端会保持锁,会造成锁没有 release? + +详细可参考 [Percolator 和 TiDB 事务算法](https://pingcap.com/blog-cn/percolator-and-txn/)。 + +#### TiDB 为什么选用 gRPC 而不选用 Thrift,是因为 Google 在用吗? + +不只是因为 Google 在用,有一些比较好的特性我们需要,比如流控、加密还有 Streaming。 + +#### like(bindo.customers.name, jason%, 92) 这个92代表什么? + +那个是转义字符,默认是 (ASCII 92)。 + +#### 为什么 `information_schema.tables.data_length` 记录的大小和 TiKV 监控面板上的 store size 不一样? + +这是因为两者计算的角度不一样。`information_schema.tables.data_length` 是通过统计信息(平均每行的大小)得到的估算值。TiKV 监控面板上的 store size 是单个 TiKV 实例的数据文件(RocksDB 的 SST 文件)的大小总和。由于多版本和 TiKV 会压缩数据,所以两者显示的大小不一样。 + +### PD 管理 + +#### 访问 PD 报错:TiKV cluster is not bootstrapped + +PD 的大部分 API 需要在初始化 TiKV 集群以后才能使用,如果在部署新集群的时候只启动了 PD,还没有启动 TiKV,这时候访问 PD 就会报这个错误。遇到这个错误应该先把要部署的 TiKV 启动起来,TiKV 会自动完成初始化工作,然后就可以正常访问 PD。 + +#### PD 启动报错:etcd cluster ID mismatch + +PD 启动参数中的 `--initial-cluster` 包含了某个不属于该集群的成员。遇到这个错误时请检查各个成员的所属集群,剔除错误的成员后即可正常启动。 + +#### PD 能容忍的时间同步误差是多少? + +理论上,时间同步误差越小越好。PD 可容忍任意时长的误差,但是,时间同步误差越大意味着 PD 分配的时间戳与真实的物理时间相差越大,这个差距会影响读历史版本等功能。 + +#### Client 连接是如何寻找 PD 的? + +Client 连接只能通过 TiDB 访问集群,TiDB 负责连接 PD 与 TiKV,PD 与 TiKV 对 Client 透明。当 TiDB 连接任意一台 PD 的时候,PD 会告知 TiDB 当前的 leader 是谁,如果此台 PD 不是 leader,TiDB 将会重新连接至 leader PD。 + +#### PD 参数中 leader-schedule-limit 和 region-schedule-limit 调度有什么区别? + +- leader-schedule-limit 调度是用来均衡不同 TiKV 的 leader 数,影响处理查询的负载。 +- region-schedule-limit 调度是均衡不同 TiKV 的副本数,影响不同节点的数据量。 + +#### 每个 region 的 replica 数量可配置吗?调整的方法是? + +可以,目前只能调整全局的 replica 数量。首次启动时 PD 会读配置文件(conf/pd.yml),使用其中的 max-replicas 配置,之后修改需要使用 pd-ctl 配置命令 `config set max-replicas $num`,配置后可通过 `config show all` 来查看已生效的配置。调整的时候,不会影响业务,会在后台添加,注意总 TiKV 实例数总是要大于等于设置的副本数,例如 3 副本需要至少 3 个 TiKV。增加副本数量之前需要预估额外的存储需求。pd-ctl 的详细用法可参考 [PD Control 使用说明](/pd-control.md)。 + +#### 缺少命令行集群管理工具,整个集群的健康度当前是否正常,不好确认? + +可以通过 pd-ctl 等工具来判断集群大概的状态,详细的集群状态还是需要通过监控来确认。 + +#### 集群下线节点后,怎么删除老集群节点监控信息? + +下线节点一般指 TiKV 节点通过 pd-ctl 或者监控判断节点是否下线完成。节点下线完成后,手动停止下线节点上相关的服务。从 Prometheus 配置文件中删除对应节点的 node_exporter 信息。从 Ansible inventory.ini 中删除对应节点的信息。 + +#### 使用 PD Control 连接 PD Server 时,为什么只能通过本机 IP 连接,不能通过 127.0.0.1 连接? + +因为使用 TiDB Ansible 部署的集群,PD 对外服务端口不会绑定到 127.0.0.1,所以 PD Control 不会识别 127.0.0.1。 + +### TiDB server 管理 + +#### TiDB 的 lease 参数应该如何设置? + +启动 TiDB Server 时,需要通过命令行参数设置 lease 参数(--lease=60),其值会影响 DDL 的速度(只会影响当前执行 DDL 的 session,其他的 session 不会受影响)。在测试阶段,lease 的值可以设为 1s,加快测试进度;在生产环境下,我们推荐这个值设为分钟级(一般可以设为 60),这样可以保证 DDL 操作的安全。 + +#### DDL 在正常情况下的耗时是多少? + +一般情况下处理一个 DDL 操作(之前没有其他 DDL 操作在处理)的耗时基本可以分如下为三种: + +- add index 操作,且此操作对应表数据行数比较少,耗时约为 3s。 +- add index 操作,且此操作对应表数据行数比较多,耗时具体由表中数据行数和当时 QPS 情况定(add index 操作优先级比一般 SQL 低)。 +- 其他 DDL 操作耗时约为 1s。 + +此外,如果接收 DDL 请求的 TiDB 和 DDL owner 所处的 TiDB 是一台,那么上面列举的第一和第三种可能的耗时应该在几十到几百毫秒。 + +#### 为什么有的时候执行 DDL 会很慢? + +可能原因如下: + +- 多个 DDL 语句一起执行的时候,后面的几个 DDL 语句会比较慢。原因是当前 TiDB 集群中 DDL 操作是串行执行的。 +- 在正常集群启动后,第一个 DDL 操作的执行时间可能会比较久,一般在 30s 左右,这个原因是刚启动时 TiDB 在竞选处理 DDL 的 leader。 +- 由于停 TiDB 时不能与 PD 正常通信(包括停电情况)或者用 `kill -9` 指令停 TiDB 导致 TiDB 没有及时从 PD 清理注册数据,那么会影响 TiDB 启动后 10min 内的 DDL 语句处理时间。这段时间内运行 DDL 语句时,每个 DDL 状态变化都需要等待 2 * lease(默认 lease = 45s)。 +- 当集群中某个 TiDB 与 PD 之间发生通信问题,即 TiDB 不能从 PD 及时获取或更新版本信息,那么这时候 DDL 操作的每个状态处理需要等待 2 * lease。 + +#### TiDB 可以使用 S3 作为后端存储吗? + +不可以,目前 TiDB 只支持分布式存储引擎和 GolevelDB/RocksDB/BoltDB 引擎。 + +#### Information_schema 能否支持更多真实信息? + +Information_schema 库里面的表主要是为了兼容 MySQL 而存在,有些第三方软件会查询里面的信息。在目前 TiDB 的实现中,里面大部分只是一些空表。后续随着 TiDB 的升级,会提供更多的参数信息。当前 TiDB 支持的 Information\_schema 请参考 [TiDB 系统数据库说明文档](/system-tables/system-table-information-schema.md)。 + +#### TiDB Backoff type 主要原因? + +TiDB-server 与 TiKV-server 随时进行通信,在进行大量数据操作过程中,会出现 `Server is busy` 或者 `backoff.maxsleep 20000ms` 的日志提示信息,这是由于 TiKV-server 在处理过程中系统比较忙而出现的提示信息,通常这时候可以通过系统资源监控到 TiKV 主机系统资源使用率比较高的情况出现。如果这种情况出现,可以根据资源使用情况进行相应的扩容操作。 + +#### TiDB TiClient type 主要原因? + +TiClient Region Error 该指标描述的是在 TiDB-server 作为客户端通过 KV 接口访问 TiKV-server 进行数据操作过程中,TiDB-server 操作 TiKV-server 中的 Region 数据出现的错误类型与 metric 指标,错误类型包括 not_leader、stale_epoch。出现这些错误的情况是当 TiDB-server 根据自己的缓存信息去操作 Region leader 数据的时候,Region leader 发生了迁移或者 TiKV 当前的 Region 信息与 TiDB 缓存的路由信息不一致而出现的错误提示。一般这种情况下,TiDB-server 都会自动重新从 PD 获取最新的路由数据,重做之前的操作。 + +#### TiDB 同时支持的最大并发连接数? + +当前版本 TiDB 没有最大连接数的限制,如果并发过大导致响应时间增加,可以通过增加 TiDB 节点进行扩容。 + +#### 如何查看某张表创建的时间? + +information_schema 库中的 tables 表里的 create_time 即为表的真实创建时间。 + +#### TiDB 的日志中 EXPENSIVE_QUERY 是什么意思? + +TiDB 在执行 SQL 时,预估出来每个 operator 处理了超过 10000 条数据就认为这条 query 是 expensive query。可以通过修改 tidb-server 配置参数来对这个门限值进行调整,调整后需要重新启动 tidb-server。 + +### TiKV 管理 + +#### TiKV 集群副本建议配置数量是多少,是不是最小高可用配置(3个)最好? + +如果是测试环境 3 副本足够;在生产环境中,不可让集群副本数低于 3,需根据架构特点、业务系统及恢复能力的需求,适当增加副本数。值得注意的是,副本升高,性能会有下降,但是安全性更高。 + +#### TiKV 启动报错:cluster ID mismatch + +TiKV 本地存储的 cluster ID 和指定的 PD 的 cluster ID 不一致。在部署新的 PD 集群的时候,PD 会随机生成一个 cluster ID,TiKV 第一次初始化的时候会从 PD 获取 cluster ID 存储在本地,下次启动的时候会检查本地的 cluster ID 与 PD 的 cluster ID 是否一致,如果不一致则会报错并退出。出现这个错误一个常见的原因是,用户原先部署了一个集群,后来把 PD 的数据删除了并且重新部署了新的 PD,但是 TiKV 还是使用旧的数据重启连到新的 PD 上,就会报这个错误。 + +#### TiKV 启动报错:duplicated store address + +启动参数中的地址已经被其他的 TiKV 注册在 PD 集群中了。造成该错误的常见情况:TiKV `--data-dir` 指定的路径下没有数据文件夹(删除或移动后没有更新 --data-dir),用之前参数重新启动该 TiKV。请尝试用 pd-ctl 的 [store delete](https://github.com/pingcap/pd/tree/55db505e8f35e8ab4e00efd202beb27a8ecc40fb/tools/pd-ctl#store-delete--label--weight-store_id----jqquery-string) 功能,删除之前的 store,然后重新启动 TiKV 即可。 + +#### TiKV master 和 slave 用的是一样的压缩算法,为什么效果不一样? + +目前来看 master 有些文件的压缩率会高一些,这个取决于底层数据的分布和 RocksDB 的实现,数据大小偶尔有些波动是正常的,底层存储引擎会根据需要调整数据。 + +#### TiKV block cache 有哪些特性? + +TiKV 使用了 RocksDB 的 Column Family (CF) 特性,KV 数据最终存储在默认 RocksDB 内部的 default、write、lock 3 个 CF 内。 + +- default CF 存储的是真正的数据,与其对应的参数位于 `[rocksdb.defaultcf]` 项中。 +- write CF 存储的是数据的版本信息(MVCC)、索引、小表相关的数据,相关的参数位于 `[rocksdb.writecf]` 项中。 +- lock CF 存储的是锁信息,系统使用默认参数。 +- Raft RocksDB 实例存储 Raft log。default CF 主要存储的是 Raft log,与其对应的参数位于 `[raftdb.defaultcf]` 项中。 +- 所有 CF 共享一个 Block-cache,用于缓存数据块,加速 RocksDB 的读取速度,Block-cache 的大小通过参数 `block-cache-size` 控制,`block-cache-size` 越大,能够缓存的热点数据越多,对读取操作越有利,同时占用的系统内存也会越多。 +- 每个 CF 有各自的 Write-buffer,大小通过 `write-buffer-size` 控制。 + +#### TiKV channel full 是什么原因? + +- Raftstore 线程太忙,或者因 I/O 而卡住。可以看一下 Raftstore 的 CPU 使用情况。 +- TiKV 过忙(CPU、磁盘 I/O 等),请求处理不过来。 + +#### TiKV 频繁切换 Region leader 是什么原因? + +- 网络问题导致节点间通信卡了,查看 Report failures 监控。 +- 原主 Leader 的节点卡了,导致没有及时给 Follower 发送消息。 +- Raftstore 线程卡了。 + +#### 如果一个节点挂了会影响服务吗?影响会持续多久? + +TiDB 使用 Raft 在多个副本之间做数据同步(默认为每个 Region 3 个副本)。当一份备份出现问题时,其他的副本能保证数据的安全。根据 Raft 协议,当某个节点挂掉导致该节点里的 Leader 失效时,在最大 2 * lease time(leasetime 是 10 秒)时间后,通过 Raft 协议会很快将一个另外一个节点里的 Follower 选为新的 Region Leader 来提供服务。 + +#### TiKV 在分别在那些场景下占用大量 IO、内存、CPU(超过参数配置的多倍)? + +在大量写入、读取的场景中会占用大量的磁盘 IO、内存、CPU。在执行很复杂的查询,比如会产生很大中间结果集的情况下,会消耗很多的内存和 CPU 资源。 + +#### TiKV 是否可以使用 SAS/SATA 盘或者进行 SSD/SAS 混合部署? + +不可以使用,TiDB 在进行 OLTP 场景中,数据访问和操作需要高 IO 磁盘的支持,TiDB 作为强一致的分布式数据库,存在一定的写放大,如副本复制、存储底层 Compaction,因此,TiDB 部署的最佳实践中推荐用户使用 NVMe SSD 磁盘作为数据存储磁盘。另外,TiKV 与 PD 不能混合部署。 + +#### 数据表 Key 的 Range 范围划分是在数据接入之前就已经划分好了吗? + +不是的,这个和 MySQL 分表规则不一样,需要提前设置好,TiKV 是根据 Region 的大小动态分裂的。 + +#### Region 是如何进行分裂的? + +Region 不是前期划分好的,但确实有 Region 分裂机制。当 Region 的大小超过参数 `region-max-size` 或 `region-max-keys` 的值时,就会触发分裂,分裂后的信息会汇报给 PD。 + +#### TiKV 是否有类似 MySQL 的 `innodb_flush_log_trx_commit` 参数,来保证提交数据不丢失? + +是的,TiKV 单机的存储引擎目前使用两个 RocksDB 实例,其中一个存储 raft-log,TiKV 有个 sync-log 参数,在 ture 的情况下,每次提交都会强制刷盘到 raft-log,如果发生 crash 后,通过 raft-log 进行 KV 数据的恢复。 + +#### 对 WAL 存储有什么推荐的硬件配置,例如 SSD,RAID 级别,RAID 卡 cache 策略,NUMA 设置,文件系统选择,操作系统的 IO 调度策略等? + +WAL 属于顺序写,目前我们并没有单独对他进行配置,建议 SSD,RAID 如果允许的话,最好是 RAID 10,RAID 卡 cache、操作系统 I/O 调度目前没有针对性的最佳实践,Linux 7 以上默认配置即可,NUMA 没有特别建议,NUMA 内存分配策略可以尝试使用 `interleave = all`,文件系统建议 ext4。 + +#### 在最严格的 `sync-log = true` 数据可用模式下,写入性能如何? + +一般来说,开启 `sync-log` 会让性能损耗 30% 左右。关闭 `sync-log` 时的性能表现,请参见 [TiDB Sysbench 性能测试报告](https://pingcap.com/docs-cn/v3.0/benchmark/v3.0-performance-benchmarking-with-sysbench/)。 + +#### 是否可以利用 TiKV 的 Raft + 多副本达到完全的数据可靠,单机存储引擎是否需要最严格模式? + +通过使用 [Raft 一致性算法](https://raft.github.io/),数据在各 TiKV 节点间复制为多副本,以确保某个节点挂掉时数据的安全性。只有当数据已写入超过 50% 的副本时,应用才返回 ACK(三副本中的两副本)。但理论上两个节点也可能同时发生故障,所以除非是对性能要求高于数据安全的场景,一般都强烈推荐开启 `sync-log`。 + +另外,还有一种 `sync-log` 的替代方案,即在 Raft group 中用五个副本而非三个。这将允许两个副本同时发生故障,而仍然能保证数据安全性。 + +对于单机存储引擎也同样推荐打开 `sync-log` 模式。否则如果节点宕机可能会丢失最后一次写入数据。 + +#### 使用 Raft 协议,数据写入会有多次网络的 roundtrip,实际写入延迟如何? + +理论上,和单机数据库相比,数据写入会多四个网络延迟。 + +#### 有没有类似 MySQL 的 InnoDB Memcached plugin,可以直接使用 KV 接口,可以不需要独立的 Cache? + +TiKV 支持单独进行接口调用,理论上也可以起个实例做为 Cache,但 TiDB 最大的价值是分布式关系型数据库,我们原则上不对 TiKV 单独进行支持。 + +#### Coprocessor 组件的主要作用? + +- 减少 TiDB 与 TiKV 之间的数据传输。 +- 计算下推,充分利用 TiKV 的分布式计算资源。 + +#### IO error: No space left on device While appending to file + +这是磁盘空间不足导致的,需要加节点或者扩大磁盘空间。 + +#### 为什么 TiKV 容易出现 OOM? + +TiKV 的内存占用主要来自于 RocksDB 的 block-cache,默认为系统总内存的 40%。当 TiKV 容易出现 OOM 时,检查 `block-cache-size` 配置是否过高。还需要注意,当单机部署了多个 TiKV 实例时,需要显式地配置该参数,以防止多个实例占用过多系统内存导致 OOM。 + +#### TiDB 数据和 RawKV 数据可存储于同一个 TiKV 集群里吗? + +不可以。TiDB 数据(或使用其他事务 API 生成的数据)依赖于一种特殊的键值格式,和 RawKV API 数据(或其他基于 RawKV 的服务生成的数据)并不兼容。 + +### TiDB 测试 + +#### TiDB Sysbench 基准测试结果如何? + +很多用户在接触 TiDB 都习惯做一个基准测试或者 TiDB 与 MySQL 的对比测试,官方也做了一个类似测试,汇总很多测试结果后,我们发现虽然测试的数据有一定的偏差,但结论或者方向基本一致,由于 TiDB 与 MySQL 由于架构上的差别非常大,很多方面是很难找到一个基准点,所以官方的建议两点: + +- 大家不要用过多精力纠结这类基准测试上,应该更多关注 TiDB 的场景上的区别。 +- 大家可以直接参考 [TiDB Sysbench 性能测试报告](https://pingcap.com/docs-cn/v3.0/benchmark/v3.0-performance-benchmarking-with-sysbench/)。 + +#### TiDB 集群容量 QPS 与节点数之间关系如何,和 MySQL 对比如何? + +- 在 10 节点内,TiDB 写入能力(Insert TPS)和节点数量基本成 40% 线性递增,MySQL 由于是单节点写入,所以不具备写入扩展能力。 +- MySQL 读扩容可以通过添加从库进行扩展,但写流量无法扩展,只能通过分库分表,而分库分表有很多问题,具体参考[方案虽好,成本先行:数据库 Sharding+Proxy 实践解析](http://t.cn/RTD18qV)。 +- TiDB 不管是读流量、还是写流量都可以通过添加节点快速方便的进行扩展。 + +#### 我们的 DBA 测试过 MySQL 性能,单台 TiDB 的性能没有 MySQL 性能那么好? + +TiDB 设计的目标就是针对 MySQL 单台容量限制而被迫做的分库分表的场景,或者需要强一致性和完整分布式事务的场景。它的优势是通过尽量下推到存储节点进行并行计算。对于小表(比如千万级以下),不适合 TiDB,因为数据量少,Region 有限,发挥不了并行的优势,最极端的就是计数器表,几行记录高频更新,这几行在 TiDB 里,会变成存储引擎上的几个 KV,然后只落在一个 Region 里,而这个 Region 只落在一个节点上。加上后台强一致性复制的开销,TiDB 引擎到 TiKV 引擎的开销,最后表现出来的就是没有单个 MySQL 好。 + +### TiDB 备份恢复 + +#### TiDB 主要备份方式? + +目前,推荐的备份方式是使用 [PingCAP fork 的 Mydumper](/mydumper-overview.md)。尽管 TiDB 也支持使用 MySQL 官方工具 `mysqldump` 进行数据备份、恢复,但其性能低于 [`mydumper`](/mydumper-overview.md)/[`loader`](/loader-overview.md),并且该工具备份、恢复大量数量时,要耗费更多时间。 + +使用 Mydumper 导出来的数据文件尽可能的小, 最好不要超过 64M, 可以设置参数 -F 64; + +loader 的 -t 参数可以根据 TiKV 的实例个数以及负载进行评估调整,例如 3 个 TiKV 的场景, 此值可以设为 3 * (1 ~ n),当 TiKV 负载过高,loader 以及 TiDB 日志中出现大量 `backoffer.maxSleep 15000ms is exceeded` 可以适当调小该值,当 TiKV 负载不是太高的时候,可以适当调大该值。 + +## 监控 FAQ + ++ Prometheus 监控框架详情可见 [TiDB 监控框架概述](/tidb-monitoring-framework.md)。 ++ 监控指标解读详细参考 [重要监控指标详解](/grafana-overview-dashboard.md)。 + +### 目前的监控使用方式及主要监控指标,有没有更好看的监控? + +TiDB 使用 Prometheus + Grafana 组成 TiDB 数据库系统的监控系统,用户在 Grafana 上通过 dashboard 可以监控到 TiDB 的各类运行指标,包括系统资源的监控指标,包括客户端连接与 SQL 运行的指标,包括内部通信和 Region 调度的指标,通过这些指标,可以让数据库管理员更好的了解到系统的运行状态,运行瓶颈等内容。在监控指标的过程中,我们按照 TiDB 不同的模块,分别列出了各个模块重要的指标项,一般用户只需要关注这些常见的指标项。具体指标请参见[官方文档](/grafana-overview-dashboard.md)。 + +### Prometheus 监控数据默认 15 天自动清除一次,可以自己设定成 2 个月或者手动删除吗? + +可以的,在 Prometheus 启动的机器上,找到启动脚本,然后修改启动参数,然后重启 Prometheus 生效。 + +```config +--storage.tsdb.retention="60d" +``` + +### Region Health 监控项 + +TiDB-2.0 版本中,PD metric 监控页面中,对 Region 健康度进行了监控,其中 Region Health 监控项是对所有 Region 副本状况的一些统计。其中 miss 是缺副本,extra 是多副本。同时也增加了按 Label 统计的隔离级别,level-1 表示这些 Region 的副本在第一级 Label 下是物理隔离的,没有配置 location label 时所有 Region 都在 level-0。 + +### Statement Count 监控项中的 selectsimplefull 是什么意思? + +代表全表扫,但是可能是很小的系统表。 + +### 监控上的 QPS 和 Statement OPS 有什么区别? + +QPS 会统计执行的所有 SQL 命令,包括 use database、load data、begin、commit、set、show、insert、select 等。 + +Statement OPS 只统计 select、update、insert 等业务相关的,所以 Statement OPS 的统计和业务比较相符。 diff --git a/faq/high-availability-faq.md b/faq/high-availability-faq.md new file mode 100644 index 000000000000..0a178693bee7 --- /dev/null +++ b/faq/high-availability-faq.md @@ -0,0 +1,19 @@ +--- +title: 高可用常见问题 +summary: 介绍高可用相关的常见问题。 +category: FAQ +--- + +# 高可用常见问题 + +本文档介绍高可用相关的常见问题。 + +## TiDB 数据是强一致的吗? + +通过使用 [Raft 一致性算法](https://raft.github.io/),数据在各 TiKV 节点间复制为多副本,以确保某个节点挂掉时数据的安全性。 + +在底层,TiKV 使用复制日志 + 状态机 (State Machine) 的模型来复制数据。对于写入请求,数据被写入 Leader,然后 Leader 以日志的形式将命令复制到它的 Follower 中。当集群中的大多数节点收到此日志时,日志会被提交,状态机会相应作出变更。 + +## 官方有没有三中心跨机房多活部署的推荐方案? + +从 TiDB 架构来讲,支持真正意义上的跨中心异地多活,从操作层面讲,依赖数据中心之间的网络延迟和稳定性,一般建议延迟在 5ms 以下,目前我们已经有相似客户方案,具体请咨询官方 [info@pingcap.com](mailto:info@pingcap.com)。 diff --git a/faq/high-reliability-faq.md b/faq/high-reliability-faq.md new file mode 100644 index 000000000000..82e8f86d0958 --- /dev/null +++ b/faq/high-reliability-faq.md @@ -0,0 +1,28 @@ +--- +title: 高可靠常见问题 +summary: 介绍高可靠相关的常见问题。 +category: FAQ +--- + +# 高可靠常见问题 + +本文档介绍高可靠相关的常见问题。 + +## 我们的安全漏洞扫描工具对 MySQL version 有要求,TiDB 是否支持修改 server 版本号呢? + +TiDB 在 v3.0.8 后支持修改 server 版本号,可以通过配置文件中的 [`server-version`](/tidb-configuration-file.md#server-version) 配置项进行修改。在使用 TiDB Ansible 部署集群时,同样可以通过 `conf/tidb.yml` 配置文件中的 `server-version` 来设置合适的版本号,以避免出现安全漏洞扫描不通过的问题。 + +## TiDB 支持哪些认证协议,过程是怎样的? + +这一层跟 MySQL 一样,走的 SASL 认证协议,用于用户登录认证,对密码的处理流程。 + +客户端连接 TiDB 的时候,走的是 challenge-response(挑战-应答)的认证模式,过程如下: + +1. 客户端连接服务器; +2. 服务器发送随机字符串 `challenge` 给客户端; +3. 客户端发送 `username` + `response` 给服务器; +4. 服务器验证 `response`。 + +## 如何修改用户名密码和权限? + +TiDB 作为分布式数据库,在 TiDB 中修改用户密码建议使用 `set password for 'root'@'%' = '0101001';` 或 `alter` 方法,不推荐使用 `update mysql.user` 的方法进行,这种方法可能会造成其它节点刷新不及时的情况。修改权限也一样,都建议采用官方的标准语法。详情可参考 [TiDB 用户账户管理](/user-account-management.md)。 diff --git a/faq/licensing-faq.md b/faq/licensing-faq.md new file mode 100644 index 000000000000..4140a0571267 --- /dev/null +++ b/faq/licensing-faq.md @@ -0,0 +1,3 @@ +--- +draft: true +--- \ No newline at end of file diff --git a/faq/migration-tidb-faq.md b/faq/migration-tidb-faq.md new file mode 100644 index 000000000000..2336f4fa38d5 --- /dev/null +++ b/faq/migration-tidb-faq.md @@ -0,0 +1,165 @@ +--- +title: 迁移常见问题 +summary: 介绍 TiDB 迁移中的常见问题。 +category: FAQ +--- + +# 迁移常见问题 + +## 全量数据导出导入 + +### TiDB 是否支持 Mydumper + +支持,参见 [Mydumper 使用文档](/mydumper-overview.md)。 + +### TiDB 是否支持 Loader + +支持,参见 [Loader 使用文档](/loader-overview.md)。 + +### 如何将一个运行在 MySQL 上的应用迁移到 TiDB 上? + +TiDB 支持绝大多数 MySQL 语法,一般不需要修改代码。 + +### 不小心把 MySQL 的 user 表导入到 TiDB 了,或者忘记密码,无法登录,如何处理? + +重启 TiDB 服务,配置文件中增加 `-skip-grant-table=true` 参数,无密码登录集群后,可以根据情况重建用户,或者重建 mysql.user 表,具体表结构搜索官网。 + +### 在 Loader 运行的过程中,TiDB 可以对外提供服务吗? + +该操作进行逻辑插入,TiDB 仍可对外提供服务,但不要执行相关 DDL 操作。 + +### 如何导出 TiDB 数据? + +TiDB 目前暂时不支持 `select into outfile`,可以通过以下方式导出 TiDB 数据:参考 [MySQL 使用 mysqldump 导出某个表的部分数据](https://blog.csdn.net/xin_yu_xin/article/details/7574662),使用 mysqldump 加 where 条件导出,使用 MySQL client 将 select 的结果输出到一个文件。 + +### 如何从 DB2、Oracle 数据库迁移到 TiDB? + +DB2、Oracle 到 TiDB 数据迁移(增量+全量),通常做法有: + +- 使用 Oracle 官方迁移工具,如 OGG、Gateway(透明网关)、CDC(Change Data Capture)。 +- 自研数据导出导入程序实现。 +- 导出(Spool)成文本文件,然后通过 Load infile 进行导入。 +- 使用第三方数据迁移工具。 + +目前看来 OGG 最为合适。 + +### 用 Sqoop 批量写入 TiDB 数据,虽然配置了 `--batch` 选项,但还是会遇到 `java.sql.BatchUpdateExecption:statement count 5001 exceeds the transaction limitation` 的错误,该如何解决? + +- 在 Sqoop 中,`--batch` 是指每个批次提交 100 条 statement,但是默认每个 statement 包含 100 条 SQL 语句,所以此时 100 * 100 = 10000 条 SQL 语句,超出了 TiDB 的事务限制 5000 条,可以增加选项 `-Dsqoop.export.records.per.statement=10` 来解决这个问题,完整的用法如下: + + {{< copyable "shell-regular" >}} + + ```bash + sqoop export \ + -Dsqoop.export.records.per.statement=10 \ + --connect jdbc:mysql://mysql.example.com/sqoop \ + --username sqoop ${user} \ + --password ${passwd} \ + --table ${tab_name} \ + --export-dir ${dir} \ + --batch + ``` + +- 也可以选择增大 tidb 的单个事物语句数量限制,不过这个会导致内存上涨。 + +### TiDB 有像 Oracle 那样的 Flashback Query 功能么,DDL 支持么? + +有,也支持 DDL。详细参考 [TiDB 历史数据回溯](/read-historical-data.md)。 + +## 在线数据同步 + +### Syncer 架构 + +详细参考 [解析 TiDB 在线数据同步工具 Syncer](https://pingcap.com/blog-cn/tidb-syncer/)。 + +#### Syncer 使用文档 + +详细参考 [Syncer 使用文档](/syncer-overview.md)。 + +#### 如何配置监控 Syncer 运行情况? + +下载 [Syncer Json](https://github.com/pingcap/tidb-ansible/blob/master/scripts/syncer.json) 导入到 Grafana,修改 Prometheus 配置文件,添加以下内容: + +- job_name: 'syncer_ops' // 任务名字 + static_configs: +- targets: ['10.10.1.1:10096'] //Syncer 监听地址与端口,通知 prometheus 拉取 Syncer 的数据。 + +重启 Prometheus 即可。 + +#### 有没有现成的同步方案,可以将数据同步到 Hbase、Elasticsearh 等其他存储? + +没有,目前依赖程序自行实现。 + +#### 利用 Syncer 做数据同步的时候是否支持只同步部分表? + +支持,具体参考 Syncer 使用手册 [Syncer 使用文档](/syncer-overview.md) + +#### 频繁的执行 DDL 会影响 Syncer 同步速度吗? + +频繁执行 DDL 对同步速度会有影响。对于 Sycner 来说,DDL 是串行执行的,当同步遇到了 DDL,就会以串行的方式执行,所以这种场景就会导致同步速度下降。 + +#### 使用 Syncer gtid 的方式同步时,同步过程中会不断更新 syncer.meta 文件,如果 Syncer 所在的机器坏了,导致 syncer.meta 文件所在的目录丢失,该如何处理? + +当前 Syncer 版本的没有进行高可用设计,Syncer 目前的配置信息 syncer.meta 直接存储在硬盘上,其存储方式类似于其他 MySQL 生态工具,比如 Mydumper。因此,要解决这个问题当前可以有两个方法: + ++ 把 syncer.meta 数据放到比较安全的磁盘上,例如磁盘做好 raid1; + ++ 可以根据 Syncer 定期上报到 Prometheus 的监控信息来还原出历史同步的位置信息,该方法的位置信息在大量同步数据时由于延迟会可能不准确。 + +#### Syncer 下游 TiDB 数据和 MySQL 数据不一致,DML 会退出么? + +- 上游 MySQL 中存在数据,下游 TiDB 中该数据不存在,上游 MySQL 执行 `UPDATE` 或 `DELETE`(更新/删除)该条数据的操作时,Syncer 同步过程即不会报错退出也没有该条数据。 +- 下游有主键索引或是唯一索引冲突时,执行 `UPDATE` 会退出,执行 `INSERT` 不会退出。 + +## 业务流量迁入 + +### 如何快速迁移业务流量? + +我们建议通过 Syncer 工具搭建成多源 MySQL -> TiDB 实时同步环境,读写流量可以按照需求分阶段通过修改网络配置进行流量迁移,建议 DB 上层部署一个稳定的网络 LB(HAproxy、LVS、F5、DNS 等),这样直接修改网络配置就能实现无缝流量迁移。 + +### TiDB 总读写流量有限制吗? + +TiDB 读流量可以通过增加 TiDB server 进行扩展,总读容量无限制,写流量可以通过增加 TiKV 节点进行扩容,基本上写容量也没有限制。 + +### Transaction too large 是什么原因,怎么解决? + +TiDB 限制了单条 KV entry 不超过 6MB。 + +分布式事务要做两阶段提交,而且底层还需要做 Raft 复制。如果一个事务非常大,提交过程会非常慢,事务写冲突概率会增加,而且事务失败后回滚会导致不必要的性能开销。所以我们设置了 key-value entry 的总大小默认不超过 100MB。如果业务需要使用大事务,可以修改配置文件中的 `txn-total-size-limit` 配置项进行调整,最大可以修改到 10G。实际的大小限制还受机器的物理内存影响。 + +在 Google 的 Cloud Spanner 上面,也有类似的[限制](https://cloud.google.com/spanner/docs/limits)。 + +### 如何批量导入? + +导入数据的时候,可以分批插入,每批最好不要超过 1w 行。 + +### TiDB 中删除数据后会立即释放空间吗? + +DELETE,TRUNCATE 和 DROP 都不会立即释放空间。对于 TRUNCATE 和 DROP 操作,在达到 TiDB 的 GC (garbage collection) 时间后(默认 10 分钟),TiDB 的 GC 机制会删除数据并释放空间。对于 DELETE 操作 TiDB 的 GC 机制会删除数据,但不会释放空间,而是当后续数据写入 RocksDB 且进行 compact 时对空间重新利用。 + +### Load 数据时可以对目标表执行 DDL 操作吗? + +不可以,加载数据期间不能对目标表执行任何 DDL 操作,这会导致数据加载失败。 + +### TiDB 是否支持 replace into 语法? + +支持,但是 load data 不支持 replace into 语法。 + +### 数据删除后查询速度为何会变慢? + +大量删除数据后,会有很多无用的 key 存在,影响查询效率。目前正在开发 Region Merge 功能,完善之后可以解决这个问题,具体看参考[最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/)中的删除数据部分。 + +### 数据删除最高效最快的方式? + +在删除大量数据的时候,建议使用 `Delete * from t where xx limit 5000`(xx 建议在满足业务过滤逻辑下,尽量加上强过滤索引列或者直接使用主键选定范围,如 `id >= 5000*n+m and id <= 5000*(n+1)+m` 这样的方案,通过循环来删除,用 `Affected Rows == 0` 作为循环结束条件,这样避免遇到事务大小的限制。如果一次删除的数据量非常大,这种循环的方式会越来越慢,因为每次删除都是从前向后遍历,前面的删除之后,短时间内会残留不少删除标记(后续会被 GC 掉),影响后面的 Delete 语句。如果有可能,建议把 Where 条件细化。可以参考官网[最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/)。 + +### TiDB 如何提高数据加载速度? + +主要有两个方面: + +- 目前已开发分布式导入工具 [Lightning](/tidb-lightning/tidb-lightning-overview.md),需要注意的是数据导入过程中为了性能考虑,不会执行完整的事务流程,所以没办法保证导入过程中正在导入的数据的 ACID 约束,只能保证整个导入过程结束以后导入数据的 ACID 约束。因此适用场景主要为新数据的导入(比如新的表或者新的索引),或者是全量的备份恢复(先 Truncate 原表再导入)。 +- TiDB 的数据加载与磁盘以及整体集群状态相关,加载数据时应关注该主机的磁盘利用率,TiClient Error/Backoff/Thread CPU 等相关 metric,可以分析相应瓶颈。 + +### 对数据做删除操作之后,空间回收比较慢,如何处理? + +可以设置并行 GC,加快对空间的回收速度。默认并发为 1,最大可调整为 tikv 实例数量的 50%。可使用 `update mysql.tidb set VARIABLE_VALUE="3" where VARIABLE_NAME="tikv_gc_concurrency";` 命令来调整。 diff --git a/faq/sql-faq.md b/faq/sql-faq.md new file mode 100644 index 000000000000..96bde8a0f608 --- /dev/null +++ b/faq/sql-faq.md @@ -0,0 +1,221 @@ +--- +title: SQL 操作常见问题 +summary: 介绍 SQL 操作相关的常见问题。 +category: FAQ +--- + +# SQL 操作常见问题 + +本文档介绍 TiDB 中常见的 SQL 操作问题。 + +## TiDB 对哪些 MySQL variables 兼容? + +详细可参考[系统变量](/system-variables.md)。 + +## TiDB 是否支持 select for update? + +支持,但语义上和 MySQL 有区别,TiDB 是分布式数据库,3.0.8 版本前,采用的乐观锁机制,也就说 select for update 不在事务开启就锁住数据,而是其他事务在提交的时候进行冲突检查,如有冲突,会进行回滚。3.0.8 版本之后,默认采用悲观锁机制,行为和 MySQL 基本一致,SELECT FOR UPDATE 会读取已提交的最新数据,并对读取到的数据加悲观锁。 + +## TiDB 的 codec 能保证 UTF8 的字符串是 memcomparable 的吗?我们的 key 需要支持 UTF8,有什么编码建议吗? + +TiDB 字符集默认就是 UTF8 而且目前只支持 UTF8,字符串就是 memcomparable 格式的。 + +## 一个事务中的语句数量最大是多少? + +一个事务中的语句数量,默认限制最大为 5000 条。 + +## TiDB 中,为什么出现后插入数据的自增 ID 反而小? + +TiDB 的自增 ID (`AUTO_INCREMENT`) 只保证自增且唯一,并不保证连续分配。TiDB 目前采用批量分配的方式,所以如果在多台 TiDB 上同时插入数据,分配的自增 ID 会不连续。当多个线程并发往不同的 tidb-server 插入数据的时候,有可能会出现后插入的数据自增 ID 小的情况。此外,TiDB允许给整型类型的字段指定 AUTO_INCREMENT,且一个表只允许一个属性为 `AUTO_INCREMENT` 的字段。详情可参考[CREATE TABLE 语法](/mysql-compatibility.md#自增-id)。 + +## sql_mode 默认除了通过命令 set 修改,配置文件怎么修改? + +TiDB 的 sql_mode 与 MySQL 的 sql_mode 设置方法有一些差别,TiDB 不支持配置文件配置设置数据库的 sql\_mode,而只能使用 set 命令去设置,具体方法为:`set @@global.sql_mode = 'STRICT_TRANS_TABLES';`。 + +## 用 Sqoop 批量写入 TiDB 数据,虽然配置了 `--batch` 选项,但还是会遇到 `java.sql.BatchUpdateExecption:statement count 5001 exceeds the transaction limitation` 的错误,该如何解决? + +- 在 Sqoop 中,`--batch` 是指每个批次提交 100 条 statement,但是默认每个 statement 包含 100 条 SQL 语句,所以此时 100 * 100 = 10000 条 SQL 语句,超出了 TiDB 的事务限制 5000 条,可以增加选项 `-Dsqoop.export.records.per.statement=10` 来解决这个问题,完整的用法如下: + + {{< copyable "shell-regular" >}} + + ```bash + sqoop export \ + -Dsqoop.export.records.per.statement=10 \ + --connect jdbc:mysql://mysql.example.com/sqoop \ + --username sqoop ${user} \ + --password ${passwd} \ + --table ${tab_name} \ + --export-dir ${dir} \ + --batch + ``` + +- 也可以选择增大 tidb 的单个事物语句数量限制,不过这个会导致内存上涨。 + +## TiDB 有像 Oracle 那样的 Flashback Query 功能么,DDL 支持么? + +有,也支持 DDL。详细参考 [TiDB 历史数据回溯](/read-historical-data.md)。 + +## TiDB 中删除数据后会立即释放空间吗? + +DELETE,TRUNCATE 和 DROP 都不会立即释放空间。对于 TRUNCATE 和 DROP 操作,在达到 TiDB 的 GC (garbage collection) 时间后(默认 10 分钟),TiDB 的 GC 机制会删除数据并释放空间。对于 DELETE 操作 TiDB 的 GC 机制会删除数据,但不会释放空间,而是当后续数据写入 RocksDB 且进行 compact 时对空间重新利用。 + +## TiDB 是否支持 replace into 语法? + +支持,但是 load data 不支持 replace into 语法。 + +## 数据删除后查询速度为何会变慢? + +大量删除数据后,会有很多无用的 key 存在,影响查询效率。可以尝试开启 [Region Merge](/best-practices/massive-regions-best-practices.md#方法五开启-region-merge) 功能,具体看参考[最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/)中的删除数据部分。 + +## 对数据做删除操作之后,空间回收比较慢,如何处理? + +可以设置并行 GC,加快对空间的回收速度。默认并发为 1,最大可调整为 tikv 实例数量的 50%。可使用 `update mysql.tidb set VARIABLE_VALUE="3" where VARIABLE_NAME="tikv_gc_concurrency";` 命令来调整。 + +## show processlist 是否显示系统进程号? + +TiDB 的 `show processlist` 与 MySQL 的 `show processlist` 显示内容基本一样,不会显示系统进程号,而 ID 表示当前的 session ID。其中 TiDB 的 `show processlist` 和 MySQL 的 `show processlist` 区别如下: + ++ 由于 TiDB 是分布式数据库,TiDB server 实例是无状态的 SQL 解析和执行引擎(详情可参考 [TiDB 整体架构](/overview.md#tidb-整体架构)),用户使用 MySQL 客户端登录的是哪个 TiDB server ,`show processlist` 就会显示当前连接的这个 TiDB server 中执行的 session 列表,不是整个集群中运行的全部 session 列表;而 MySQL 是单机数据库,`show processlist` 列出的是当前整个 MySQL 数据库的全部执行 SQL 列表。 + ++ TiDB 的 `show processlist` 显示内容比起 MySQL 来讲,多了一个当前 session 使用内存的估算值(单位 Byte)。 + +## 在 TiDB 中如何控制或改变 SQL 提交的执行优先级? + +TiDB 支持改变 [per-session](/tidb-specific-system-variables.md#tidb_force_priority)、[全局](/tidb-configuration-file.md#force-priority)或单个语句的优先级。优先级包括: + +- HIGH_PRIORITY:该语句为高优先级语句,TiDB 在执行阶段会优先处理这条语句 +- LOW_PRIORITY:该语句为低优先级语句,TiDB 在执行阶段会降低这条语句的优先级 + +以上两种参数可以结合 TiDB 的 DML 语言进行使用,使用方法举例如下: + +1. 通过在数据库中写 SQL 的方式来调整优先级: + + {{< copyable "sql" >}} + + ```sql + select HIGH_PRIORITY | LOW_PRIORITY count(*) from table_name; + insert HIGH_PRIORITY | LOW_PRIORITY into table_name insert_values; + delete HIGH_PRIORITY | LOW_PRIORITY from table_name; + update HIGH_PRIORITY | LOW_PRIORITY table_reference set assignment_list where where_condition; + replace HIGH_PRIORITY | LOW_PRIORITY into table_name; + ``` + +2. 全表扫会自动调整为低优先级,analyze 也是默认低优先级。 + +## 在 TiDB 中 auto analyze 的触发策略是怎样的? + +触发策略:新表达到 1000 条,并且在 1 分钟内没有写入,会自动触发。 + +当表的(修改数/当前总行数)大于 `tidb_auto_analyze_ratio` 的时候,会自动触发 `analyze` 语句。`tidb_auto_analyze_ratio` 的默认值为 0.5,即默认开启此功能。为了保险起见,在开启此功能的时候,保证了其最小值为 0.3。但是不能大于等于 `pseudo-estimate-ratio`(默认值为 0.8),否则会有一段时间使用 pseudo 统计信息,建议设置值为 0.5。 + +## SQL 中如何通过 hint 使用一个具体的 index? + +同 MySQL 的用法一致,例如: +`select column_name from table_name use index(index_name)where where_condition;` + +## 触发 Information schema is changed 错误的原因? + +TiDB 在执行 SQL 语句时,会使用当时的 `schema` 来处理该 SQL 语句,而且 TiDB 支持在线异步变更 DDL。那么,在执行 DML 的时候可能有 DDL 语句也在执行,而你需要确保每个 SQL 语句在同一个 `schema` 上执行。所以当执行 DML 时,遇到正在执行中的 DDL 操作就可能会报 `Information schema is changed` 的错误。为了避免太多的 DML 语句报错,已做了一些优化。 + +现在会报此错的可能原因如下(后两个报错原因与表无关): + +- 执行的 DML 语句中涉及的表和集群中正在执行的 DDL 的表有相同的,那么这个 DML 语句就会报此错。 +- 这个 DML 执行时间很久,而这段时间内执行了很多 DDL 语句,导致中间 `schema` 版本变更次数超过 1024 (此为默认值,可以通过 `tidb_max_delta_schema_count` 变量修改)。 +- 接受 DML 请求的 TiDB 长时间不能加载到 `schema information`(TiDB 与 PD 或 TiKV 之间的网络连接故障等会导致此问题),而这段时间内执行了很多 DDL 语句,导致中间 `schema` 版本变更次数超过 100。 + +> **注意:** +> +> + 目前 TiDB 未缓存所有的 `schema` 版本信息。 +> + 对于每个 DDL 操作,`schema` 版本变更的数量与对应 `schema state` 变更的次数一致。 +> + 不同的 DDL 操作版本变更次数不一样。例如,`create table` 操作会有 1 次 `schema` 版本变更;`add column` 操作有 4 次 `schema` 版本变更。 + +## 触发 Information schema is out of date 错误的原因? + +当执行 DML 时,TiDB 超过一个 DDL lease 时间(默认 45s)没能加载到最新的 schema 就可能会报 `Information schema is out of date` 的错误。遇到此错的可能原因如下: + +- 执行此 DML 的 TiDB 被 kill 后准备退出,且此 DML 对应的事务执行时间超过一个 DDL lease,在事务提交时会报这个错误。 +- TiDB 在执行此 DML 时,有一段时间内连不上 PD 或者 TiKV,导致 TiDB 超过一个 DDL lease 时间没有 load schema,或者导致 TiDB 断开与 PD 之间带 keep alive 设置的连接。 + +## 高并发情况下执行 DDL 时报错的原因? + +高并发情况下执行 DDL(比如批量建表)时,极少部分 DDL 可能会由于并发执行时 key 冲突而执行失败。 + +并发执行 DDL 时,建议将 DDL 数量保持在 20 以下,否则你需要在应用端重试失败的 DDL 语句。 + +## SQL 优化 + +### TiDB 执行计划解读 + +详细解读 [理解 TiDB 执行计划](/query-execution-plan.md)。 + +### 统计信息收集 + +详细解读 [统计信息](/statistics.md)。 + +### Count 如何加速? + +Count 就是暴力扫表,提高并发度能显著的提升速度,修改并发度可以参考 `tidb_distsql_scan_concurrency` 变量,但是也要看 CPU 和 I/O 资源。TiDB 每次查询都要访问 TiKV,在数据量小的情况下,MySQL 都在内存里,TiDB 还需要进行一次网络访问。 + +提升建议: + +- 建议提升硬件配置,可以参考[部署建议](/hardware-and-software-requirements.md)。 +- 提升并发度,默认是 10,可以提升到 50 试试,但是一般提升在 2-4 倍之间。 +- 测试大数据量的 count。 +- 调优 TiKV 配置,可以参考[性能调优](/tune-tikv-memory-performance.md)。 + +### 查看当前 DDL 的进度? + +通过 `admin show ddl` 查看当前 job 进度。操作如下: + +{{< copyable "sql" >}} + +```sql +admin show ddl; +``` + +```sql +*************************** 1. row *************************** + SCHEMA_VER: 140 + OWNER: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc +RUNNING_JOBS: ID:121, Type:add index, State:running, SchemaState:write reorganization, SchemaID:1, TableID:118, RowCount:77312, ArgLen:0, start time: 2018-12-05 16:26:10.652 +0800 CST, Err:, ErrCount:0, SnapshotVersion:404749908941733890 + SELF_ID: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc +``` + +从上面操作结果可知,当前正在处理的是 `add index` 操作。且从 `RUNNING_JOBS` 列的 `RowCount` 字段可以知道当前 `add index` 操作已经添加了 77312 行索引。 + +### 如何查看 DDL job? + +可以使用 `admin show ddl` 语句查看正在运行的 DDL 作业。 + +- `admin show ddl jobs`:用于查看当前 DDL 作业队列中的所有结果(包括正在运行以及等待运行的任务)以及已执行完成的 DDL 作业队列中的最近十条结果。 +- `admin show ddl job queries 'job_id' [, 'job_id'] ...`:用于显示 `job_id` 对应的 DDL 任务的原始 SQL 语句。此 `job_id` 只搜索正在执行中的任务以及 DDL 历史作业队列中的最近十条结果。 + +### TiDB 是否支持基于 COST 的优化(CBO),如果支持,实现到什么程度? + +是的,TiDB 使用的基于成本的优化器(CBO),我们有一个小组单独会对代价模型、统计信息持续优化,除此之外,我们支持 hash join、soft merge 等关联算法。 + +### 如何确定某张表是否需要做 analyze ? + +可以通过 `show stats_healthy` 来查看 Healthy 字段,一般小于等于 60 的表需要做 analyze。 + +### SQL 的执行计划展开成了树,ID 的序号有什么规律吗?这棵树的执行顺序会是怎么样的? + +ID 没什么规律,只要是唯一就行,不过生成的时候,是有一个计数器,生成一个 plan 就加一,执行的顺序和序号无关,整个执行计划是一颗树,执行时从根节点开始,不断地向上返回数据。执行计划的理解,请参考[理解 TiDB 执行计划](/query-execution-plan.md)。 + +### TiDB 执行计划中,task cop 在一个 root 下,这个是并行的么? + +目前 TiDB 的计算任务隶属于两种不同的 task:cop task 和 root task。cop task 是指被下推到 KV 端分布式执行的计算任务,root task 是指在 TiDB 端单点执行的计算任务。一般来讲 root task 的输入数据是来自于 cop task 的;但是 root task 在处理数据的时候,TiKV 上的 cop task 也可以同时处理数据,等待 TiDB 的 root task 拉取,所以从这个观点上来看,他们是并行的;但是存在数据上下游关系;在执行的过程中,某些时间段其实也是并行的,第一个 cop task 在处理 [100, 200] 的数据,第二个 cop task 在处理 [1, 100] 的数据。执行计划的理解,请参考[理解 TiDB 执行计划](/query-execution-plan.md)。 + +## 数据库优化 + +### TiDB 参数及调整 + +详情参考 [TiDB 配置参数](/command-line-flags-for-tidb-configuration.md)。 + +### 如何打散热点 + +TiDB 中以 Region 分片来管理数据库,通常来讲,TiDB 的热点指的是 Region 的读写访问热点。而 TiDB 中对于 PK 非整数或没有 PK 的表,可以通过设置 `SHARD_ROW_ID_BITS` 来适度分解 Region 分片,以达到打散 Region 热点的效果。详情可参考官网 [TiDB 专用系统变量和语法](/tidb-specific-system-variables.md#shard_row_id_bits)中 `SHARD_ROW_ID_BITS` 的介绍。 + +### TiKV 性能参数调优 + +详情参考 [TiKV 性能参数调优](/tune-tikv-memory-performance.md)。 diff --git a/faq/tidb-faq.md b/faq/tidb-faq.md new file mode 100644 index 000000000000..d378c671841b --- /dev/null +++ b/faq/tidb-faq.md @@ -0,0 +1,169 @@ +--- +title: TiDB FAQ +category: FAQ +aliases: ['/docs-cn/stable/faq/tidb/'] +--- + +# FAQ + +## 一、 TiDB 介绍、架构、原理 + +### 1.1 TiDB 介绍及整体架构 + +#### 1.1.1 TiDB 整体架构 + +[TiDB 简介](/overview.md#tidb-简介) + +#### 1.1.2 TiDB 是什么? + +TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。 + +#### 1.1.3 TiDB 是基于 MySQL 开发的吗? + +不是,虽然 TiDB 支持 MySQL 语法和协议,但是 TiDB 是由 PingCAP 团队完全自主开发的产品。 + +#### 1.1.4 TiDB、TiKV、Placement Driver (PD) 主要作用? + +- TiDB 是 Server 计算层,主要负责 SQL 的解析、制定查询计划、生成执行器。 +- TiKV 是分布式 Key-Value 存储引擎,用来存储真正的数据,简而言之,TiKV 是 TiDB 的存储引擎。 +- PD 是 TiDB 集群的管理组件,负责存储 TiKV 的元数据,同时也负责分配时间戳以及对 TiKV 做负载均衡调度。 + +#### 1.1.5 TiDB 易用性如何? + +TiDB 使用起来很简单,可以将 TiDB 集群当成 MySQL 来用,你可以将 TiDB 用在任何以 MySQL 作为后台存储服务的应用中,并且基本上不需要修改应用代码,同时你可以用大部分流行的 MySQL 管理工具来管理 TiDB。 + +#### 1.1.6 TiDB 和 MySQL 兼容性如何? + +TiDB 目前还不支持触发器、存储过程、自定义函数、外键,除此之外,TiDB 支持绝大部分 MySQL 5.7 的语法。 + +详情参见[与 MySQL 兼容性对比](/mysql-compatibility.md)。 + +#### 1.1.7 TiDB 支持分布式事务吗? + +支持。无论是一个地方的几个节点,还是[跨多个数据中心的多个节点](/multi-data-centers-in-one-city-deployment.md),TiDB 均支持 ACID 分布式事务。 + +TiDB 事务模型灵感源自 Google Percolator 模型,主体是一个两阶段提交协议,并进行了一些实用的优化。该模型依赖于一个时间戳分配器,为每个事务分配单调递增的时间戳,这样就检测到事务冲突。在 TiDB 集群中,[PD](/architecture.md#pd-server) 承担时间戳分配器的角色。 + +#### 1.1.8 TiDB 支持哪些编程语言? + +只要支持 MySQL Client/Driver 的编程语言,都可以直接使用 TiDB。 + +#### 1.1.9 TiDB 是否支持其他存储引擎? + +是的,除了 TiKV 之外,TiDB 还支持一些流行的单机存储引擎,比如 GolevelDB、RocksDB、BoltDB 等。如果一个存储引擎是支持事务的 KV 引擎,并且能提供一个满足 TiDB 接口要求的 Client,即可接入 TiDB。 + +#### 1.1.10 除了官方文档,有没有其他 TiDB 知识获取途径? + +目前[官方文档](/overview.md#tidb-简介)是获取 TiDB 相关知识最主要、最及时的发布途径。除此之外,我们也有一些技术沟通群,如有需求可发邮件至 [info@pingcap.com](mailto:info@pingcap.com) 获取,以及 [AskTUG 网站](https://asktug.com) 与技术专家互动交流。 + +#### 1.1.11 TiDB 用户名长度限制? + +在 TiDB 中用户名最长为 32 字符。 + +#### 1.1.12 TiDB 是否支持 XA? + +虽然 TiDB 的 JDBC 驱动用的就是 MySQL JDBC(Connector / J),但是当使用 Atomikos 的时候,数据源要配置成类似这样的配置:`type="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"`。MySQL JDBC XADataSource 连接 TiDB 的模式目前是不支持的。MySQL JDBC 中配置好的 XADataSource 模式,只对 MySQL 数据库起作用(DML 去修改 redo 等)。 + +Atomikos 配好两个数据源后,JDBC 驱动都要设置成 XA 模式,然后 Atomikos 在操作 TM 和 RM(DB)的时候,会通过数据源的配置,发起带有 XA 指令到 JDBC 层,JDBC 层 XA 模式启用的情况下,会对 InnoDB(如果是 MySQL 的话)下发操作一连串 XA 逻辑的动作,包括 DML 去变更 redo log 等,就是两阶段递交的那些操作。TiDB 目前的引擎版本中,没有对上层应用层 JTA / XA 的支持,不解析这些 Atomikos 发过来的 XA 类型的操作。 + +MySQL 是单机数据库,只能通过 XA 来满足跨数据库事务,而 TiDB 本身就通过 Google 的 Percolator 事务模型支持分布式事务,性能稳定性比 XA 要高出很多,所以不会也不需要支持 XA。 + +### 1.2 TiDB 原理 + +#### 1.2.1 存储 TiKV + +##### 1.2.1.1 TiKV 详细解读 + +[三篇文章了解 TiDB 技术内幕 - 说存储](http://t.cn/RTKRRWv) + +#### 1.2.2 计算 TiDB + +##### 1.2.2.1 TiDB 详细解读 + +[三篇文章了解 TiDB 技术内幕 - 说计算](http://t.cn/RTKRkBh) + +#### 1.2.3 调度 PD + +##### 1.2.3.1 PD 详细解读 + +[三篇文章了解 TiDB 技术内幕 - 谈调度](http://t.cn/RTKEZ0U) + +## 二、Cloud TiDB + +### 2.1 公有云 + +#### 2.1.1 目前 Cloud TiDB 都支持哪些云厂商? + +Cloud TiDB 目前已经在京东云、UCloud 上线,都是数据库一级入口,欢迎大家使用。 + +另外,Cloud TiDB 还支持在 [Google GKE](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-on-gcp-gke/),[AWS EKS](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-on-aws-eks/) 和 [阿里云 ACK](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-on-alibaba-cloud/) 上部署使用。 + +## 三、故障排除 + +### 3.1 TiDB 自定义报错汇总 + +#### 3.1.1 ERROR 8005 (HY000) : Write Conflict, txnStartTS is stale + +可以检查 `tidb_disable_txn_auto_retry` 是否为 on。如是,将其设置为 off;如已经是 off,将 `tidb_retry_limit` 调大到不再发生该错误。 + +#### 3.1.2 ERROR 9001 (HY000) : PD Server Timeout + +请求 PD 超时,请检查 PD Server 状态/监控/日志以及 TiDB Server 与 PD Server 之间的网络。 + +#### 3.1.3 ERROR 9002 (HY000) : TiKV Server Timeout + +请求 TiKV 超时,请检查 TiKV Server 状态/监控/日志以及 TiDB Server 与 TiKV Server 之间的网络。 + +#### 3.1.4 ERROR 9003 (HY000) : TiKV Server is Busy + +TiKV 操作繁忙,一般出现在数据库负载比较高时,请检查 TiKV Server 状态/监控/日志。 + +#### 3.1.5 ERROR 9004 (HY000) : Resolve Lock Timeout + +清理锁超时,当数据库上承载的业务存在大量的事务冲突时,会遇到这种错误,请检查业务代码是否有锁争用。 + +#### 3.1.6 ERROR 9005 (HY000) : Region is unavailable + +访问的 Region 不可用,某个 Raft Group 不可用,如副本数目不足,出现在 TiKV 比较繁忙或者是 TiKV 节点停机的时候,请检查 TiKV Server 状态/监控/日志。 + +#### 3.1.7 ERROR 9006 (HY000) : GC life time is shorter than transaction duration + +`GC Life Time` 间隔时间过短,长事务本应读到的数据可能被清理了,可使用如下命令增加 `GC Life Time`: + +{{< copyable "sql" >}} + +```sql +update mysql.tidb set variable_value='30m' where variable_name='tikv_gc_life_time'; +``` + +其中 30m 代表仅清理 30 分钟前的数据,这可能会额外占用一定的存储空间。 + +#### 3.1.8 ERROR 9007 (HY000) : Write Conflict + +可以检查 `tidb_disable_txn_auto_retry` 是否为 on。如是,将其设置为 off;如已经是 off,将 `tidb_retry_limit` 调大到不再发生该错误。 + +### 3.2 MySQL 原生报错汇总 + +#### 3.2.1 ERROR 2013 (HY000): Lost connection to MySQL server during query 问题的排查方法? + +- log 中是否有 panic +- dmesg 中是否有 oom,命令:`dmesg -T | grep -i oom` +- 长时间没有访问,也会收到这个报错,一般是 tcp 超时导致的,tcp 长时间不用, 会被操作系统 kill。 + +#### 3.2.2 ERROR 1105 (HY000): other error: unknown error Wire Error(InvalidEnumValue(4004)) 是什么意思? + +这类问题一般是 TiDB 和 TiKV 版本不匹配,在升级过程尽量一起升级,避免版本 mismatch。 + +#### 3.2.3 ERROR 1148 (42000): the used command is not allowed with this TiDB version 问题的处理方法? + +这个问题是因为在执行 `LOAD DATA LOCAL` 语句的时候,MySQL 客户端不允许执行此语句(即 `local_infile` 选项为 0)。解决方法是在启动 MySQL 客户端时,用 `--local-infile=1` 选项。具体启动指令类似:`mysql --local-infile=1 -u root -h 127.0.0.1 -P 4000`。有些 MySQL 客户端需要设置而有些不需要设置,原因是不同版本的 MySQL 客户端对 `local-infile` 的默认值不同。 + +#### 3.2.4 ERROR 9001 (HY000): PD server timeout start timestamp may fall behind safe point + +这个报错一般是 TiDB 访问 PD 出了问题,TiDB 后台有个 worker 会不断地从 PD 查询 safepoint,如果超过 100s 查不成功就会报这个错。一般是因为 PD 磁盘操作过忙、反应过慢,或者 TiDB 和 PD 之间的网络有问题。TiDB 常见错误码请参考[错误码与故障诊断](/error-codes.md)。 + +### 3.3 TiDB 日志中的报错信息 + +#### 3.3.1 EOF + +当客户端或者 proxy 断开连接时,TiDB 不会立刻察觉连接已断开,而是等到开始往连接返回数据时,才发现连接已断开,此时日志会打印 EOF 错误。 diff --git a/faq/tidb-lightning.md b/faq/tidb-lightning.md deleted file mode 100644 index 864038c99cfc..000000000000 --- a/faq/tidb-lightning.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: TiDB Lightning 常见问题 -category: FAQ ---- - -# TiDB Lightning 常见问题 - -本文列出了一些使用 TiDB Lightning 时可能会遇到的问题与解决办法。 - ->**注意:** -> -> 使用 TiDB Lightning 的过程中如遇错误,参考 [TiDB Lightning 故障诊断](/how-to/troubleshoot/tidb-lightning.md)进行排查。 - -## TiDB Lightning 对 TiDB/TiKV/PD 的最低版本要求是多少? - -TiDB Lightning 的版本应与集群相同。最低版本要求是 2.0.9,但建议使用最新的稳定版本 3.0。 - -## TiDB Lightning 支持导入多个库吗? - -支持。 - -## TiDB Lightning 对下游数据库的账号权限要求是怎样的? - -TiDB Lightning 需要以下权限: - -* SELECT -* UPDATE -* ALTER -* CREATE -* DROP - -如果选择 [TiDB-backend](/reference/tools/tidb-lightning/tidb-backend.md) 模式,或目标数据库用于存储断点,则 TiBD Lightning 额外需要以下权限: - -* INSERT -* DELETE - -+Importer-backend 无需以上两个权限,因为数据直接被 Ingest 到 TiKV 中,所以绕过了 TiDB 的权限系统。只要 TiKV、TiKV Importer 和 TiDB Lightning 的端口在集群之外不可访问,就可以保证安全。 - -如果 TiDB Lightning 配置项 `checksum = true`,则 TiDB Lightning 需要有下游 TiDB admin 用户权限。 - -## TiDB Lightning 在导数据过程中某个表报错了,会影响其他表吗?进程会马上退出吗? - -如果只是个别表报错,不会影响整体。报错的那个表会停止处理,继续处理其他的表。 - -## 如何正确重启 TiDB Lightning? - -根据 `tikv-importer` 的状态,重启 TiDB Lightning 的基本顺序如下: - -如果 `tikv-importer` 仍在运行: - -1. [结束 `tidb-lightning` 进程](#如何正确结束-tidb-lightning-进程)。 -2. 执行修改操作(如修复数据源、更改设置、更换硬件等)。 -3. 如果上面的修改操作更改了任何表,你还需要[清除对应的断点](/reference/tools/tidb-lightning/checkpoints.md#--checkpoint-remove)。 -4. 重启 `tidb-lightning`。 - -如果 `tikv-importer` 需要重启: - -1. [结束 `tidb-lightning` 进程](#如何正确结束-tidb-lightning-进程)。 -2. [结束 `tikv-importer` 进程](#如何正确结束-tikv-importer-进程)。 -3. 执行修改操作(如修复数据源、更改设置、更换硬件等)。 -4. 重启 `tikv-importer`。 -5. 重启 `tidb-lightning` 并等待,**直到程序因校验和错误(如果有的话)而失败**。 - * 重启 `tikv-importer` 将清除所有仍在写入的引擎文件,但是 `tidb-lightning` 并不会感知到该操作。从 v3.0 开始,最简单的方法是让 `tidb-lightning` 继续,然后再重试。 -6. [清除失败的表及断点](/how-to/troubleshoot/tidb-lightning.md#checkpoint-for--has-invalid-status错误码)。 -7. 再次重启 `tidb-lightning`。 - -## 如何校验导入的数据的正确性? - -TiDB Lightning 默认会对导入数据计算校验和 (checksum),如果校验和不一致就会停止导入该表。可以在日志看到相关的信息。 - -TiDB 也支持从 MySQL 命令行运行 `ADMIN CHECKSUM TABLE` 指令来计算校验和。 - -{{< copyable "sql" >}} - -```sql -ADMIN CHECKSUM TABLE `schema`.`table`; -``` - -``` -+---------+------------+---------------------+-----------+-------------+ -| Db_name | Table_name | Checksum_crc64_xor | Total_kvs | Total_bytes | -+---------+------------+---------------------+-----------+-------------+ -| schema | table | 5505282386844578743 | 3 | 96 | -+---------+------------+---------------------+-----------+-------------+ -1 row in set (0.01 sec) -``` - -## TiDB Lightning 支持哪些格式的数据源? - -TiDB Lightning 只支持两种格式的数据源: - -1. [Mydumper](/reference/tools/mydumper.md) 生成的 SQL dump -2. 储存在本地文件系统的 [CSV](/reference/tools/tidb-lightning/csv.md) 文件 - -## 我已经在下游创建好库和表了,TiDB Lightning 可以忽略建库建表操作吗? - -可以。在配置文档中的 `[mydumper]` 部分将 `no-schema` 设置为 `true` 即可。`no-schema=true` 会默认下游已经创建好所需的数据库和表,如果没有创建,会报错。 - -## 有些不合法的数据,能否通过关掉严格 SQL 模式 (Strict SQL Mode) 来导入? - -可以。Lightning 默认的 [`sql_mode`](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html) 为 `"STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION"`。 - -这个设置不允许一些非法的数值,例如 `1970-00-00` 这样的日期。可以修改配置文件 `[tidb]` 下的 `sql-mode` 值。 - -```toml -... -[tidb] -sql-mode = "" -... -``` - -## 可以启用一个 `tikv-importer`,同时有多个 `tidb-lightning` 进程导入数据吗? - -只要每个 Lightning 操作的表互不相同就可以。 - -## 如何正确结束 `tikv-importer` 进程? - -根据部署方式,选择相应操作结束进程 - -- 使用 TiDB Ansible 部署:在 Importer 的服务器上运行 `scripts/stop_importer.sh`。 - -- 手动部署:如果 `tikv-importer` 正在前台运行,可直接按 Ctrl+C 退出。否则,可通过 `ps aux | grep tikv-importer` 获取进程 ID,然后通过 `kill «pid»` 结束进程。 - -## 如何正确结束 `tidb-lightning` 进程? - -根据部署方式,选择相应操作结束进程 - -- 使用 TiDB Ansible 部署:在 Lightning 的服务器上运行 `scripts/stop_lightning.sh`。 - -- 手动部署:如果 `tidb-lightning` 正在前台运行,可直接按 Ctrl+C 退出。否则,可通过 `ps aux | grep tidb-lightning` 获取进程 ID,然后通过 `kill -2 «pid»` 结束进程。 - -## `tidb-lightning` 在服务器上运行,进程莫名其妙地退出了,是怎么回事呢? - -这种情况可能是启动方式不正确,导致收到 SIGHUP 信号而退出。此时 `tidb-lightning.log` 通常有如下日志: - -``` -[2018/08/10 07:29:08.310 +08:00] [INFO] [main.go:41] ["got signal to exit"] [signal=hangup] -``` - -不推荐在命令行中直接使用 `nohup` 启动进程,推荐[使用脚本启动 `tidb-lightning`](/reference/tools/tidb-lightning/deployment.md)。 - -## 为什么用过 TiDB Lightning 之后,TiDB 集群变得又慢又耗 CPU? - -如果 `tidb-lightning` 曾经异常退出,集群可能仍留在“导入模式” (import mode),不适合在生产环境工作。此时需要强制切换回“普通模式” (normal mode): - -{{< copyable "shell-regular" >}} - -```sh -tidb-lightning-ctl --switch-mode=normal -``` - -## TiDB Lightning 可以使用千兆网卡吗? - -使用 TiDB Lightning 建议配置万兆网卡。**不推荐**使用千兆网卡,尤其是在部署 `tikv-importer` 的机器上。 - -千兆网卡的总带宽只有 120 MB/s,而且需要与整个 TiKV 集群共享。在使用 TiDB Lightning 导入时,极易用尽所有带宽,继而因 PD 无法联络集群使集群断连。为了避免这种情况,你可以在 [`tikv-importer` 的配置文件](/reference/tools/tidb-lightning/config.md#tikv-importer-配置参数)中**限制上传速度**。 - -```toml -[import] -# Importer 上传至 TiKV 的最大速度(字节/秒)。 -# 建议将该速度设为 100 MB/s 或更小。 -upload-speed-limit = "100MB" -``` - -## 为什么 TiDB Lightning 需要在 TiKV 集群预留这么多空间? - -当使用默认的 3 副本设置时,TiDB Lightning 需要 TiKV 集群预留数据源大小 6 倍的空间。多出来的 2 倍是算上下列没储存在数据源的因素的保守估计: - -- 索引会占据额外的空间 -- RocksDB 的空间放大效应 - -## TiDB Lightning 使用过程中是否可以重启 TiKV Importer? - -不能,Importer 会在内存中存储一些引擎文件,Importer 重启后,`tidb-lightning` 会因连接失败而停止。此时,你需要[清除失败的断点](/reference/tools/tidb-lightning/checkpoints.md#--checkpoint-error-destroy),因为这些 Importer 特有的信息丢失了。你可以在之后[重启 Lightning](#如何正确重启-tidb-lightning)。 - -## 如何清除所有与 TiDB Lightning 相关的中间数据? - -1. 删除断点文件。 - - {{< copyable "shell-regular" >}} - - ```sh - tidb-lightning-ctl --config conf/tidb-lightning.toml --checkpoint-remove=all - ``` - - 如果出于某些原因而无法运行该命令,你可以尝试手动删除 `/tmp/tidb_lightning_checkpoint.pb` 文件。 - -2. 删除 `tikv-importer` 所在机器上的整个 “import” 文件目录。 - -3. 如果需要的话,删除 TiDB 集群上创建的所有表和库。 diff --git a/faq/tidb.md b/faq/tidb.md deleted file mode 100755 index af0857482cb9..000000000000 --- a/faq/tidb.md +++ /dev/null @@ -1,1080 +0,0 @@ ---- -title: TiDB FAQ -category: FAQ ---- - -# FAQ - -## 一、 TiDB 介绍、架构、原理 - -### 1.1 TiDB 介绍及整体架构 - -#### 1.1.1 TiDB 整体架构 - -[TiDB 简介](/overview.md#tidb-简介) - -#### 1.1.2 TiDB 是什么? - -TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。 - -#### 1.1.3 TiDB 是基于 MySQL 开发的吗? - -不是,虽然 TiDB 支持 MySQL 语法和协议,但是 TiDB 是由 PingCAP 团队完全自主开发的产品。 - -#### 1.1.4 TiDB、TiKV、Placement Driver (PD) 主要作用? - -- TiDB 是 Server 计算层,主要负责 SQL 的解析、制定查询计划、生成执行器。 -- TiKV 是分布式 Key-Value 存储引擎,用来存储真正的数据,简而言之,TiKV 是 TiDB 的存储引擎。 -- PD 是 TiDB 集群的管理组件,负责存储 TiKV 的元数据,同时也负责分配时间戳以及对 TiKV 做负载均衡调度。 - -#### 1.1.5 TiDB 易用性如何? - -TiDB 使用起来很简单,可以将 TiDB 集群当成 MySQL 来用,你可以将 TiDB 用在任何以 MySQL 作为后台存储服务的应用中,并且基本上不需要修改应用代码,同时你可以用大部分流行的 MySQL 管理工具来管理 TiDB。 - -#### 1.1.6 TiDB 和 MySQL 兼容性如何? - -TiDB 目前还不支持触发器、存储过程、自定义函数、外键,除此之外,TiDB 支持绝大部分 MySQL 5.7 的语法。 - -详情参见[与 MySQL 兼容性对比](/reference/mysql-compatibility.md)。 - -#### 1.1.7 TiDB 具备高可用的特性吗? - -TiDB 天然具备高可用特性,TiDB、TiKV、PD 这三个组件都能容忍部分实例失效,不影响整个集群的可用性。具体见 [TiDB 高可用性](/key-features.md#高可用)。 - -#### 1.1.8 TiDB 数据是强一致的吗? - -TiDB 实现了快照隔离 (Snapshot Isolation) 级别的一致性。为与 MySQL 保持一致,又称其为“可重复读”。通过使用 [Raft 一致性算法](https://raft.github.io/),数据在各 TiKV 节点间复制为多副本,以确保某个节点挂掉时数据的安全性。 - -在底层,TiKV 使用复制日志 + 状态机 (State Machine) 的模型来复制数据。对于写入请求,数据被写入 Leader,然后 Leader 以日志的形式将命令复制到它的 Follower 中。当集群中的大多数节点收到此日志时,日志会被提交,状态机会相应作出变更。 - -#### 1.1.9 TiDB 支持分布式事务吗? - -支持。无论是一个地方的几个节点,还是[跨多个数据中心的多个节点](/how-to/deploy/geographic-redundancy/overview.md),TiDB 均支持 ACID 分布式事务。 - -TiDB 事务模型灵感源自 Google Percolator 模型,主体是一个两阶段提交协议,并进行了一些实用的优化。该模型依赖于一个时间戳分配器,为每个事务分配单调递增的时间戳,这样就检测到事务冲突。在 TiDB 集群中,[PD](/architecture.md#pd-server) 承担时间戳分配器的角色。 - -#### 1.1.10 TiDB 支持哪些编程语言? - -只要支持 MySQL Client/Driver 的编程语言,都可以直接使用 TiDB。 - -#### 1.1.11 TiDB 是否支持其他存储引擎? - -是的,除了 TiKV 之外,TiDB 还支持一些流行的单机存储引擎,比如 GolevelDB、RocksDB、BoltDB 等。如果一个存储引擎是支持事务的 KV 引擎,并且能提供一个满足 TiDB 接口要求的 Client,即可接入 TiDB。 - -#### 1.1.12 官方有没有三中心跨机房多活部署的推荐方案? - -从 TiDB 架构来讲,支持真正意义上的跨中心异地多活,从操作层面讲,依赖数据中心之间的网络延迟和稳定性,一般建议延迟在 5ms 以下,目前我们已经有相似客户方案,具体请咨询官方 [info@pingcap.com](mailto:info@pingcap.com)。 - -#### 1.1.13 除了官方文档,有没有其他 TiDB 知识获取途径? - -目前[官方文档](/overview.md#tidb-简介)是获取 TiDB 相关知识最主要、最及时的发布途径。除此之外,我们也有一些技术沟通群,如有需求可发邮件至 [info@pingcap.com](mailto:info@pingcap.com) 获取。 - -#### 1.1.14 TiDB 对哪些 MySQL variables 兼容? - -详细可参考[系统变量](/reference/configuration/tidb-server/mysql-variables.md)。 - -#### 1.1.15 TiDB 是否支持 select for update? - -支持,但语义上和 MySQL 有区别,TiDB 是分布式数据库,采用的乐观锁机制,也就说 select for update 不在事务开启就锁住数据,而是其他事务在提交的时候进行冲突检查,如有冲突,会进行回滚。 - -#### 1.1.16 TiDB 的 codec 能保证 UTF8 的字符串是 memcomparable 的吗?我们的 key 需要支持 UTF8,有什么编码建议吗? - -TiDB 字符集默认就是 UTF8 而且目前只支持 UTF8,字符串就是 memcomparable 格式的。 - -#### 1.1.17 TiDB 用户名长度限制? - -在 TiDB 中用户名最长为 32 字符。 - -#### 1.1.18 TiDB 是否支持 XA? - -虽然 TiDB 的 JDBC 驱动用的就是 MySQL JDBC(Connector / J),但是当使用 Atomikos 的时候,数据源要配置成类似这样的配置:`type="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"`。MySQL JDBC XADataSource 连接 TiDB 的模式目前是不支持的。MySQL JDBC 中配置好的 XADataSource 模式,只对 MySQL 数据库起作用(DML 去修改 redo 等)。 - -Atomikos 配好两个数据源后,JDBC 驱动都要设置成 XA 模式,然后 Atomikos 在操作 TM 和 RM(DB)的时候,会通过数据源的配置,发起带有 XA 指令到 JDBC 层,JDBC 层 XA 模式启用的情况下,会对 InnoDB(如果是 MySQL 的话)下发操作一连串 XA 逻辑的动作,包括 DML 去变更 redo log 等,就是两阶段递交的那些操作。TiDB 目前的引擎版本中,没有对上层应用层 JTA / XA 的支持,不解析这些 Atomikos 发过来的 XA 类型的操作。 - -MySQL 是单机数据库,只能通过 XA 来满足跨数据库事务,而 TiDB 本身就通过 Google 的 Percolator 事务模型支持分布式事务,性能稳定性比 XA 要高出很多,所以不会也不需要支持 XA。 - -#### 1.1.19 show processlist 是否显示系统进程号? - -TiDB 的 `show processlist` 与 MySQL 的 `show processlist` 显示内容基本一样,不会显示系统进程号,而 ID 表示当前的 session ID。其中 TiDB 的 `show processlist` 和 MySQL 的 `show processlist` 区别如下: - -1)由于 TiDB 是分布式数据库,tidb-server 实例是无状态的 SQL 解析和执行引擎(详情可参考 [TiDB 整体架构](/overview.md#tidb-整体架构)),用户使用 MySQL 客户端登录的是哪个 tidb-server,`show processlist` 就会显示当前连接的这个 tidb-server 中执行的 session 列表,不是整个集群中运行的全部 session 列表;而 MySQL 是单机数据库,`show processlist` 列出的是当前整个 MySQL 数据库的全部执行 SQL 列表。 - -2)TiDB 的 `show processlist` 显示内容比起 MySQL 来讲,多了一个当前 session 使用内存的估算值(单位 Byte)。 - -#### 1.1.20 如何修改用户名密码和权限? - -TiDB 作为分布式数据库,在 TiDB 中修改用户密码建议使用 `set password for 'root'@'%' = '0101001';` 或 `alter` 方法,不推荐使用 `update mysql.user` 的方法进行,这种方法可能会造成其它节点刷新不及时的情况。修改权限也一样,都建议采用官方的标准语法。详情可参考 [TiDB 用户账户管理](/reference/security/user-account-management.md)。 - -#### 1.1.21 TiDB 中,为什么出现后插入数据的自增 ID 反而小? - -TiDB 的自增 ID (`AUTO_INCREMENT`) 只保证自增且唯一,并不保证连续分配。TiDB 目前采用批量分配的方式,所以如果在多台 TiDB 上同时插入数据,分配的自增 ID 会不连续。当多个线程并发往不同的 tidb-server 插入数据的时候,有可能会出现后插入的数据自增 ID 小的情况。此外,TiDB允许给整型类型的字段指定 AUTO_INCREMENT,且一个表只允许一个属性为 `AUTO_INCREMENT` 的字段。详情可参考[CREATE TABLE 语法](/reference/mysql-compatibility.md#自增-id)。 - -#### 1.1.22 sql_mode 默认除了通过命令 set 修改,配置文件怎么修改? - -TiDB 的 sql_mode 与 MySQL 的 sql_mode 设置方法有一些差别,TiDB 不支持配置文件配置设置数据库的 sql\_mode,而只能使用 set 命令去设置,具体方法为:`set @@global.sql_mode = 'STRICT_TRANS_TABLES';`。 - -#### 1.1.23 我们的安全漏洞扫描工具对 MySQL version 有要求,TiDB 是否支持修改 server 版本号呢? - -TiDB 在 v3.0.8 后支持修改 server 版本号,可以通过配置文件中的 [`server-version`](/reference/configuration/tidb-server/configuration-file.md#server-version) 配置项进行修改。在使用 TiDB Ansible 部署集群时,同样可以通过 `conf/tidb.yml` 配置文件中的 `server-version` 来设置合适的版本号,以避免出现安全漏洞扫描不通过的问题。 - -#### 1.1.24 TiDB 支持哪些认证协议,过程是怎样的? - -这一层跟 MySQL 一样,走的 SASL 认证协议,用于用户登录认证,对密码的处理流程。 - -客户端连接 TiDB 的时候,走的是 challenge-response(挑战-应答)的认证模式,过程如下: - -第一步:客户端连接服务器; - -第二步:服务器发送随机字符串 challenge 给客户端; - -第三步:客户端发送 username + response 给服务器; - -第四步:服务器验证 response。 - -### 1.2 TiDB 原理 - -#### 1.2.1 存储 TiKV - -##### 1.2.1.1 TiKV 详细解读 - -[三篇文章了解 TiDB 技术内幕 - 说存储](http://t.cn/RTKRRWv) - -#### 1.2.2 计算 TiDB - -##### 1.2.2.1 TiDB 详细解读 - -[三篇文章了解 TiDB 技术内幕 - 说计算](http://t.cn/RTKRkBh) - -#### 1.2.3 调度 PD - -##### 1.2.3.1 PD 详细解读 - -[三篇文章了解 TiDB 技术内幕 - 谈调度](http://t.cn/RTKEZ0U) - -## 二、安装部署升级 - -### 2.1 环境准备 - -#### 2.1.1 操作系统版本要求 - -| **Linux 操作系统平台** | **版本** | -| --- | --- | -| Red Hat Enterprise Linux | 7.3 及以上 | -| CentOS | 7.3 及以上 | -| Oracle Enterprise Linux | 7.3 及以上 | - -##### 2.1.1.1 为什么要在 CentOS 7 上部署 TiDB 集群? - -TiDB 作为一款开源分布式 NewSQL 数据库,可以很好的部署和运行在 Intel 架构服务器环境及主流虚拟化环境,并支持绝大多数的主流硬件网络,作为一款高性能数据库系统,TiDB 支持主流的 Linux 操作系统环境,具体可以参考 TiDB 的[官方部署要求](/how-to/deploy/hardware-recommendations.md)。其中 TiDB 在 CentOS 7.3 的环境下进行大量的测试,同时也有很多这个操作系统的部署最佳实践,因此,我们推荐客户在部署 TiDB 的时候使用 CentOS 7.3+ 以上的Linux 操作系统。 - -#### 2.1.2 硬件要求 - -TiDB 支持部署和运行在 Intel x86-64 架构的 64 位通用硬件服务器平台。对于开发,测试,及生产环境的服务器硬件配置有以下要求和建议: - -##### 2.1.2.1 开发及测试环境 - -| **组件** | **CPU** | **内存** | **本地存储** | **网络** | **实例数量(最低要求)** | -| --- | --- | --- | --- | --- | --- | -| TiDB | 8核+ | 16 GB+ | SAS, 200 GB+ | 千兆网卡 | 1(可与 PD 同机器) | -| PD | 8核+ | 16 GB+ | SAS, 200 GB+ | 千兆网卡 | 1(可与 TiDB 同机器) | -| TiKV | 8核+ | 32 GB+ | SSD, 200 GB+ | 千兆网卡 | 3 | -| | | | | 服务器总计 | 4 | - -##### 2.1.2.2 线上环境 - -| **组件** | **CPU** | **内存** | **硬盘类型** | **网络** | **实例数量(最低要求)** | -| --- | --- | --- | --- | --- | --- | -| TiDB | 16核+ | 48 GB+ | SAS | 万兆网卡(2块最佳) | 2 | -| PD | 8核+ | 16 GB+ | SSD | 万兆网卡(2块最佳) | 3 | -| TiKV | 16核+ | 48 GB+ | SSD | 万兆网卡(2块最佳) | 3 | -| 监控 | 8核+ | 16 GB+ | SAS | 千兆网卡 | 1 | -| | | | | 服务器总计 | 9 | - -##### 2.1.2.3 2 块网卡的目的是?万兆的目的是? - -作为一个分布式集群,TiDB 对时间的要求还是比较高的,尤其是 PD 需要分发唯一的时间戳,如果 PD 时间不统一,如果有 PD 切换,将会等待更长的时间。2 块网卡可以做 bond,保证数据传输的稳定,万兆可以保证数据传输的速度,千兆网卡容易出现瓶颈,我们强烈建议使用万兆网卡。 - -##### 2.1.2.4 SSD 不做 RAID 是否可行? - -资源可接受的话,我们建议做 RAID 10,如果资源有限,也可以不做 RAID。 - -##### 2.1.2.5 TiDB 集群各个组件的配置推荐? - -- TiDB 需要 CPU 和内存比较好的机器,参考官网配置要求,如果后期需要开启 Binlog,根据业务量的评估和 GC 时间的要求,也需要本地磁盘大一点,不要求 SSD 磁盘; -- PD 里面存了集群元信息,会有频繁的读写请求,对磁盘 I/O 要求相对比较高,磁盘太差会影响整个集群性能,推荐 SSD 磁盘,空间不用太大。另外集群 Region 数量越多对 CPU、内存的要求越高; -- TiKV 对 CPU、内存、磁盘要求都比较高,一定要用 SSD 磁盘。 - -详情可参考 [TiDB 软硬件环境需求](/how-to/deploy/hardware-recommendations.md)。 - -### 2.2 安装部署 - -#### 2.2.1 TiDB Ansible 部署方式(强烈推荐) - -详细可参考[使用 TiDB Ansible 部署 TiDB 集群](/how-to/deploy/orchestrated/ansible.md)。 - -##### 2.2.1.1 为什么修改了 TiKV/PD 的 toml 配置文件,却没有生效? - -这种情况一般是因为没有使用 `--config` 参数来指定配置文件(目前只会出现在 binary 部署的场景),TiKV/PD 会按默认值来设置。如果要使用配置文件,请设置 TiKV/PD 的 `--config` 参数。对于 TiKV 组件,修改配置后重启服务即可;对于 PD 组件,只会在第一次启动时读取配置文件,之后可以使用 pd-ctl 的方式来修改配置,详情可参考 [PD 配置参数](/reference/configuration/pd-server/configuration.md)。 - -##### 2.2.1.2 TiDB 监控框架 Prometheus + Grafana 监控机器建议单独还是多台部署? - -监控机建议单独部署。建议 CPU 8 core,内存 16 GB 以上,硬盘 500 GB 以上。 - -##### 2.2.1.3 有一部分监控信息显示不出来? - -查看访问监控的机器时间跟集群内机器的时间差,如果比较大,更正时间后即可显示正常。 - -##### 2.2.1.4 supervise/svc/svstat 服务具体起什么作用? - -- supervise 守护进程 -- svc 启停服务 -- svstat 查看进程状态 - -##### 2.2.1.5 inventory.ini 变量参数解读 - -| **变量** | **含义** | -| --- | --- | -| cluster_name | 集群名称,可调整 | -| tidb_version | TiDB 版本,TiDB Ansible 各分支默认已配置 | -| deployment_method | 部署方式,默认为 binary,可选 docker | -| process_supervision | 进程监管方式,默认为 systemd,可选 supervise | -| timezone | 修改部署目标机器时区,默认为 Asia/Shanghai, 可调整,与set_timezone 变量结合使用 | -| set_timezone | 默认为 True,即修改部署目标机器时区,关闭可修改为 False | -| enable_elk | 目前不支持,请忽略 | -| enable_firewalld | 开启防火墙,默认不开启 | -| enable_ntpd | 检测部署目标机器 NTP 服务,默认为 True,请勿关闭 | -| machine_benchmark | 检测部署目标机器磁盘 IOPS,默认为 True,请勿关闭 | -| set_hostname | 根据 IP 修改部署目标机器主机名,默认为 False | -| enable_binlog | 是否部署 pump 并开启 binlog,默认为 False,依赖 Kafka 集群,参见 zookeeper_addrs 变量 | -| zookeeper_addrs | binlog Kafka 集群的 zookeeper 地址 | -| enable_slow_query_log | TiDB 慢查询日志记录到单独文件({{ deploy_dir }}/log/tidb_slow_query.log),默认为 False,记录到 tidb 日志 | -| deploy_without_tidb | KV 模式,不部署 TiDB 服务,仅部署 PD、TiKV 及监控服务,请将 inventory.ini 文件中 tidb_servers 主机组 IP 设置为空。 | - -#### 2.2.2 TiDB 离线 Ansible 部署方案 - -首先这不是我们建议的方式,如果中控机没有外网,也可以通过离线 Ansible 部署方式,详情可参考[离线 TiDB Ansible 部署方案](/how-to/deploy/orchestrated/offline-ansible.md)。 - -#### 2.2.3 Docker Compose 快速构建集群(单机部署) - -使用 docker-compose 在本地一键拉起一个集群,包括集群监控,还可以根据需求自定义各个组件的软件版本和实例个数,以及自定义配置文件,这种只限于开发环境,详细可参考[官方文档](/how-to/get-started/deploy-tidb-from-docker-compose.md)。 - -#### 2.2.4 如何单独记录 TiDB 中的慢查询日志,如何定位慢查询 SQL? - -1)TiDB 中,对慢查询的定义在 tidb-ansible 的 `conf/tidb.yml` 配置文件中,`slow-threshold: 300`,这个参数是配置慢查询记录阈值的,单位是 ms。 - -慢查询日志默认记录到 tidb.log 中,如果希望生成单独的慢查询日志文件,修改 inventory.ini 配置文件的参数 `enable_slow_query_log` 为 True。 - -如上配置修改之后,需要执行 `ansible-playbook rolling_update.yml --tags=tidb`,对 tidb-server 实例进行滚动升级,升级完成后,tidb-server 将在 `tidb_slow_query.log` -文件中记录慢查询日志。 - -2)如果出现了慢查询,可以从 Grafana 监控定位到出现慢查询的 tidb-server 以及时间点,然后在对应节点查找日志中记录的 SQL 信息。 - -3)除了日志,还可以通过 `admin show slow` 命令查看,详情可参考 [`admin show slow` 命令](/how-to/maintain/identify-abnormal-queries/identify-slow-queries.md#admin-show-slow-命令)。 - -#### 2.2.5 首次部署 TiDB 集群时,没有配置 tikv 的 Label 信息,在后续如何添加配置 Label? - -TiDB 的 Label 设置是与集群的部署架构相关的,是集群部署中的重要内容,是 PD 进行全局管理和调度的依据。如果集群在初期部署过程中没有设置 Label,需要在后期对部署结构进行调整,就需要手动通过 PD 的管理工具 pd-ctl 来添加 location-labels 信息,例如:`config set location-labels "zone,rack,host"`(根据实际的 label 层级名字配置)。 - -pd-ctl 的使用参考 [PD Control 使用说明](/reference/tools/pd-control.md)。 - -#### 2.2.6 为什么测试磁盘的 dd 命令用 oflag=direct 这个选项? - -Direct 模式就是把写入请求直接封装成 I/O 指令发到磁盘,这样是为了绕开文件系统的缓存,可以直接测试磁盘的真实的 I/O 读写能力。 - -#### 2.2.7 如何用 fio 命令测试 TiKV 实例的磁盘性能? - -- 随机读测试: - - {{< copyable "shell-regular" >}} - - ```bash - ./fio -ioengine=psync -bs=32k -fdatasync=1 -thread -rw=randread -size=10G -filename=fio_randread_test.txt -name='fio randread test' -iodepth=4 -runtime=60 -numjobs=4 -group_reporting --output-format=json --output=fio_randread_result.json - ``` - -- 顺序写和随机读混合测试: - - {{< copyable "shell-regular" >}} - - ```bash - ./fio -ioengine=psync -bs=32k -fdatasync=1 -thread -rw=randrw -percentage_random=100,0 -size=10G -filename=fio_randread_write_test.txt -name='fio mixed randread and sequential write test' -iodepth=4 -runtime=60 -numjobs=4 -group_reporting --output-format=json --output=fio_randread_write_test.json - ``` - -#### 2.2.8 使用 TiDB Ansible 部署 TiDB 集群的时候,遇到 `UNREACHABLE! "msg": "Failed to connect to the host via ssh: "` 报错是什么原因? - -有两种可能性: - -- ssh 互信的准备工作未做好,建议严格参照我们的[官方文档步骤](/how-to/deploy/orchestrated/ansible.md)配置互信,并使用命令 `ansible -i inventory.ini all -m shell -a 'whoami' -b` 来验证互信配置是否成功。 - -- 如果涉及到单服务器分配了多角色的场景,例如多组件混合部署或单台服务器部署了多个 TiKV 实例,可能是由于 ssh 复用的机制引起这个报错,可以使用 `ansible … -f 1` 的选项来规避这个报错。 - -### 2.3 升级 - -#### 2.3.1 如何使用 TiDB Ansible 滚动升级? - -滚动升级 TiKV 节点( 只升级单独服务 ) - -`ansible-playbook rolling_update.yml --tags=tikv` - -滚动升级所有服务 - -`ansible-playbook rolling_update.yml` - -#### 2.3.2 滚动升级有那些影响? - -滚动升级 TiDB 服务,滚动升级期间不影响业务运行,需要配置最小集群拓扑(TiDB \* 2、PD \* 3、TiKV \* 3),如果集群环境中有 Pump/Drainer 服务,建议先停止 Drainer 后滚动升级(升级 TiDB 时会升级 Pump)。 - -#### 2.3.3 Binary 如何升级? - -Binary 不是我们建议的安装方式,对升级支持也不友好,建议换成 TiDB Ansible 部署。 - -#### 2.3.4 一般升级选择升级 TiKV 还是所有组件都升级? - -常规需要一起升,因为整个版本都是一起测试的,单独升级只限当发生一个紧急故障时,需要单独对一个有问题的角色做升级。 - -#### 2.3.5 启动集群或者升级集群过程中出现 “Timeout when waiting for search string 200 OK” 是什么原因?如何处理? - -可能有以下几种原因:进程没有正常启动;端口被占用;进程没有正常停掉;停掉集群的情况下使用 rolling_update.yml 来升级集群(操作错误)。 - -处理方式:登录到相应节点查看进程或者端口的状态;纠正错误的操作步骤。 - -## 三、集群管理 - -### 3.1 集群日常管理 - -#### 3.1.1 Ansible 常见运维操作有那些? - -| **任务** | **Playbook** | -| --- | --- | -| 启动集群 | ansible-playbook start.yml | -| 停止集群 | ansible-playbook stop.yml | -| 销毁集群 | ansible-playbook unsafe\_cleanup.yml (若部署目录为挂载点,会报错,可忽略) | -| 清除数据(测试用) | ansible-playbook cleanup\_data.yml | -| 滚动升级 | ansible-playbook rolling\_update.yml | -| 滚动升级 TiKV | ansible-playbook rolling\_update.yml --tags=tikv | -| 滚动升级除 PD 外模块 | ansible-playbook rolling\_update.yml --skip-tags=pd | -| 滚动升级监控组件 | ansible-playbook rolling\_update\_monitor.yml | - -#### 3.1.2 TiDB 如何登录? - -和 MySQL 登录方式一样,可以按照下面例子进行登录。 - -`mysql -h 127.0.0.1 -uroot -P4000` - -#### 3.1.3 TiDB 如何修改数据库系统变量? - -和 MySQL 一样,TiDB 也分为静态参数和固态参数,静态参数可以直接通过`set global xxx = n`的方式进行修改,不过新参数值只限于该实例生命周期有效。 - -#### 3.1.4 TiDB (TiKV) 有哪些数据目录? - -默认在 [`--data-dir`](/reference/configuration/tikv-server/configuration.md#--data-dir) 目录下,其中包括 backup、db、raft、snap 四个目录,分别存储备份、数据、raft 数据及镜像数据。 - -#### 3.1.5 TiDB 有哪些系统表? - -和 MySQL 类似,TiDB 中也有系统表,用于存放数据库运行时所需信息,具体信息参考 [TiDB 系统数据库](/reference/system-databases/mysql.md)文档。 - -#### 3.1.6 TiDB 各节点服务器下是否有日志文件,如何管理? - -默认情况下各节点服务器会在日志中输出标准错误,如果启动的时候通过 `--log-file` 参数指定了日志文件,那么日志会输出到指定的文件中,并且按天做 rotation。 - -#### 3.1.7 如何规范停止 TiDB? - -如果是用 TiDB Ansible 部署的,可以使用 `ansible-playbook stop.yml` 命令停止 TiDB 集群。如果不是 TiDB Ansible 部署的,可以直接 kill 掉所有服务。如果使用 kill 命令,TiDB 的组件会做 graceful 的 shutdown。 - -#### 3.1.8 TiDB 里面可以执行 kill 命令吗? - -- 可以 kill DML 语句,首先使用 `show processlist`,找到对应 session 的 id,然后执行 `kill tidb [session id]`。 -- 可以 kill DDL 语句,首先使用 `admin show ddl jobs`,查找需要 kill 的 DDL job ID,然后执行 `admin cancel ddl jobs 'job_id' [, 'job_id'] ...`。具体可以参考 [admin 操作](/reference/sql/statements/admin.md)。 - -#### 3.1.9 TiDB 是否支持会话超时? - -TiDB 暂不支持数据库层面的会话超时,目前想要实现超时,在没 LB(Load Balancing)的时候,需要应用侧记录发起的 Session 的 ID,通过应用自定义超时,超时以后需要到发起 Query 的节点上用 `kill tidb [session id]` 来杀掉 SQL。目前建议使用应用程序来实现会话超时,当达到超时时间,应用层就会抛出异常继续执行后续的程序段。 - -#### 3.1.10 TiDB 生产环境的版本管理策略是怎么样的?如何尽可能避免频繁升级? - -TiDB 版本目前逐步标准化,每次 Release 都包含详细的 Change log,版本功能[变化详情](https://github.com/pingcap/TiDB/releases),生产环境是否有必要升级取决于业务系统,建议升级之前详细了解前后版本的功能差异。 - -版本号说明参考:Release Version: `v1.0.3-1-ga80e796` - -- `v1.0.3` 表示 GA 标准版 -- `1` 表示该版本 commit 1 次 -- `ga80e796` 代表版本的 `git-hash` - -#### 3.1.11 分不清 TiDB master 版本之间的区别,经常用错 TiDB Ansible 版本? - -TiDB 目前社区非常活跃,在 1.0 GA 版本发布后,还在不断的优化和修改 BUG,因此 TiDB 的版本更新周期比较快,会不定期有新版本发布,请关注我们的[新版本发布官方网站](https://pingcap.com/weekly/)。此外 TiDB 安装推荐使用 TiDB Ansible 进行安装,TiDB Ansible 的版本也会随着 TiDB 的版本发布进行更新,因此建议用户在安装升级新版本的时候使用最新的 TiDB Ansible 安装包版本进行安装。此外,在 TiDB 1.0 GA 版本后,对 TiDB 的版本号进行了统一管理,TiDB 的版本可以通过以下两种方式进行查看: - -- 通过 `select tidb_version()` 进行查看 -- 通过执行 `tidb-server -V` 进行查看 - -#### 3.1.12 有没有图形化部署 TiDB 的工具? - -暂时没有。 - -#### 3.1.13 TiDB 如何进行水平扩展? - -当您的业务不断增长时,数据库可能会面临三方面瓶颈,第一是存储空间,第二是计算资源,第三是读写容量,这时可以对 TiDB 集群做水平扩展。 - -- 如果是存储资源不够,可以通过添加 TiKV Server 节点来解决,新节点启动后,PD 会自动将其他节点的部分数据迁移过去,无需人工介入。 -- 如果是计算资源不够,可以查看 TiDB Server 和 TiKV Server 节点的 CPU 消耗情况,再考虑添加 TiDB Server 节点或者是 TiKV Server 节点来解决,如添加 TiDB Server 节点,将其添加到前端 Load Balancer 配置之中即可。 -- 如果是容量跟不上,一般可以考虑同时增加 TiDB Server 和 TiKV Server 节点。 - -#### 3.1.14 Percolator 用了分布式锁,crash 的客户端会保持锁,会造成锁没有 release? - -详细可参考 [Percolator 和 TiDB 事务算法](https://pingcap.com/blog-cn/percolator-and-txn/)。 - -#### 3.1.15 TiDB 为什么选用 gRPC 而不选用 Thrift,是因为 Google 在用吗? - -不只是因为 Google 在用,有一些比较好的特性我们需要,比如流控、加密还有 Streaming。 - -#### 3.1.16 like(bindo.customers.name, jason%, 92) 这个92代表什么? - -那个是转义字符,默认是 (ASCII 92)。 - -#### 3.1.17 为什么 `information_schema.tables.data_length` 记录的大小和 TiKV 监控面板上的 store size 不一样? - -这是因为两者计算的角度不一样。`information_schema.tables.data_length` 是通过统计信息(平均每行的大小)得到的估算值。TiKV 监控面板上的 store size 是单个 TiKV 实例的数据文件(RocksDB 的 SST 文件)的大小总和。由于多版本和 TiKV 会压缩数据,所以两者显示的大小不一样。 - -### 3.2 PD 管理 - -#### 3.2.1 访问 PD 报错:TiKV cluster is not bootstrapped - -PD 的大部分 API 需要在初始化 TiKV 集群以后才能使用,如果在部署新集群的时候只启动了 PD,还没有启动 TiKV,这时候访问 PD 就会报这个错误。遇到这个错误应该先把要部署的 TiKV 启动起来,TiKV 会自动完成初始化工作,然后就可以正常访问 PD。 - -#### 3.2.2 PD 启动报错:etcd cluster ID mismatch - -PD 启动参数中的 `--initial-cluster` 包含了某个不属于该集群的成员。遇到这个错误时请检查各个成员的所属集群,剔除错误的成员后即可正常启动。 - -#### 3.2.3 PD 能容忍的时间同步误差是多少? - -理论上,时间同步误差越小越好。PD 可容忍任意时长的误差,但是,时间同步误差越大意味着 PD 分配的时间戳与真实的物理时间相差越大,这个差距会影响读历史版本等功能。 - -#### 3.2.4 Client 连接是如何寻找 PD 的? - -Client 连接只能通过 TiDB 访问集群,TiDB 负责连接 PD 与 TiKV,PD 与 TiKV 对 Client 透明。当 TiDB 连接任意一台 PD 的时候,PD 会告知 TiDB 当前的 leader 是谁,如果此台 PD 不是 leader,TiDB 将会重新连接至 leader PD。 - -#### 3.2.5 PD 参数中 leader-schedule-limit 和 region-schedule-limit 调度有什么区别? - -- leader-schedule-limit 调度是用来均衡不同 TiKV 的 leader 数,影响处理查询的负载。 -- region-schedule-limit 调度是均衡不同 TiKV 的副本数,影响不同节点的数据量。 - -#### 3.2.6 每个 region 的 replica 数量可配置吗?调整的方法是? - -可以,目前只能调整全局的 replica 数量。首次启动时 PD 会读配置文件(conf/pd.yml),使用其中的 max-replicas 配置,之后修改需要使用 pd-ctl 配置命令 `config set max-replicas $num`,配置后可通过 `config show all` 来查看已生效的配置。调整的时候,不会影响业务,会在后台添加,注意总 TiKV 实例数总是要大于等于设置的副本数,例如 3 副本需要至少 3 个 TiKV。增加副本数量之前需要预估额外的存储需求。pd-ctl 的详细用法可参考 [PD Control 使用说明](/reference/tools/pd-control.md)。 - -#### 3.2.7 缺少命令行集群管理工具,整个集群的健康度当前是否正常,不好确认? - -可以通过 pd-ctl 等工具来判断集群大概的状态,详细的集群状态还是需要通过监控来确认。 - -#### 3.2.8 集群下线节点后,怎么删除老集群节点监控信息? - -下线节点一般指 TiKV 节点通过 pd-ctl 或者监控判断节点是否下线完成。节点下线完成后,手动停止下线节点上相关的服务。从 Prometheus 配置文件中删除对应节点的 node_exporter 信息。从 Ansible inventory.ini 中删除对应节点的信息。 - -#### 3.2.9 使用 PD Control 连接 PD Server 时,为什么只能通过本机 IP 连接,不能通过 127.0.0.1 连接? - -因为使用 TiDB Ansible 部署的集群,PD 对外服务端口不会绑定到 127.0.0.1,所以 PD Control 不会识别 127.0.0.1。 - -### 3.3 TiDB server 管理 - -#### 3.3.1 TiDB 的 lease 参数应该如何设置? - -启动 TiDB Server 时,需要通过命令行参数设置 lease 参数(--lease=60),其值会影响 DDL 的速度(只会影响当前执行 DDL 的 session,其他的 session 不会受影响)。在测试阶段,lease 的值可以设为 1s,加快测试进度;在生产环境下,我们推荐这个值设为分钟级(一般可以设为 60),这样可以保证 DDL 操作的安全。 - -#### 3.3.2 DDL 在正常情况下的耗时是多少? - -一般情况下处理一个 DDL 操作(之前没有其他 DDL 操作在处理)的耗时基本可以分如下为三种: - -- add index 操作,且此操作对应表数据行数比较少,耗时约为 3s。 -- add index 操作,且此操作对应表数据行数比较多,耗时具体由表中数据行数和当时 QPS 情况定(add index 操作优先级比一般 SQL 低)。 -- 其他 DDL 操作耗时约为 1s。 - -此外,如果接收 DDL 请求的 TiDB 和 DDL owner 所处的 TiDB 是一台,那么上面列举的第一和第三种可能的耗时应该在几十到几百毫秒。 - -#### 3.3.3 为什么有的时候执行 DDL 会很慢? - -可能原因如下: - -- 多个 DDL 语句一起执行的时候,后面的几个 DDL 语句会比较慢。原因是当前 TiDB 集群中 DDL 操作是串行执行的。 -- 在正常集群启动后,第一个 DDL 操作的执行时间可能会比较久,一般在 30s 左右,这个原因是刚启动时 TiDB 在竞选处理 DDL 的 leader。 -- 由于停 TiDB 时不能与 PD 正常通信(包括停电情况)或者用 `kill -9` 指令停 TiDB 导致 TiDB 没有及时从 PD 清理注册数据,那么会影响 TiDB 启动后 10min 内的 DDL 语句处理时间。这段时间内运行 DDL 语句时,每个 DDL 状态变化都需要等待 2 * lease(默认 lease = 45s)。 -- 当集群中某个 TiDB 与 PD 之间发生通信问题,即 TiDB 不能从 PD 及时获取或更新版本信息,那么这时候 DDL 操作的每个状态处理需要等待 2 * lease。 - -#### 3.3.4 TiDB 可以使用 S3 作为后端存储吗? - -不可以,目前 TiDB 只支持分布式存储引擎和 GolevelDB/RocksDB/BoltDB 引擎。 - -#### 3.3.5 Information_schema 能否支持更多真实信息? - -Information_schema 库里面的表主要是为了兼容 MySQL 而存在,有些第三方软件会查询里面的信息。在目前 TiDB 的实现中,里面大部分只是一些空表。后续随着 TiDB 的升级,会提供更多的参数信息。当前 TiDB 支持的 Information\_schema 请参考 [TiDB 系统数据库说明文档](/reference/system-databases/information-schema.md)。 - -#### 3.3.6 TiDB Backoff type 主要原因? - -TiDB-server 与 TiKV-server 随时进行通信,在进行大量数据操作过程中,会出现 `Server is busy` 或者 `backoff.maxsleep 20000ms` 的日志提示信息,这是由于 TiKV-server 在处理过程中系统比较忙而出现的提示信息,通常这时候可以通过系统资源监控到 TiKV 主机系统资源使用率比较高的情况出现。如果这种情况出现,可以根据资源使用情况进行相应的扩容操作。 - -#### 3.3.7 TiDB TiClient type 主要原因? - -TiClient Region Error 该指标描述的是在 TiDB-server 作为客户端通过 KV 接口访问 TiKV-server 进行数据操作过程中,TiDB-server 操作 TiKV-server 中的 Region 数据出现的错误类型与 metric 指标,错误类型包括 not_leader、stale_epoch。出现这些错误的情况是当 TiDB-server 根据自己的缓存信息去操作 Region leader 数据的时候,Region leader 发生了迁移或者 TiKV 当前的 Region 信息与 TiDB 缓存的路由信息不一致而出现的错误提示。一般这种情况下,TiDB-server 都会自动重新从 PD 获取最新的路由数据,重做之前的操作。 - -#### 3.3.8 TiDB 同时支持的最大并发连接数? - -当前版本 TiDB 没有最大连接数的限制,如果并发过大导致响应时间增加,可以通过增加 TiDB 节点进行扩容。 - -#### 3.3.9 如何查看某张表创建的时间? - -information_schema 库中的 tables 表里的 create_time 即为表的真实创建时间。 - -#### 3.3.9 TiDB 的日志中 EXPENSIVE_QUERY 是什么意思? - -TiDB 在执行 SQL 时,预估出来每个 operator 处理了超过 10000 条数据就认为这条 query 是 expensive query。可以通过修改 tidb-server 配置参数来对这个门限值进行调整,调整后需要重新启动 tidb-server。 - -#### 3.3.10 在 TiDB 中如何控制或改变 SQL 提交的执行优先级? - -TiDB 支持改变 [per-session](/reference/configuration/tidb-server/tidb-specific-variables.md#tidb_force_priority)、[全局](/reference/configuration/tidb-server/configuration-file.md#force-priority)或单个语句的优先级。优先级包括: - -- HIGH_PRIORITY:该语句为高优先级语句,TiDB 在执行阶段会优先处理这条语句 -- LOW_PRIORITY:该语句为低优先级语句,TiDB 在执行阶段会降低这条语句的优先级 - -以上两种参数可以结合 TiDB 的 DML 语言进行使用,使用方法举例如下: - -1. 通过在数据库中写 SQL 的方式来调整优先级: - - {{< copyable "sql" >}} - - ```sql - select HIGH_PRIORITY | LOW_PRIORITY count(*) from table_name; - insert HIGH_PRIORITY | LOW_PRIORITY into table_name insert_values; - delete HIGH_PRIORITY | LOW_PRIORITY from table_name; - update HIGH_PRIORITY | LOW_PRIORITY table_reference set assignment_list where where_condition; - replace HIGH_PRIORITY | LOW_PRIORITY into table_name; - ``` - -2. 全表扫会自动调整为低优先级,analyze 也是默认低优先级。 - -#### 3.3.11 在 TiDB 中 auto analyze 的触发策略是怎样的? - -触发策略:新表达到 1000 条,并且在 1 分钟内没有写入,会自动触发。 - -当表的(修改数/当前总行数)大于 `tidb_auto_analyze_ratio` 的时候,会自动触发 `analyze` 语句。`tidb_auto_analyze_ratio` 的默认值为 0.5,即默认开启此功能。为了保险起见,在开启此功能的时候,保证了其最小值为 0.3。但是不能大于等于 `pseudo-estimate-ratio`(默认值为 0.8),否则会有一段时间使用 pseudo 统计信息,建议设置值为 0.5。 - -#### 3.3.12 SQL 中如何通过 hint 使用一个具体的 index? - -同 MySQL 的用法一致,例如: -`select column_name from table_name use index(index_name)where where_condition;` - -#### 3.3.13 触发 Information schema is changed 错误的原因? - -TiDB 在执行 SQL 语句时,会使用当时的 `schema` 来处理该 SQL 语句,而且 TiDB 支持在线异步变更 DDL。那么,在执行 DML 的时候可能有 DDL 语句也在执行,而你需要确保每个 SQL 语句在同一个 `schema` 上执行。所以当执行 DML 时,遇到正在执行中的 DDL 操作就可能会报 `Information schema is changed` 的错误。为了避免太多的 DML 语句报错,已做了一些优化。 - -现在会报此错的可能原因如下(后两个报错原因与表无关): - -- 执行的 DML 语句中涉及的表和集群中正在执行的 DDL 的表有相同的,那么这个 DML 语句就会报此错。 -- 这个 DML 执行时间很久,而这段时间内执行了很多 DDL 语句,导致中间 `schema` 版本变更次数超过 1024 (此为默认值,可以通过 `tidb_max_delta_schema_count` 变量修改)。 -- 接受 DML 请求的 TiDB 长时间不能加载到 `schema information`(TiDB 与 PD 或 TiKV 之间的网络连接故障等会导致此问题),而这段时间内执行了很多 DDL 语句,导致中间 `schema` 版本变更次数超过 100。 - -> **注意:** -> -> + 目前 TiDB 未缓存所有的 `schema` 版本信息。 -> + 对于每个 DDL 操作,`schema` 版本变更的数量与对应 `schema state` 变更的次数一致。 -> + 不同的 DDL 操作版本变更次数不一样。例如,`create table` 操作会有 1 次 `schema` 版本变更;`add column` 操作有 4 次 `schema` 版本变更。 - -#### 3.3.14 触发 Information schema is out of date 错误的原因? - -当执行 DML 时,TiDB 超过一个 DDL lease 时间(默认 45s)没能加载到最新的 schema 就可能会报 `Information schema is out of date` 的错误。遇到此错的可能原因如下: - -- 执行此 DML 的 TiDB 被 kill 后准备退出,且此 DML 对应的事务执行时间超过一个 DDL lease,在事务提交时会报这个错误。 -- TiDB 在执行此 DML 时,有一段时间内连不上 PD 或者 TiKV,导致 TiDB 超过一个 DDL lease 时间没有 load schema,或者导致 TiDB 断开与 PD 之间带 keep alive 设置的连接。 - -#### 3.3.15 高并发情况下执行 DDL 时报错的原因? - -高并发情况下执行 DDL(比如批量建表)时,极少部分 DDL 可能会由于并发执行时 key 冲突而执行失败。 - -并发执行 DDL 时,建议将 DDL 数量保持在 20 以下,否则你需要在应用端重试失败的 DDL 语句。 - -### 3.4 TiKV 管理 - -#### 3.4.1 TiKV 集群副本建议配置数量是多少,是不是最小高可用配置(3个)最好? - -如果是测试环境 3 副本足够;在生产环境中,不可让集群副本数低于 3,需根据架构特点、业务系统及恢复能力的需求,适当增加副本数。值得注意的是,副本升高,性能会有下降,但是安全性更高。 - -#### 3.4.2 TiKV 启动报错:cluster ID mismatch - -TiKV 本地存储的 cluster ID 和指定的 PD 的 cluster ID 不一致。在部署新的 PD 集群的时候,PD 会随机生成一个 cluster ID,TiKV 第一次初始化的时候会从 PD 获取 cluster ID 存储在本地,下次启动的时候会检查本地的 cluster ID 与 PD 的 cluster ID 是否一致,如果不一致则会报错并退出。出现这个错误一个常见的原因是,用户原先部署了一个集群,后来把 PD 的数据删除了并且重新部署了新的 PD,但是 TiKV 还是使用旧的数据重启连到新的 PD 上,就会报这个错误。 - -#### 3.4.3 TiKV 启动报错:duplicated store address - -启动参数中的地址已经被其他的 TiKV 注册在 PD 集群中了。造成该错误的常见情况:TiKV `--data-dir` 指定的路径下没有数据文件夹(删除或移动后没有更新 --data-dir),用之前参数重新启动该 TiKV。请尝试用 pd-ctl 的 [store delete](https://github.com/pingcap/pd/tree/55db505e8f35e8ab4e00efd202beb27a8ecc40fb/tools/pd-ctl#store-delete--label--weight-store_id----jqquery-string) 功能,删除之前的 store,然后重新启动 TiKV 即可。 - -#### 3.4.4 TiKV master 和 slave 用的是一样的压缩算法,为什么效果不一样? - -目前来看 master 有些文件的压缩率会高一些,这个取决于底层数据的分布和 RocksDB 的实现,数据大小偶尔有些波动是正常的,底层存储引擎会根据需要调整数据。 - -#### 3.4.5 TiKV block cache 有哪些特性? - -TiKV 使用了 RocksDB 的 Column Family (CF) 特性,KV 数据最终存储在默认 RocksDB 内部的 default、write、lock 3 个 CF 内。 - -- default CF 存储的是真正的数据,与其对应的参数位于 `[rocksdb.defaultcf]` 项中。 -- write CF 存储的是数据的版本信息(MVCC)、索引、小表相关的数据,相关的参数位于 `[rocksdb.writecf]` 项中。 -- lock CF 存储的是锁信息,系统使用默认参数。 -- Raft RocksDB 实例存储 Raft log。default CF 主要存储的是 Raft log,与其对应的参数位于 `[raftdb.defaultcf]` 项中。 -- 所有 CF 共享一个 Block-cache,用于缓存数据块,加速 RocksDB 的读取速度,Block-cache 的大小通过参数 `block-cache-size` 控制,`block-cache-size` 越大,能够缓存的热点数据越多,对读取操作越有利,同时占用的系统内存也会越多。 -- 每个 CF 有各自的 Write-buffer,大小通过 `write-buffer-size` 控制。 - -#### 3.4.6 TiKV channel full 是什么原因? - -- Raftstore 线程太忙,或者因 I/O 而卡住。可以看一下 Raftstore 的 CPU 使用情况。 -- TiKV 过忙(CPU、磁盘 I/O 等),请求处理不过来。 - -#### 3.4.7 TiKV 频繁切换 Region leader 是什么原因? - -- 网络问题导致节点间通信卡了,查看 Report failures 监控。 -- 原主 Leader 的节点卡了,导致没有及时给 Follower 发送消息。 -- Raftstore 线程卡了。 - -#### 3.4.8 如果一个节点挂了会影响服务吗?影响会持续多久? - -TiDB 使用 Raft 在多个副本之间做数据同步(默认为每个 Region 3 个副本)。当一份备份出现问题时,其他的副本能保证数据的安全。根据 Raft 协议,当某个节点挂掉导致该节点里的 Leader 失效时,在最大 2 * lease time(leasetime 是 10 秒)时间后,通过 Raft 协议会很快将一个另外一个节点里的 Follower 选为新的 Region Leader 来提供服务。 - -#### 3.4.9 TiKV 在分别在那些场景下占用大量 IO、内存、CPU(超过参数配置的多倍)? - -在大量写入、读取的场景中会占用大量的磁盘 IO、内存、CPU。在执行很复杂的查询,比如会产生很大中间结果集的情况下,会消耗很多的内存和 CPU 资源。 - -#### 3.4.10 TiKV 是否可以使用 SAS/SATA 盘或者进行 SSD/SAS 混合部署? - -不可以使用,TiDB 在进行 OLTP 场景中,数据访问和操作需要高 IO 磁盘的支持,TiDB 作为强一致的分布式数据库,存在一定的写放大,如副本复制、存储底层 Compaction,因此,TiDB 部署的最佳实践中推荐用户使用 NVMe SSD 磁盘作为数据存储磁盘。另外,TiKV 与 PD 不能混合部署。 - -#### 3.4.11 数据表 Key 的 Range 范围划分是在数据接入之前就已经划分好了吗? - -不是的,这个和 MySQL 分表规则不一样,需要提前设置好,TiKV 是根据 Region 的大小动态分裂的。 - -#### 3.4.12 Region 是如何进行分裂的? - -Region 不是前期划分好的,但确实有 Region 分裂机制。当 Region 的大小超过参数 `region-max-size` 或 `region-max-keys` 的值时,就会触发分裂,分裂后的信息会汇报给 PD。 - -#### 3.4.13 TiKV 是否有类似 MySQL 的 `innodb_flush_log_trx_commit` 参数,来保证提交数据不丢失? - -是的,TiKV 单机的存储引擎目前使用两个 RocksDB 实例,其中一个存储 raft-log,TiKV 有个 sync-log 参数,在 ture 的情况下,每次提交都会强制刷盘到 raft-log,如果发生 crash 后,通过 raft-log 进行 KV 数据的恢复。 - -#### 3.4.14 对 WAL 存储有什么推荐的硬件配置,例如 SSD,RAID 级别,RAID 卡 cache 策略,NUMA 设置,文件系统选择,操作系统的 IO 调度策略等? - -WAL 属于顺序写,目前我们并没有单独对他进行配置,建议 SSD,RAID 如果允许的话,最好是 RAID 10,RAID 卡 cache、操作系统 I/O 调度目前没有针对性的最佳实践,Linux 7 以上默认配置即可,NUMA 没有特别建议,NUMA 内存分配策略可以尝试使用 `interleave = all`,文件系统建议 ext4。 - -#### 3.4.15 在最严格的 `sync-log = true` 数据可用模式下,写入性能如何? - -一般来说,开启 `sync-log` 会让性能损耗 30% 左右。关闭 `sync-log` 时的性能表现,请参见 [TiDB Sysbench 性能测试报告](/benchmark/sysbench-v4.md)。 - -#### 3.4.16 是否可以利用 TiKV 的 Raft + 多副本达到完全的数据可靠,单机存储引擎是否需要最严格模式? - -通过使用 [Raft 一致性算法](https://raft.github.io/),数据在各 TiKV 节点间复制为多副本,以确保某个节点挂掉时数据的安全性。只有当数据已写入超过 50% 的副本时,应用才返回 ACK(三副本中的两副本)。但理论上两个节点也可能同时发生故障,所以除非是对性能要求高于数据安全的场景,一般都强烈推荐开启 `sync-log`。 - -另外,还有一种 `sync-log` 的替代方案,即在 Raft group 中用五个副本而非三个。这将允许两个副本同时发生故障,而仍然能保证数据安全性。 - -对于单机存储引擎也同样推荐打开 `sync-log` 模式。否则如果节点宕机可能会丢失最后一次写入数据。 - -#### 3.4.17 使用 Raft 协议,数据写入会有多次网络的 roundtrip,实际写入延迟如何? - -理论上,和单机数据库相比,数据写入会多四个网络延迟。 - -#### 3.4.18 有没有类似 MySQL 的 InnoDB Memcached plugin,可以直接使用 KV 接口,可以不需要独立的 Cache? - -TiKV 支持单独进行接口调用,理论上也可以起个实例做为 Cache,但 TiDB 最大的价值是分布式关系型数据库,我们原则上不对 TiKV 单独进行支持。 - -#### 3.4.19 Coprocessor 组件的主要作用? - -- 减少 TiDB 与 TiKV 之间的数据传输。 -- 计算下推,充分利用 TiKV 的分布式计算资源。 - -#### 3.4.20 IO error: No space left on device While appending to file - -这是磁盘空间不足导致的,需要加节点或者扩大磁盘空间。 - -#### 3.4.21 为什么 TiKV 容易出现 OOM? - -TiKV 的内存占用主要来自于 RocksDB 的 block-cache,默认为系统总内存的 40%。当 TiKV 容易出现 OOM 时,检查 `block-cache-size` 配置是否过高。还需要注意,当单机部署了多个 TiKV 实例时,需要显式地配置该参数,以防止多个实例占用过多系统内存导致 OOM。 - -#### 3.4.22 TiDB 数据和 RawKV 数据可存储于同一个 TiKV 集群里吗? - -不可以。TiDB 数据(或使用其他事务 API 生成的数据)依赖于一种特殊的键值格式,和 RawKV API 数据(或其他基于 RawKV 的服务生成的数据)并不兼容。 - -### 3.5 TiDB 测试 - -#### 3.5.1 TiDB Sysbench 基准测试结果如何? - -很多用户在接触 TiDB 都习惯做一个基准测试或者 TiDB 与 MySQL 的对比测试,官方也做了一个类似测试,汇总很多测试结果后,我们发现虽然测试的数据有一定的偏差,但结论或者方向基本一致,由于 TiDB 与 MySQL 由于架构上的差别非常大,很多方面是很难找到一个基准点,所以官方的建议两点: - -- 大家不要用过多精力纠结这类基准测试上,应该更多关注 TiDB 的场景上的区别。 -- 大家可以直接参考 [TiDB Sysbench 性能测试报告](/benchmark/sysbench-v4.md)。 - -#### 3.5.2 TiDB 集群容量 QPS 与节点数之间关系如何,和 MySQL 对比如何? - -- 在 10 节点内,TiDB 写入能力(Insert TPS)和节点数量基本成 40% 线性递增,MySQL 由于是单节点写入,所以不具备写入扩展能力。 -- MySQL 读扩容可以通过添加从库进行扩展,但写流量无法扩展,只能通过分库分表,而分库分表有很多问题,具体参考[方案虽好,成本先行:数据库 Sharding+Proxy 实践解析](http://t.cn/RTD18qV)。 -- TiDB 不管是读流量、还是写流量都可以通过添加节点快速方便的进行扩展。 - -#### 3.5.3 我们的 DBA 测试过 MySQL 性能,单台 TiDB 的性能没有 MySQL 性能那么好? - -TiDB 设计的目标就是针对 MySQL 单台容量限制而被迫做的分库分表的场景,或者需要强一致性和完整分布式事务的场景。它的优势是通过尽量下推到存储节点进行并行计算。对于小表(比如千万级以下),不适合 TiDB,因为数据量少,Region 有限,发挥不了并行的优势,最极端的就是计数器表,几行记录高频更新,这几行在 TiDB 里,会变成存储引擎上的几个 KV,然后只落在一个 Region 里,而这个 Region 只落在一个节点上。加上后台强一致性复制的开销,TiDB 引擎到 TiKV 引擎的开销,最后表现出来的就是没有单个 MySQL 好。 - -### 3.6 TiDB 备份恢复 - -#### 3.6.1 TiDB 主要备份方式? - -目前,推荐的备份方式是使用 [PingCAP fork 的 Mydumper](/reference/tools/mydumper.md)。尽管 TiDB 也支持使用 MySQL 官方工具 `mysqldump` 进行数据备份、恢复,但其性能低于 [`mydumper`](/reference/tools/mydumper.md)/[`loader`](/reference/tools/loader.md),并且该工具备份、恢复大量数量时,要耗费更多时间。 - -使用 Mydumper 导出来的数据文件尽可能的小, 最好不要超过 64M, 可以设置参数 -F 64; - -loader 的 -t 参数可以根据 TiKV 的实例个数以及负载进行评估调整,例如 3 个 TiKV 的场景, 此值可以设为 3 * (1 ~ n),当 TiKV 负载过高,loader 以及 TiDB 日志中出现大量 `backoffer.maxSleep 15000ms is exceeded` 可以适当调小该值,当 TiKV 负载不是太高的时候,可以适当调大该值。 - -## 四、数据、流量迁移 - -### 4.1 全量数据导出导入 - -#### 4.1.1 Mydumper - -参见 [Mydumper 使用文档](/reference/tools/mydumper.md)。 - -#### 4.1.2 Loader - -参见 [Loader 使用文档](/reference/tools/loader.md)。 - -#### 4.1.3 如何将一个运行在 MySQL 上的应用迁移到 TiDB 上? - -TiDB 支持绝大多数 MySQL 语法,一般不需要修改代码。 - -#### 4.1.4 不小心把 MySQL 的 user 表导入到 TiDB 了,或者忘记密码,无法登录,如何处理? - -重启 TiDB 服务,配置文件中增加 `-skip-grant-table=true` 参数,无密码登录集群后,可以根据情况重建用户,或者重建 mysql.user 表,具体表结构搜索官网。 - -#### 4.1.5 在 Loader 运行的过程中,TiDB 可以对外提供服务吗? - -该操作进行逻辑插入,TiDB 仍可对外提供服务,但不要执行相关 DDL 操作。 - -#### 4.1.6 如何导出 TiDB 数据? - -TiDB 目前暂时不支持 `select into outfile`,可以通过以下方式导出 TiDB 数据:参考 [MySQL 使用 mysqldump 导出某个表的部分数据](https://blog.csdn.net/xin_yu_xin/article/details/7574662),使用 mysqldump 加 where 条件导出,使用 MySQL client 将 select 的结果输出到一个文件。 - -#### 4.1.7 如何从 DB2、Oracle 数据库迁移到 TiDB? - -DB2、Oracle 到 TiDB 数据迁移(增量+全量),通常做法有: - -- 使用 Oracle 官方迁移工具,如 OGG、Gateway(透明网关)、CDC(Change Data Capture)。 -- 自研数据导出导入程序实现。 -- 导出(Spool)成文本文件,然后通过 Load infile 进行导入。 -- 使用第三方数据迁移工具。 - -目前看来 OGG 最为合适。 - -#### 4.1.8 用 Sqoop 批量写入 TiDB 数据,虽然配置了 `--batch` 选项,但还是会遇到 `java.sql.BatchUpdateExecption:statement count 5001 exceeds the transaction limitation` 的错误,该如何解决? - -- 在 Sqoop 中,`--batch` 是指每个批次提交 100 条 statement,但是默认每个 statement 包含 100 条 SQL 语句,所以此时 100 * 100 = 10000 条 SQL 语句,超出了 TiDB 的事务限制 5000 条,可以增加选项 `-Dsqoop.export.records.per.statement=10` 来解决这个问题,完整的用法如下: - - {{< copyable "shell-regular" >}} - - ```bash - sqoop export \ - -Dsqoop.export.records.per.statement=10 \ - --connect jdbc:mysql://mysql.example.com/sqoop \ - --username sqoop ${user} \ - --password ${passwd} \ - --table ${tab_name} \ - --export-dir ${dir} \ - --batch - ``` - -- 也可以选择增大 tidb 的单个事物语句数量限制,不过这个会导致内存上涨。 - -#### 4.1.9 TiDB 有像 Oracle 那样的 Flashback Query 功能么,DDL 支持么? - -有,也支持 DDL。详细参考 [TiDB 历史数据回溯](/how-to/get-started/read-historical-data.md)。 - -### 4.2 在线数据同步 - -#### 4.2.1 Syncer 架构 - -详细参考 [解析 TiDB 在线数据同步工具 Syncer](https://pingcap.com/blog-cn/tidb-syncer/)。 - -##### 4.2.1.1 Syncer 使用文档 - -详细参考 [Syncer 使用文档](/reference/tools/syncer.md)。 - -##### 4.2.1.2 如何配置监控 Syncer 运行情况? - -下载 [Syncer Json](https://github.com/pingcap/tidb-ansible/blob/master/scripts/syncer.json) 导入到 Grafana,修改 Prometheus 配置文件,添加以下内容: - -- job_name: 'syncer_ops' // 任务名字 - static_configs: -- targets: ['10.10.1.1:10096'] //Syncer 监听地址与端口,通知 prometheus 拉取 Syncer 的数据。 - -重启 Prometheus 即可。 - -##### 4.2.1.3 有没有现成的同步方案,可以将数据同步到 Hbase、Elasticsearh 等其他存储? - -没有,目前依赖程序自行实现。 - -##### 4.2.1.4 利用 Syncer 做数据同步的时候是否支持只同步部分表? - -支持,具体参考 Syncer 使用手册 [Syncer 使用文档](/reference/tools/syncer.md) - -##### 4.2.1.5 频繁的执行 DDL 会影响 Syncer 同步速度吗? - -频繁执行 DDL 对同步速度会有影响。对于 Sycner 来说,DDL 是串行执行的,当同步遇到了 DDL,就会以串行的方式执行,所以这种场景就会导致同步速度下降。 - -##### 4.2.1.6 使用 Syncer gtid 的方式同步时,同步过程中会不断更新 syncer.meta 文件,如果 Syncer 所在的机器坏了,导致 syncer.meta 文件所在的目录丢失,该如何处理? - -当前 Syncer 版本的没有进行高可用设计,Syncer 目前的配置信息 syncer.meta 直接存储在硬盘上,其存储方式类似于其他 MySQL 生态工具,比如 Mydumper。因此,要解决这个问题当前可以有两个方法: - -1)把 syncer.meta 数据放到比较安全的磁盘上,例如磁盘做好 raid1; - -2)可以根据 Syncer 定期上报到 Prometheus 的监控信息来还原出历史同步的位置信息,该方法的位置信息在大量同步数据时由于延迟会可能不准确。 - -##### 4.2.1.7 Syncer 下游 TiDB 数据和 MySQL 数据不一致,DML 会退出么? - -- 上游 MySQL 中存在数据,下游 TiDB 中该数据不存在,上游 MySQL 执行 `UPDATE` 或 `DELETE`(更新/删除)该条数据的操作时,Syncer 同步过程即不会报错退出也没有该条数据。 -- 下游有主键索引或是唯一索引冲突时,执行 `UPDATE` 会退出,执行 `INSERT` 不会退出。 - -### 4.3 业务流量迁入 - -#### 4.3.1 如何快速迁移业务流量? - -我们建议通过 Syncer 工具搭建成多源 MySQL -> TiDB 实时同步环境,读写流量可以按照需求分阶段通过修改网络配置进行流量迁移,建议 DB 上层部署一个稳定的网络 LB(HAproxy、LVS、F5、DNS 等),这样直接修改网络配置就能实现无缝流量迁移。 - -#### 4.3.2 TiDB 总读写流量有限制吗? - -TiDB 读流量可以通过增加 TiDB server 进行扩展,总读容量无限制,写流量可以通过增加 TiKV 节点进行扩容,基本上写容量也没有限制。 - -#### 4.3.3 Transaction too large 是什么原因,怎么解决? - -TiDB 限制了单条 KV entry 不超过 6MB。 - -分布式事务要做两阶段提交,而且底层还需要做 Raft 复制。如果一个事务非常大,提交过程会非常慢,事务写冲突概率会增加,而且事务失败后回滚会导致不必要的性能开销。所以我们设置了 key-value entry 的总大小默认不超过 100MB。如果业务需要使用大事务,可以修改配置文件中的 `txn-total-size-limit` 配置项进行调整,最大可以修改到 10G。实际的大小限制还受机器的物理内存影响。 - -在 Google 的 Cloud Spanner 上面,也有类似的[限制](https://cloud.google.com/spanner/docs/limits)。 - -#### 4.3.4 如何批量导入? - -导入数据的时候,可以分批插入,每批最好不要超过 1w 行。 - -#### 4.3.5 TiDB 中删除数据后会立即释放空间吗? - -DELETE,TRUNCATE 和 DROP 都不会立即释放空间。对于 TRUNCATE 和 DROP 操作,在达到 TiDB 的 GC (garbage collection) 时间后(默认 10 分钟),TiDB 的 GC 机制会删除数据并释放空间。对于 DELETE 操作 TiDB 的 GC 机制会删除数据,但不会释放空间,而是当后续数据写入 RocksDB 且进行 compact 时对空间重新利用。 - -#### 4.3.6 Load 数据时可以对目标表执行 DDL 操作吗? - -不可以,加载数据期间不能对目标表执行任何 DDL 操作,这会导致数据加载失败。 - -#### 4.3.7 TiDB 是否支持 replace into 语法? - -支持,但是 load data 不支持 replace into 语法。 - -#### 4.3.8 数据删除后查询速度为何会变慢? - -大量删除数据后,会有很多无用的 key 存在,影响查询效率。目前正在开发 Region Merge 功能,完善之后可以解决这个问题,具体看参考[最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/)中的删除数据部分。 - -#### 4.3.9 数据删除最高效最快的方式? - -在删除大量数据的时候,建议使用 `Delete * from t where xx limit 5000`(xx 建议在满足业务过滤逻辑下,尽量加上强过滤索引列或者直接使用主键选定范围,如 `id >= 5000*n+m and id <= 5000*(n+1)+m` 这样的方案,通过循环来删除,用 `Affected Rows == 0` 作为循环结束条件,这样避免遇到事务大小的限制。如果一次删除的数据量非常大,这种循环的方式会越来越慢,因为每次删除都是从前向后遍历,前面的删除之后,短时间内会残留不少删除标记(后续会被 GC 掉),影响后面的 Delete 语句。如果有可能,建议把 Where 条件细化。可以参考官网[最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/)。 - -#### 4.3.10 TiDB 如何提高数据加载速度? - -主要有两个方面: - -- 目前已开发分布式导入工具 [Lightning](/reference/tools/tidb-lightning/overview.md),需要注意的是数据导入过程中为了性能考虑,不会执行完整的事务流程,所以没办法保证导入过程中正在导入的数据的 ACID 约束,只能保证整个导入过程结束以后导入数据的 ACID 约束。因此适用场景主要为新数据的导入(比如新的表或者新的索引),或者是全量的备份恢复(先 Truncate 原表再导入)。 -- TiDB 的数据加载与磁盘以及整体集群状态相关,加载数据时应关注该主机的磁盘利用率,TiClient Error/Backoff/Thread CPU 等相关 metric,可以分析相应瓶颈。 - -#### 4.3.11 对数据做删除操作之后,空间回收比较慢,如何处理? - -可以设置并行 GC,加快对空间的回收速度。默认并发为 1,最大可调整为 tikv 实例数量的 50%。可使用 `update mysql.tidb set VARIABLE_VALUE="3" where VARIABLE_NAME="tikv_gc_concurrency";` 命令来调整。 - -## 五、SQL 优化 - -### 5.1 TiDB 执行计划解读 - -详细解读 [理解 TiDB 执行计划](/reference/performance/understanding-the-query-execution-plan.md)。 - -#### 5.1.1 统计信息收集 - -详细解读 [统计信息](/reference/performance/statistics.md)。 - -#### 5.1.2 Count 如何加速? - -Count 就是暴力扫表,提高并发度能显著的提升速度,修改并发度可以参考 `tidb_distsql_scan_concurrency` 变量,但是也要看 CPU 和 I/O 资源。TiDB 每次查询都要访问 TiKV,在数据量小的情况下,MySQL 都在内存里,TiDB 还需要进行一次网络访问。 - -提升建议: - -- 建议提升硬件配置,可以参考[部署建议](/how-to/deploy/hardware-recommendations.md)。 -- 提升并发度,默认是 10,可以提升到 50 试试,但是一般提升在 2-4 倍之间。 -- 测试大数据量的 count。 -- 调优 TiKV 配置,可以参考[性能调优](/reference/performance/tune-tikv.md)。 - -#### 5.1.3 查看当前 DDL 的进度? - -通过 `admin show ddl` 查看当前 job 进度。操作如下: - -{{< copyable "sql" >}} - -```sql -admin show ddl; -``` - -``` -*************************** 1. row *************************** - SCHEMA_VER: 140 - OWNER: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc -RUNNING_JOBS: ID:121, Type:add index, State:running, SchemaState:write reorganization, SchemaID:1, TableID:118, RowCount:77312, ArgLen:0, start time: 2018-12-05 16:26:10.652 +0800 CST, Err:, ErrCount:0, SnapshotVersion:404749908941733890 - SELF_ID: 1a1c4174-0fcd-4ba0-add9-12d08c4077dc -``` - -从上面操作结果可知,当前正在处理的是 `add index` 操作。且从 `RUNNING_JOBS` 列的 `RowCount` 字段可以知道当前 `add index` 操作已经添加了 77312 行索引。 - -#### 5.1.4 如何查看 DDL job? - -可以使用 `admin show ddl` 语句查看正在运行的 DDL 作业。 - -- `admin show ddl jobs`:用于查看当前 DDL 作业队列中的所有结果(包括正在运行以及等待运行的任务)以及已执行完成的 DDL 作业队列中的最近十条结果。 -- `admin show ddl job queries 'job_id' [, 'job_id'] ...`:用于显示 `job_id` 对应的 DDL 任务的原始 SQL 语句。此 `job_id` 只搜索正在执行中的任务以及 DDL 历史作业队列中的最近十条结果。 - -#### 5.1.5 TiDB 是否支持基于 COST 的优化(CBO),如果支持,实现到什么程度? - -是的,TiDB 使用的基于成本的优化器(CBO),我们有一个小组单独会对代价模型、统计信息持续优化,除此之外,我们支持 hash join、soft merge 等关联算法。 - -#### 5.1.6 如何确定某张表是否需要做 analyze ? - -可以通过 `show stats_healthy` 来查看 Healthy 字段,一般小于等于 60 的表需要做 analyze。 - -#### 5.1.7 SQL 的执行计划展开成了树,ID 的序号有什么规律吗?这棵树的执行顺序会是怎么样的? - -ID 没什么规律,只要是唯一就行,不过生成的时候,是有一个计数器,生成一个 plan 就加一,执行的顺序和序号无关,整个执行计划是一颗树,执行时从根节点开始,不断地向上返回数据。执行计划的理解,请参考[理解 TiDB 执行计划](/reference/performance/understanding-the-query-execution-plan.md)。 - -#### 5.1.8 TiDB 执行计划中,task cop 在一个 root 下,这个是并行的么? - -目前 TiDB 的计算任务隶属于两种不同的 task:cop task 和 root task。cop task 是指被下推到 KV 端分布式执行的计算任务,root task 是指在 TiDB 端单点执行的计算任务。一般来讲 root task 的输入数据是来自于 cop task 的;但是 root task 在处理数据的时候,TiKV 上的 cop task 也可以同时处理数据,等待 TiDB 的 root task 拉取,所以从这个观点上来看,他们是并行的;但是存在数据上下游关系;在执行的过程中,某些时间段其实也是并行的,第一个 cop task 在处理 [100, 200] 的数据,第二个 cop task 在处理 [1, 100] 的数据。执行计划的理解,请参考[理解 TiDB 执行计划](/reference/performance/understanding-the-query-execution-plan.md)。 - -## 六、数据库优化 - -### 6.1 TiDB - -#### 6.1.1 TiDB 参数及调整 - -详情参考 [TiDB 配置参数](/reference/configuration/tidb-server/configuration.md)。 - -#### 6.1.2 如何打散热点 - -TiDB 中以 Region 分片来管理数据库,通常来讲,TiDB 的热点指的是 Region 的读写访问热点。而 TiDB 中对于 PK 非整数或没有 PK 的表,可以通过设置 `SHARD_ROW_ID_BITS` 来适度分解 Region 分片,以达到打散 Region 热点的效果。详情可参考官网 [TiDB 专用系统变量和语法](/reference/configuration/tidb-server/tidb-specific-variables.md#shard_row_id_bits)中 `SHARD_ROW_ID_BITS` 的介绍。 - -### 6.2 TiKV - -#### 6.2.1 TiKV 性能参数调优 - -详情参考 [TiKV 性能参数调优](/reference/performance/tune-tikv.md)。 - -## 七、监控 - -### 7.1 Prometheus 监控框架 - -详细参考 [TiDB 监控框架概述](/how-to/monitor/overview.md)。 - -### 7.2 监控指标解读 - -详细参考 [重要监控指标详解](/reference/key-monitoring-metrics/overview-dashboard.md)。 - -#### 7.2.1 目前的监控使用方式及主要监控指标,有没有更好看的监控? - -TiDB 使用 Prometheus + Grafana 组成 TiDB 数据库系统的监控系统,用户在 Grafana 上通过 dashboard 可以监控到 TiDB 的各类运行指标,包括系统资源的监控指标,包括客户端连接与 SQL 运行的指标,包括内部通信和 Region 调度的指标,通过这些指标,可以让数据库管理员更好的了解到系统的运行状态,运行瓶颈等内容。在监控指标的过程中,我们按照 TiDB 不同的模块,分别列出了各个模块重要的指标项,一般用户只需要关注这些常见的指标项。具体指标请参见[官方文档](/reference/key-monitoring-metrics/overview-dashboard.md)。 - -#### 7.2.2 Prometheus 监控数据默认 15 天自动清除一次,可以自己设定成 2 个月或者手动删除吗? - -可以的,在 Prometheus 启动的机器上,找到启动脚本,然后修改启动参数,然后重启 Prometheus 生效。 - -```config ---storage.tsdb.retention="60d" -``` - -#### 7.2.3 Region Health 监控项 - -TiDB-2.0 版本中,PD metric 监控页面中,对 Region 健康度进行了监控,其中 Region Health 监控项是对所有 Region 副本状况的一些统计。其中 miss 是缺副本,extra 是多副本。同时也增加了按 Label 统计的隔离级别,level-1 表示这些 Region 的副本在第一级 Label 下是物理隔离的,没有配置 location label 时所有 Region 都在 level-0。 - -#### 7.2.4 Statement Count 监控项中的 selectsimplefull 是什么意思? - -代表全表扫,但是可能是很小的系统表。 - -#### 7.2.5 监控上的 QPS 和 Statement OPS 有什么区别? - -QPS 会统计执行的所有 SQL 命令,包括 use database、load data、begin、commit、set、show、insert、select 等。 - -Statement OPS 只统计 select、update、insert 等业务相关的,所以 Statement OPS 的统计和业务比较相符。 - -## 八、Cloud TiDB - -### 8.1 腾讯云 - -#### 8.1.1 目前 Cloud TiDB 都有那些云厂商? - -Cloud TiDB 目前已经在腾讯云、UCloud 上线,都是数据库一级入口,欢迎大家使用。 - -## 九、故障排除 - -### 9.1 TiDB 自定义报错汇总 - -#### 9.1.1 ERROR 8005 (HY000) : Write Conflict, txnStartTS is stale - -可以检查 `tidb_disable_txn_auto_retry` 是否为 on。如是,将其设置为 off;如已经是 off,将 `tidb_retry_limit` 调大到不再发生该错误。 - -#### 9.1.2 ERROR 9001 (HY000) : PD Server Timeout - -请求 PD 超时,请检查 PD Server 状态/监控/日志以及 TiDB Server 与 PD Server 之间的网络。 - -#### 9.1.3 ERROR 9002 (HY000) : TiKV Server Timeout - -请求 TiKV 超时,请检查 TiKV Server 状态/监控/日志以及 TiDB Server 与 TiKV Server 之间的网络。 - -#### 9.1.4 ERROR 9003 (HY000) : TiKV Server is Busy - -TiKV 操作繁忙,一般出现在数据库负载比较高时,请检查 TiKV Server 状态/监控/日志。 - -#### 9.1.5 ERROR 9004 (HY000) : Resolve Lock Timeout - -清理锁超时,当数据库上承载的业务存在大量的事务冲突时,会遇到这种错误,请检查业务代码是否有锁争用。 - -#### 9.1.6 ERROR 9005 (HY000) : Region is unavailable - -访问的 Region 不可用,某个 Raft Group 不可用,如副本数目不足,出现在 TiKV 比较繁忙或者是 TiKV 节点停机的时候,请检查 TiKV Server 状态/监控/日志。 - -#### 9.1.7 ERROR 9006 (HY000) : GC life time is shorter than transaction duration - -`GC Life Time` 间隔时间过短,长事务本应读到的数据可能被清理了,可使用如下命令增加 `GC Life Time`: - -{{< copyable "sql" >}} - -```sql -update mysql.tidb set variable_value='30m' where variable_name='tikv_gc_life_time'; -``` - -其中 30m 代表仅清理 30 分钟前的数据,这可能会额外占用一定的存储空间。 - -#### 9.1.8 ERROR 9007 (HY000) : Write Conflict - -可以检查 `tidb_disable_txn_auto_retry` 是否为 on。如是,将其设置为 off;如已经是 off,将 `tidb_retry_limit` 调大到不再发生该错误。 - -### 9.2 MySQL 原生报错汇总 - -#### 9.2.1 ERROR 2013 (HY000): Lost connection to MySQL server during query 问题的排查方法? - -- log 中是否有 panic -- dmesg 中是否有 oom,命令:`dmesg -T | grep -i oom` -- 长时间没有访问,也会收到这个报错,一般是 tcp 超时导致的,tcp 长时间不用, 会被操作系统 kill。 - -#### 9.2.2 ERROR 1105 (HY000): other error: unknown error Wire Error(InvalidEnumValue(4004)) 是什么意思? - -这类问题一般是 TiDB 和 TiKV 版本不匹配,在升级过程尽量一起升级,避免版本 mismatch。 - -#### 9.2.3 ERROR 1148 (42000): the used command is not allowed with this TiDB version 问题的处理方法? - -这个问题是因为在执行 `LOAD DATA LOCAL` 语句的时候,MySQL 客户端不允许执行此语句(即 `local_infile` 选项为 0)。解决方法是在启动 MySQL 客户端时,用 `--local-infile=1` 选项。具体启动指令类似:`mysql --local-infile=1 -u root -h 127.0.0.1 -P 4000`。有些 MySQL 客户端需要设置而有些不需要设置,原因是不同版本的 MySQL 客户端对 `local-infile` 的默认值不同。 - -#### 9.2.4 ERROR 9001 (HY000): PD server timeout start timestamp may fall behind safe point - -这个报错一般是 TiDB 访问 PD 出了问题,TiDB 后台有个 worker 会不断地从 PD 查询 safepoint,如果超过 100s 查不成功就会报这个错。一般是因为 PD 磁盘操作过忙、反应过慢,或者 TiDB 和 PD 之间的网络有问题。TiDB 常见错误码请参考[错误码与故障诊断](/reference/error-codes.md)。 - -### 9.3 TiDB 日志中的报错信息 - -#### 9.3.1 EOF - -当客户端或者 proxy 断开连接时,TiDB 不会立刻察觉连接已断开,而是等到开始往连接返回数据时,才发现连接已断开,此时日志会打印 EOF 错误。 diff --git a/faq/upgrade-faq.md b/faq/upgrade-faq.md new file mode 100644 index 000000000000..9e2a2568576f --- /dev/null +++ b/faq/upgrade-faq.md @@ -0,0 +1,345 @@ +--- +title: 升级与升级后常见问题 +summary: TiDB 升级与升级后的常见问题与解决办法。 +category: FAQ +aliases: ['/docs-cn/stable/faq/upgrade/'] +--- + +# 升级与升级后常见问题 + +本文介绍 TiDB 升级与升级后的常见问题与解决办法。 + +## 升级常见问题 + +本小节列出了 TiDB 升级相关的常见问题与解决办法。 + +### 滚动升级有那些影响? + +滚动升级 TiDB 服务,滚动升级期间不影响业务运行。需要配置最小集群拓扑(TiDB \* 2、PD \* 3、TiKV \* 3),如果集群环境中有 Pump 和 Drainer 服务,建议先停止 Drainer,然后滚动升级(升级 TiDB 时会升级 Pump)。 + +### Binary 如何升级? + +Binary 不是建议的安装方式,对升级支持也不友好,建议换成 [TiUP 部署](/production-deployment-using-tiup.md)。 + +## 升级后常见问题 + +本小节列出了一些升级后可能会遇到的问题与解决办法。 + +### 执行 DDL 操作时遇到的字符集 (charset) 问题 + +TiDB 在 v2.1.0 以及之前版本(包括 v2.0 所有版本)中,默认字符集是 UTF8。从 v2.1.1 开始,默认字符集变更为 UTF8MB4。如果在 v2.1.0 及之前版本中,建表时显式指定了 table 的 charset 为 UTF8,那么升级到 v2.1.1 之后,执行 DDL 操作可能会失败。 + +要避免该问题,需注意以下两个要点: + +- 在 v2.1.3 之前,TiDB 不支持修改 column 的 charset。所以,执行 DDL 操作时,新 column 的 charset 需要和旧 column 的 charset 保持一致。 +- 在 v2.1.3 之前,即使 column 的 charset 和 table 的 charset 不一样,`show create table` 也不会显示 column 的 charset,但可以通过 HTTP API 获取 table 的元信息来查看 column 的 charset,下文提供了示例。 + +#### `unsupported modify column charset utf8mb4 not match origin utf8` + +- 升级前:v2.1.0 及之前版本 + + {{< copyable "sql" >}} + + ```sql + create table t(a varchar(10)) charset=utf8; + ``` + + ``` + Query OK, 0 rows affected + Time: 0.106s + ``` + + {{< copyable "sql" >}} + + ```sql + show create table t + ``` + + ``` + +-------+-------------------------------------------------------+ + | Table | Create Table | + +-------+-------------------------------------------------------+ + | t | CREATE TABLE `t` ( | + | | `a` varchar(10) DEFAULT NULL | + | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | + +-------+-------------------------------------------------------+ + 1 row in set + Time: 0.006s + ``` + +- 升级后:v2.1.1、v2.1.2 会出现下面的问题,v2.1.3 以及之后版本不会出现下面的问题。 + + {{< copyable "sql" >}} + + ```sql + alter table t change column a a varchar(20); + ``` + + ``` + ERROR 1105 (HY000): unsupported modify column charset utf8mb4 not match origin utf8 + ``` + +解决方案:显式指定 column charset,保持和原来的 charset 一致即可。 + +{{< copyable "sql" >}} + +```sql +alter table t change column a a varchar(22) character set utf8; +``` + +- 根据要点 1,此处如果不指定 column 的 charset,会用默认的 UTF8MB4,所以需要指定 column charset 保持和原来一致。 + +- 根据要点 2,用 HTTP API 获取 table 元信息,然后根据 column 名字和 Charset 关键字搜索即可找到 column 的 charset。 + + {{< copyable "shell-regular" >}} + + ```sh + curl "http://$IP:10080/schema/test/t" | python -m json.tool + ``` + + 这里用了 python 的格式化 json的工具,也可以不加,此处只是为了方便注释。 + + ```json + { + "ShardRowIDBits": 0, + "auto_inc_id": 0, + "charset": "utf8", # table 的 charset + "collate": "", + "cols": [ # 从这里开始列举 column 的相关信息 + { + ... + "id": 1, + "name": { + "L": "a", + "O": "a" # column 的名字 + }, + "offset": 0, + "origin_default": null, + "state": 5, + "type": { + "Charset": "utf8", # column a 的 charset + "Collate": "utf8_bin", + "Decimal": 0, + "Elems": null, + "Flag": 0, + "Flen": 10, + "Tp": 15 + } + } + ], + ... + } + ``` + +#### `unsupported modify charset from utf8mb4 to utf8` + +- 升级前:v2.1.1,v2.1.2 + + {{< copyable "sql" >}} + + ```sql + create table t(a varchar(10)) charset=utf8; + ``` + + ``` + Query OK, 0 rows affected + Time: 0.109s + ``` + + {{< copyable "sql" >}} + + ```sql + show create table t; + ``` + + ``` + +-------+-------------------------------------------------------+ + | Table | Create Table | + +-------+-------------------------------------------------------+ + | t | CREATE TABLE `t` ( | + | | `a` varchar(10) DEFAULT NULL | + | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | + +-------+-------------------------------------------------------+ + ``` + + 上面 `show create table` 只显示出了 table 的 charset,但其实 column 的 charset 是 UTF8MB4,这可以通过 HTTP API 获取 schema 来确认。这是一个 bug,即此处建表时 column 的 charset 应该要和 table 保持一致为 UTF8,该问题在 v2.1.3 中已经修复。 + +- 升级后:v2.1.3 及之后版本 + + {{< copyable "sql" >}} + + ```sql + show create table t; + ``` + + ``` + +-------+--------------------------------------------------------------------+ + | Table | Create Table | + +-------+--------------------------------------------------------------------+ + | t | CREATE TABLE `t` ( | + | | `a` varchar(10) CHARSET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL | + | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | + +-------+--------------------------------------------------------------------+ + 1 row in set + Time: 0.007s + ``` + + {{< copyable "sql" >}} + + ```sql + alter table t change column a a varchar(20); + ``` + + ``` + ERROR 1105 (HY000): unsupported modify charset from utf8mb4 to utf8 + ``` + +解决方案: + +- 因为在 v2.1.3 之后,TiDB 支持修改 column 和 table 的 charset,所以这里推荐修改 table 的 charset 为 UTF8MB4。 + + {{< copyable "sql" >}} + + ```sql + alter table t convert to character set utf8mb4; + ``` + +- 也可以像问题 1 一样指定 column 的 charset,保持和 column 原来的 charset (UTF8MB4) 一致即可。 + + {{< copyable "sql" >}} + + ```sql + alter table t change column a a varchar(20) character set utf8mb4; + ``` + +#### `ERROR 1366 (HY000): incorrect utf8 value f09f8c80(🌀) for column a` + +TiDB 在 v2.1.1 及之前版本中,如果 charset 是 UTF8,没有对 4-byte 的插入数据进行 UTF8 Unicode encoding 检查。在v2.1.2 及之后版本中,添加了该检查。 + +- 升级前:v2.1.1 及之前版本 + + {{< copyable "sql" >}} + + ```sql + create table t(a varchar(100) charset utf8); + ``` + + ``` + Query OK, 0 rows affected + ``` + + {{< copyable "sql" >}} + + ```sql + insert t values (unhex('f09f8c80')); + ``` + + ``` + Query OK, 1 row affected + ``` + +- 升级后:v2.1.2 及之后版本 + + {{< copyable "sql" >}} + + ```sql + insert t values (unhex('f09f8c80')); + ``` + + ``` + ERROR 1366 (HY000): incorrect utf8 value f09f8c80(🌀) for column a + ``` + +解决方案: + +- v2.1.2 版本:该版本不支持修改 column charset,所以只能跳过 UTF8 的检查。 + + {{< copyable "sql" >}} + + ```sql + set @@session.tidb_skip_utf8_check=1; + ``` + + ``` + Query OK, 0 rows affected + ``` + + {{< copyable "sql" >}} + + ```sql + insert t values (unhex('f09f8c80')); + ``` + + ``` + Query OK, 1 row affected + ``` + +- v2.1.3 及之后版本:建议修改 column 的 charset 为 UTF8MB4。或者也可以设置 `tidb_skip_utf8_check` 变量跳过 UTF8 的检查。如果跳过 UTF8 的检查,在需要将数据从 TiDB 同步回 MySQL 的时候,可能会失败,因为 MySQL 会执行该检查。 + + {{< copyable "sql" >}} + + ```sql + alter table t change column a a varchar(100) character set utf8mb4; + ``` + + ``` + Query OK, 0 rows affected + ``` + + {{< copyable "sql" >}} + + ```sql + insert t values (unhex('f09f8c80')); + ``` + + ``` + Query OK, 1 row affected + ``` + + 关于 `tidb_skip_utf8_check` 变量,具体来说是指跳过 UTF8 和 UTF8MB4 类型对数据的合法性检查。如果跳过这个检查,在需要将数据从 TiDB 同步回 MySQL 的时候,可能会失败,因为 MySQL 执行该检查。如果只想跳过 UTF8 类型的检查,可以设置 `tidb_check_mb4_value_in_utf8` 变量。 + + `tidb_check_mb4_value_in_utf8` 在 v2.1.3 版本加入 `config.toml` 文件,可以修改配置文件里面的 `check-mb4-value-in-utf8` 后重启集群生效。 + + `tidb_check_mb4_value_in_utf8` 在 v2.1.5 版本开始可以用 HTTP API 来设置,也可以用 session 变量来设置。 + + * HTTP API(HTTP API 只在单台服务器上生效) + + * 执行下列命令启用 HTTP API: + + {{< copyable "shell-regular" >}} + + ```sh + curl -X POST -d "check_mb4_value_in_utf8=1" http://{TiDBIP}:10080/settings + ``` + + * 执行下列命令禁用 HTTP API: + + {{< copyable "shell-regular" >}} + + ```sh + curl -X POST -d "check_mb4_value_in_utf8=0" http://{TiDBIP}:10080/settings + ``` + + * Session 变量 + + * 执行下列命令启用 Session 变量: + + {{< copyable "sql" >}} + + ```sql + set @@session.tidb_check_mb4_value_in_utf8 = 1; + ``` + + * 执行下列命令禁用 Session 变量: + + {{< copyable "sql" >}} + + ```sql + set @@session.tidb_check_mb4_value_in_utf8 = 0; + ``` + +- v2.1.7 及之后版本,如果对表和 column 的字符集没有严格要求为 UTF8,也不想修改客户端代码去跳过 UTF8 检查或者手动修改 column 的 charset,可以在配置文件中把 `treat-old-version-utf8-as-utf8mb4` 打开。该配置的作用是自动把 v2.1.7 版本之前创建的旧版本的表和 column 的 UTF8 字符集转成 UTF8MB4。这个转换是在 TiDB load schema 时在内存中将 UTF8 转成 UTF8MB4,不会对实际存储的数据做任何修改。在配置文件中关闭 `treat-old-version-utf8-as-utf8mb4` 并重启 TiDB 后,以前字符集为 UTF8 的表和 column 的字符集仍然还是 UTF8。 + + > **注意:** + > + > `treat-old-version-utf8-as-utf8mb4` 参数默认打开,如果客户端强制需要用 UTF8 而不用 UTF8MB4,需要在配置文件中关闭。 diff --git a/faq/upgrade.md b/faq/upgrade.md deleted file mode 100644 index 5e333f4a41a6..000000000000 --- a/faq/upgrade.md +++ /dev/null @@ -1,328 +0,0 @@ ---- -title: 升级后常见问题 -category: FAQ ---- - -# 升级后常见问题 - -本文列出了一些升级后可能会遇到的问题与解决办法。 - -## 执行 DDL 操作时遇到的字符集 (charset) 问题 - -TiDB 在 v2.1.0 以及之前版本(包括 v2.0 所有版本)中,默认字符集是 UTF8。从 v2.1.1 开始,默认字符集变更为 UTF8MB4。如果在 v2.1.0 及之前版本中,建表时显式指定了 table 的 charset 为 UTF8,那么升级到 v2.1.1 之后,执行 DDL 操作可能会失败。 - -要避免该问题,需注意以下两个要点: - -1. 在 v2.1.3 之前,TiDB 不支持修改 column 的 charset。所以,执行 DDL 操作时,新 column 的 charset 需要和旧 column 的 charset 保持一致。 - -2. 在 v2.1.3 之前,即使 column 的 charset 和 table 的 charset 不一样,`show create table` 也不会显示 column 的 charset,但可以通过 HTTP API 获取 table 的元信息来查看 column 的 charset,下文提供了示例。 - -### 问题 1:`unsupported modify column charset utf8mb4 not match origin utf8` - -- 升级前:v2.1.0 及之前版本 - - {{< copyable "sql" >}} - - ```sql - create table t(a varchar(10)) charset=utf8; - ``` - - ``` - Query OK, 0 rows affected - Time: 0.106s - ``` - - {{< copyable "sql" >}} - - ```sql - show create table t - ``` - - ``` - +-------+-------------------------------------------------------+ - | Table | Create Table | - +-------+-------------------------------------------------------+ - | t | CREATE TABLE `t` ( | - | | `a` varchar(10) DEFAULT NULL | - | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | - +-------+-------------------------------------------------------+ - 1 row in set - Time: 0.006s - ``` - -- 升级后:v2.1.1、v2.1.2 会出现下面的问题,v2.1.3 以及之后版本不会出现下面的问题。 - - {{< copyable "sql" >}} - - ```sql - alter table t change column a a varchar(20); - ``` - - ``` - ERROR 1105 (HY000): unsupported modify column charset utf8mb4 not match origin utf8 - ``` - -解决方案:显式指定 column charset,保持和原来的 charset 一致即可。 - -{{< copyable "sql" >}} - -```sql -alter table t change column a a varchar(22) character set utf8; -``` - -- 根据要点 1,此处如果不指定 column 的 charset,会用默认的 UTF8MB4,所以需要指定 column charset 保持和原来一致。 - -- 根据要点 2,用 HTTP API 获取 table 元信息,然后根据 column 名字和 Charset 关键字搜索即可找到 column 的 charset。 - - {{< copyable "shell-regular" >}} - - ```sh - curl "http://$IP:10080/schema/test/t" | python -m json.tool - ``` - - 这里用了 python 的格式化 json的工具,也可以不加,此处只是为了方便注释。 - - ```json - { - "ShardRowIDBits": 0, - "auto_inc_id": 0, - "charset": "utf8", # table 的 charset - "collate": "", - "cols": [ # 从这里开始列举 column 的相关信息 - { - ... - "id": 1, - "name": { - "L": "a", - "O": "a" # column 的名字 - }, - "offset": 0, - "origin_default": null, - "state": 5, - "type": { - "Charset": "utf8", # column a 的 charset - "Collate": "utf8_bin", - "Decimal": 0, - "Elems": null, - "Flag": 0, - "Flen": 10, - "Tp": 15 - } - } - ], - ... - } - ``` - -### 问题 2:`unsupported modify charset from utf8mb4 to utf8` - -- 升级前:v2.1.1,v2.1.2 - - {{< copyable "sql" >}} - - ```sql - create table t(a varchar(10)) charset=utf8; - ``` - - ``` - Query OK, 0 rows affected - Time: 0.109s - ``` - - {{< copyable "sql" >}} - - ```sql - show create table t; - ``` - - ``` - +-------+-------------------------------------------------------+ - | Table | Create Table | - +-------+-------------------------------------------------------+ - | t | CREATE TABLE `t` ( | - | | `a` varchar(10) DEFAULT NULL | - | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | - +-------+-------------------------------------------------------+ - ``` - - 上面 `show create table` 只显示出了 table 的 charset,但其实 column 的 charset 是 UTF8MB4,这可以通过 HTTP API 获取 schema 来确认。这是一个 bug,即此处建表时 column 的 charset 应该要和 table 保持一致为 UTF8,该问题在 v2.1.3 中已经修复。 - -- 升级后:v2.1.3 及之后版本 - - {{< copyable "sql" >}} - - ```sql - show create table t; - ``` - - ``` - +-------+--------------------------------------------------------------------+ - | Table | Create Table | - +-------+--------------------------------------------------------------------+ - | t | CREATE TABLE `t` ( | - | | `a` varchar(10) CHARSET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL | - | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | - +-------+--------------------------------------------------------------------+ - 1 row in set - Time: 0.007s - ``` - - {{< copyable "sql" >}} - - ```sql - alter table t change column a a varchar(20); - ``` - - ``` - ERROR 1105 (HY000): unsupported modify charset from utf8mb4 to utf8 - ``` - -解决方案: - -- 因为在 v2.1.3 之后,TiDB 支持修改 column 和 table 的 charset,所以这里推荐修改 table 的 charset 为 UTF8MB4。 - - {{< copyable "sql" >}} - - ```sql - alter table t convert to character set utf8mb4; - ``` - -- 也可以像问题 1 一样指定 column 的 charset,保持和 column 原来的 charset (UTF8MB4) 一致即可。 - - {{< copyable "sql" >}} - - ```sql - alter table t change column a a varchar(20) character set utf8mb4; - ``` - -### 问题 3:`ERROR 1366 (HY000): incorrect utf8 value f09f8c80(🌀) for column a` - -TiDB 在 v2.1.1 及之前版本中,如果 charset 是 UTF8,没有对 4-byte 的插入数据进行 UTF8 Unicode encoding 检查。在v2.1.2 及之后版本中,添加了该检查。 - -- 升级前:v2.1.1 及之前版本 - - {{< copyable "sql" >}} - - ```sql - create table t(a varchar(100) charset utf8); - ``` - - ``` - Query OK, 0 rows affected - ``` - - {{< copyable "sql" >}} - - ```sql - insert t values (unhex('f09f8c80')); - ``` - - ``` - Query OK, 1 row affected - ``` - -- 升级后:v2.1.2 及之后版本 - - {{< copyable "sql" >}} - - ```sql - insert t values (unhex('f09f8c80')); - ``` - - ``` - ERROR 1366 (HY000): incorrect utf8 value f09f8c80(🌀) for column a - ``` - -解决方案: - -- v2.1.2 版本:该版本不支持修改 column charset,所以只能跳过 UTF8 的检查。 - - {{< copyable "sql" >}} - - ```sql - set @@session.tidb_skip_utf8_check=1; - ``` - - ``` - Query OK, 0 rows affected - ``` - - {{< copyable "sql" >}} - - ```sql - insert t values (unhex('f09f8c80')); - ``` - - ``` - Query OK, 1 row affected - ``` - -- v2.1.3 及之后版本:建议修改 column 的 charset 为 UTF8MB4。或者也可以设置 `tidb_skip_utf8_check` 变量跳过 UTF8 的检查。如果跳过 UTF8 的检查,在需要将数据从 TiDB 同步回 MySQL 的时候,可能会失败,因为 MySQL 会执行该检查。 - - {{< copyable "sql" >}} - - ```sql - alter table t change column a a varchar(100) character set utf8mb4; - ``` - - ``` - Query OK, 0 rows affected - ``` - - {{< copyable "sql" >}} - - ```sql - insert t values (unhex('f09f8c80')); - ``` - - ``` - Query OK, 1 row affected - ``` - - 关于 `tidb_skip_utf8_check` 变量,具体来说是指跳过 UTF8 和 UTF8MB4 类型对数据的合法性检查。如果跳过这个检查,在需要将数据从 TiDB 同步回 MySQL 的时候,可能会失败,因为 MySQL 执行该检查。如果只想跳过 UTF8 类型的检查,可以设置 `tidb_check_mb4_value_in_utf8` 变量。 - - `tidb_check_mb4_value_in_utf8` 在 v2.1.3 版本加入 `config.toml` 文件,可以修改配置文件里面的 `check-mb4-value-in-utf8` 后重启集群生效。 - - `tidb_check_mb4_value_in_utf8` 在 v2.1.5 版本开始可以用 HTTP API 来设置,也可以用 session 变量来设置。 - - * HTTP API(HTTP API 只在单台服务器上生效) - - * 执行下列命令启用 HTTP API: - - {{< copyable "shell-regular" >}} - - ```sh - curl -X POST -d "check_mb4_value_in_utf8=1" http://{TiDBIP}:10080/settings - ``` - - * 执行下列命令禁用 HTTP API: - - {{< copyable "shell-regular" >}} - - ```sh - curl -X POST -d "check_mb4_value_in_utf8=0" http://{TiDBIP}:10080/settings - ``` - - * Session 变量 - - * 执行下列命令启用 Session 变量: - - {{< copyable "sql" >}} - - ```sql - set @@session.tidb_check_mb4_value_in_utf8 = 1; - ``` - - * 执行下列命令禁用 Session 变量: - - {{< copyable "sql" >}} - - ```sql - set @@session.tidb_check_mb4_value_in_utf8 = 0; - ``` - -- v2.1.7 及之后版本,如果对表和 column 的字符集没有严格要求为 UTF8,也不想修改客户端代码去跳过 UTF8 检查或者手动修改 column 的 charset,可以在配置文件中把 `treat-old-version-utf8-as-utf8mb4` 打开。该配置的作用是自动把 v2.1.7 版本之前创建的旧版本的表和 column 的 UTF8 字符集转成 UTF8MB4。这个转换是在 TiDB load schema 时在内存中将 UTF8 转成 UTF8MB4,不会对实际存储的数据做任何修改。在配置文件中关闭 `treat-old-version-utf8-as-utf8mb4` 并重启 TiDB 后,以前字符集为 UTF8 的表和 column 的字符集仍然还是 UTF8。 - - > **注意:** - > - > `treat-old-version-utf8-as-utf8mb4` 参数默认打开,如果客户端强制需要用 UTF8 而不用 UTF8MB4,需要在配置文件中关闭。 diff --git a/follower-read.md b/follower-read.md new file mode 100644 index 000000000000..ce232366d9c7 --- /dev/null +++ b/follower-read.md @@ -0,0 +1,53 @@ +--- +title: Follower Read +summary: 了解 Follower Read 的使用与实现。 +category: reference +aliases: ['/docs-cn/stable/reference/performance/follower-read/'] +--- + +# Follower Read + +当系统中存在读取热点 Region 导致 leader 资源紧张成为整个系统读取瓶颈时,启用 Follower Read 功能可明显降低 leader 的负担,并且通过在多个 follower 之间均衡负载,显著地提升整体系统的吞吐能力。本文主要介绍 Follower Read 的使用方法与实现机制。 + +## 概述 + +Follower Read 功能是指在强一致性读的前提下使用 Region 的 follower 副本来承载数据读取的任务,从而提升 TiDB 集群的吞吐能力并降低 leader 负载。Follower Read 包含一系列将 TiKV 读取负载从 Region 的 leader 副本上 offload 到 follower 副本的负载均衡机制。TiKV 的 Follower Read 可以保证数据读取的一致性,可以为用户提供强一致的数据读取能力。 + +> **注意:** +> +> 为了获得强一致读取的能力,在当前的实现中,follower 节点需要向 leader 节点询问当前的执行进度(即 `ReadIndex`),这会产生一次额外的网络请求开销,因此目前 Follower Read 的主要优势是处理隔离集群的读写请求以及提升整体读取吞吐。 + +## 使用方式 + +要开启 TiDB 的 Follower Read 功能,将 SESSION 变量 `tidb_replica_read` 的值设置为 `follower` 或 `leader-and-follower` 即可: + +{{< copyable "sql" >}} + +```sql +set @@tidb_replica_read = '<目标值>'; +``` + +作用域:SESSION + +默认值:leader + +该变量用于设置当前会话期待的数据读取方式。 + +- 当设定为默认值 `leader` 或者空字符串时,TiDB 会维持原有行为方式,将所有的读取操作都发送给 leader 副本处理。 +- 当设置为 `follower` 时,TiDB 会选择 Region 的 follower 副本完成所有的数据读取操作。 +- 当 `tidb_replica_read` 的值设为 `leader-and-follower` 时,TiDB 可以选择任意副本来执行读取操作。 +- 当设置为 `leader-and-follower` 时,读请求会在 leader 和 follower 之间负载均衡。 + +## 实现机制 + +在 Follower Read 功能出现之前,TiDB 采用 strong leader 策略将所有的读写操作全部提交到 Region 的 leader 节点上完成。虽然 TiKV 能够很均匀地将 Region 分散到多个物理节点上,但是对于每一个 Region 来说,只有 leader 副本能够对外提供服务,另外的 follower 除了时刻同步数据准备着 failover 时投票切换成为 leader 外,没有办法对 TiDB 的请求提供任何帮助。 + +为了允许在 TiKV 的 follower 节点进行数据读取,同时又不破坏线性一致性和 Snapshot Isolation 的事务隔离,Region 的 follower 节点需要使用 Raft `ReadIndex` 协议确保当前读请求可以读到当前 leader 上已经 commit 的最新数据。在 TiDB 层面,Follower Read 只需根据负载均衡策略将某个 Region 的读取请求发送到 follower 节点。 + +### Follower 强一致读 + +TiKV follower 节点处理读取请求时,首先使用 Raft `ReadIndex` 协议与 Region 当前的 leader 进行一次交互,来获取当前 Raft group 最新的 commit index。本地 apply 到所获取的 leader 最新 commit index 后,便可以开始正常的读取请求处理流程。 + +### Follower 副本选择策略 + +由于 TiKV 的 Follower Read 不会破坏 TiDB 的 Snapshot Isolation 事务隔离级别,因此 TiDB 选择 follower 的策略可以采用 round robin 的方式。目前,对于 Coprocessor 请求,Follower Read 负载均衡策略粒度是连接级别的,对于一个 TiDB 的客户端连接在某个具体的 Region 上会固定使用同一个 follower,只有在选中的 follower 发生故障或者因调度策略发生调整的情况下才会进行切换。而对于非 Coprocessor 请求(点查等),Follower Read 负载均衡策略粒度是事务级别的,对于一个 TiDB 的事务在某个具体的 Region 上会固定使用同一个 follower,同样在 follower 发生故障或者因调度策略发生调整的情况下才会进行切换。 diff --git a/reference/sql/functions-and-operators/aggregate-group-by-functions.md b/functions-and-operators/aggregate-group-by-functions.md similarity index 90% rename from reference/sql/functions-and-operators/aggregate-group-by-functions.md rename to functions-and-operators/aggregate-group-by-functions.md index 0586410900ab..314fa7677d94 100644 --- a/reference/sql/functions-and-operators/aggregate-group-by-functions.md +++ b/functions-and-operators/aggregate-group-by-functions.md @@ -1,6 +1,7 @@ --- title: GROUP BY 聚合函数 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/aggregate-group-by-functions/'] --- # GROUP BY 聚合函数 @@ -20,6 +21,8 @@ TiDB 支持的 MySQL GROUP BY 聚合函数如下所示: | [`MAX()`](https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_max) | 返回最大值 | | [`MIN()`](https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_min) | 返回最小值 | | [`GROUP_CONCAT()`](https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat) | 返回连接的字符串 | +| [`VARIANCE()`, `VAR_POP()`](https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_var-pop) | 返回表达式的总体标准方差 | +| [`JSON_OBJECTAGG(key, value)`](https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_json-objectagg) | 将结果集返回为单个含 (key, value) 键值对的 JSON object | > **注意:** > @@ -79,7 +82,7 @@ select a, b, sum(c) from t group by a; ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'b' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by ``` -目前,TiDB 默认开启 SQL 模式 [`ONLY_FULL_GROUP_BY`](/reference/mysql-compatibility.md#默认设置的区别)。 +目前,TiDB 默认开启 SQL 模式 [`ONLY_FULL_GROUP_BY`](/mysql-compatibility.md#默认设置的区别)。 ### 与 MySQL 的区别 @@ -151,7 +154,5 @@ TiDB 目前不支持的聚合函数如下所示,相关进展参阅 [TiDB #7623 - `STD`, `STDDEV`, `STDDEV_POP` - `STDDEV_SAMP` -- `VARIANCE`, `VAR_POP` - `VAR_SAMP` - `JSON_ARRAYAGG` -- `JSON_OBJECTAGG` diff --git a/reference/sql/functions-and-operators/bit-functions-and-operators.md b/functions-and-operators/bit-functions-and-operators.md similarity index 91% rename from reference/sql/functions-and-operators/bit-functions-and-operators.md rename to functions-and-operators/bit-functions-and-operators.md index 9d44c9caf9af..9fde75eee0cd 100644 --- a/reference/sql/functions-and-operators/bit-functions-and-operators.md +++ b/functions-and-operators/bit-functions-and-operators.md @@ -1,6 +1,7 @@ --- title: 位函数和操作符 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/bit-functions-and-operators/'] --- # 位函数和操作符 diff --git a/reference/sql/functions-and-operators/cast-functions-and-operators.md b/functions-and-operators/cast-functions-and-operators.md similarity index 89% rename from reference/sql/functions-and-operators/cast-functions-and-operators.md rename to functions-and-operators/cast-functions-and-operators.md index 8a6efeacdb27..61dcec2f0f10 100644 --- a/reference/sql/functions-and-operators/cast-functions-and-operators.md +++ b/functions-and-operators/cast-functions-and-operators.md @@ -1,6 +1,7 @@ --- title: Cast 函数和操作符 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/cast-functions-and-operators/'] --- # Cast 函数和操作符 diff --git a/reference/sql/functions-and-operators/control-flow-functions.md b/functions-and-operators/control-flow-functions.md similarity index 92% rename from reference/sql/functions-and-operators/control-flow-functions.md rename to functions-and-operators/control-flow-functions.md index 407a57690777..e39f5a017d7c 100644 --- a/reference/sql/functions-and-operators/control-flow-functions.md +++ b/functions-and-operators/control-flow-functions.md @@ -1,6 +1,7 @@ --- title: 控制流程函数 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/control-flow-functions/'] --- # 控制流程函数 diff --git a/reference/sql/functions-and-operators/date-and-time-functions.md b/functions-and-operators/date-and-time-functions.md similarity index 98% rename from reference/sql/functions-and-operators/date-and-time-functions.md rename to functions-and-operators/date-and-time-functions.md index e9bf3ab4b279..d19385f8b546 100644 --- a/reference/sql/functions-and-operators/date-and-time-functions.md +++ b/functions-and-operators/date-and-time-functions.md @@ -1,6 +1,7 @@ --- title: 日期和时间函数 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/date-and-time-functions/'] --- # 日期和时间函数 diff --git a/reference/sql/functions-and-operators/encryption-and-compression-functions.md b/functions-and-operators/encryption-and-compression-functions.md similarity index 97% rename from reference/sql/functions-and-operators/encryption-and-compression-functions.md rename to functions-and-operators/encryption-and-compression-functions.md index 34b2a6bbd8fa..d3bf2791ad50 100644 --- a/reference/sql/functions-and-operators/encryption-and-compression-functions.md +++ b/functions-and-operators/encryption-and-compression-functions.md @@ -1,6 +1,7 @@ --- title: 加密和压缩函数 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/encryption-and-compression-functions/'] --- # 加密和压缩函数 diff --git a/functions-and-operators/expressions-pushed-down.md b/functions-and-operators/expressions-pushed-down.md new file mode 100644 index 000000000000..732d763fe775 --- /dev/null +++ b/functions-and-operators/expressions-pushed-down.md @@ -0,0 +1,173 @@ +--- +title: 下推到 TiKV 的表达式列表 +summary: TiDB 中下推到 TiKV 的表达式列表及相关设置。 +category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/expressions-pushed-down/'] +--- + +# 下推到 TiKV 的表达式列表 + +当 TiDB 从 TiKV 中读取数据的时候,TiDB 会尽量下推一些表达式运算到 TiKV 中,从而减少数据传输量以及 TiDB 单一节点的计算压力。本文将介绍 TiDB 已支持下推的表达式,以及如何禁止下推特定表达式。 + +## 已支持下推的表达式列表 + +| 表达式分类 | 具体操作 | +| :-------------- | :------------------------------------- | +| [逻辑运算](/functions-and-operators/operators.md#逻辑操作符) | AND (&&), OR (||), NOT (!) | +| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | <, <=, =, != (`<>`), >, >=, [`<=>`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal-to), [`IN()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in), IS NULL, LIKE, IS TRUE, IS FALSE, [`COALESCE()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce) | +| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | +, -, *, /, [`ABS()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs), [`CEIL()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil), [`CEILING()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceiling), [`FLOOR()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor) | +| [控制流运算](/functions-and-operators/control-flow-functions.md) | [`CASE`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#operator_case), [`IF()`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_if), [`IFNULL()`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_ifnull) | +| [JSON运算](/functions-and-operators/json-functions.md) | [JSON_TYPE(json_val)][json_type],
[JSON_EXTRACT(json_doc, path[, path] ...)][json_extract],
[JSON_UNQUOTE(json_val)][json_unquote],
[JSON_OBJECT(key, val[, key, val] ...)][json_object],
[JSON_ARRAY([val[, val] ...])][json_array],
[JSON_MERGE(json_doc, json_doc[, json_doc] ...)][json_merge],
[JSON_SET(json_doc, path, val[, path, val] ...)][json_set],
[JSON_INSERT(json_doc, path, val[, path, val] ...)][json_insert],
[JSON_REPLACE(json_doc, path, val[, path, val] ...)][json_replace],
[JSON_REMOVE(json_doc, path[, path] ...)][json_remove] | +| [日期运算](/functions-and-operators/date-and-time-functions.md) | [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format) | + +## 禁止特定表达式下推 + +当函数的计算过程由于下推而出现异常时,可通过黑名单功能禁止其下推来快速恢复业务。具体而言,你可以将上述支持的函数或运算符名加入黑名单 `mysql.expr_pushdown_blacklist` 中,以禁止特定表达式下推。 + +`mysql.expr_pushdown_blacklist` 的 schema 如下: + +```sql +tidb> desc mysql.expr_pushdown_blacklist; ++------------+--------------+------+------+-------------------+-------+ +| Field | Type | Null | Key | Default | Extra | ++------------+--------------+------+------+-------------------+-------+ +| name | char(100) | NO | | NULL | | +| store_type | char(100) | NO | | tikv,tiflash,tidb | | +| reason | varchar(200) | YES | | NULL | | ++------------+--------------+------+------+-------------------+-------+ +3 rows in set (0.00 sec) +``` + +以上结果字段解释如下: + ++ `name`:禁止下推的函数名。 ++ `store_type`:用于指明希望禁止该函数下推到哪些组件进行计算。组件可选 `tidb`、`tikv` 和 `tiflash`。`store_type` 不区分大小写,如果需要禁止向多个存储引擎下推,各个存储之间需用逗号隔开。 + - `store_type` 为 `tidb` 时表示在读取 TiDB 内存表时,是否允许该函数在其他 TiDB Server 上执行。 + - `store_type` 为 `tikv` 时表示是否允许该函数在 TiKV Server 的 Coprocessor 模块中执行。 + - `store_type` 为 `tiflash` 时表示是否允许该函数在 TiFlash Server 的 Coprocessor 模块中执行。 ++ `reason`:用于记录该函数被加入黑名单的原因。 + +> **注意**: +> +> `tidb` 是一种特殊的 store_type,其含义是 TiDB 内存表,比如:`PERFORMANCE_SCHEMA.events_statements_summary_by_digest`,属于系统表的一种,非特殊情况不用考虑这种存储引擎。 + +### 加入黑名单 + +执行以下步骤,可将一个或多个函数或运算符加入黑名单: + +1. 向 `mysql.expr_pushdown_blacklist` 插入对应的函数名或运算符名以及希望禁止下推的存储类型集合。 +2. 执行 `admin reload expr_pushdown_blacklist;`。 + +### 移出黑名单 + +执行以下步骤,可将一个或多个函数及运算符移出黑名单: + +1. 从 `mysql.expr_pushdown_blacklist` 表中删除对应的函数名或运算符名。 +2. 执行 `admin reload expr_pushdown_blacklist;`。 + +### 黑名单用法示例 + +以下示例首先将运算符 `<` 及 `>` 加入黑名单,然后将运算符 `>` 从黑名单中移出。 + +黑名单是否生效可以从 `explain` 结果中进行观察(参见[如何理解 `explain` 结果](/query-execution-plan.md))。 + +```sql +tidb> create table t(a int); +Query OK, 0 rows affected (0.06 sec) + +tidb> explain select * from t where a < 2 and a > 2; ++-------------------------+----------+-----------+---------------+------------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------+----------+-----------+---------------+------------------------------------+ +| TableReader_7 | 0.00 | root | | data:Selection_6 | +| └─Selection_6 | 0.00 | cop[tikv] | | gt(ssb_1.t.a, 2), lt(ssb_1.t.a, 2) | +| └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | ++-------------------------+----------+-----------+---------------+------------------------------------+ +3 rows in set (0.00 sec) + +tidb> insert into mysql.expr_pushdown_blacklist values('<', 'tikv',''), ('>','tikv',''); +Query OK, 2 rows affected (0.01 sec) +Records: 2 Duplicates: 0 Warnings: 0 + +tidb> admin reload expr_pushdown_blacklist; +Query OK, 0 rows affected (0.00 sec) + +tidb> explain select * from t where a < 2 and a > 2; ++-------------------------+----------+-----------+---------------+------------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------+----------+-----------+---------------+------------------------------------+ +| Selection_7 | 10000.00 | root | | gt(ssb_1.t.a, 2), lt(ssb_1.t.a, 2) | +| └─TableReader_6 | 10000.00 | root | | data:TableFullScan_5 | +| └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | ++-------------------------+----------+-----------+---------------+------------------------------------+ +3 rows in set (0.00 sec) + +tidb> delete from mysql.expr_pushdown_blacklist where name = '>'; +Query OK, 1 row affected (0.01 sec) + +tidb> admin reload expr_pushdown_blacklist; +Query OK, 0 rows affected (0.00 sec) + +tidb> explain select * from t where a < 2 and a > 2; ++---------------------------+----------+-----------+---------------+--------------------------------+ +| id | estRows | task | access object | operator info | ++---------------------------+----------+-----------+---------------+--------------------------------+ +| Selection_8 | 0.00 | root | | lt(ssb_1.t.a, 2) | +| └─TableReader_7 | 0.00 | root | | data:Selection_6 | +| └─Selection_6 | 0.00 | cop[tikv] | | gt(ssb_1.t.a, 2) | +| └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | ++---------------------------+----------+-----------+---------------+--------------------------------+ +4 rows in set (0.00 sec) +``` + +> **注意:** +> +> - `admin reload expr_pushdown_blacklist` 只对执行该 SQL 语句的 TiDB server 生效。若需要集群中所有 TiDB server 生效,需要在每台 TiDB server 上执行该 SQL 语句。 +> - 表达式黑名单功能在 v3.0.0 及以上版本中支持。 +> - 在 v3.0.3 及以下版本中,不支持将某些运算符的原始名称文本(如 ">"、"+" 和 "is null")加入黑名单中,部分运算符在黑名单中需使用别名。已支持下推的表达式中,别名与原始名不同的运算符见下表(区分大小写)。 + +| 运算符原始名称 | 运算符别名 | +| :-------- | :---------- | +| < | lt | +| > | gt | +| <= | le | +| >= | ge | +| = | eq | +| != | ne | +| `<>` | ne | +| <=> | nulleq | +| | | bitor | +| && | bitand| +| || | or | +| ! | not | +| in | in | +| + | plus| +| - | minus | +| * | mul | +| / | div | +| DIV | intdiv| +| IS NULL | isnull | +| IS TRUE | istrue | +| IS FALSE | isfalse | + +[json_extract]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-extract +[json_short_extract]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#operator_json-column-path +[json_short_extract_unquote]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#operator_json-inline-path +[json_unquote]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-unquote +[json_type]: https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-type +[json_set]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-set +[json_insert]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-insert +[json_replace]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-replace +[json_remove]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-remove +[json_merge]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge +[json_merge_preserve]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge-preserve +[json_object]: https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-object +[json_array]: https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-array +[json_keys]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-keys +[json_length]: https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-length +[json_valid]: https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-valid +[json_quote]: https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-quote +[json_contains]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-contains +[json_contains_path]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-contains-path +[json_arrayagg]: https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_json-arrayagg +[json_depth]: https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-depth diff --git a/functions-and-operators/functions-and-operators-overview.md b/functions-and-operators/functions-and-operators-overview.md new file mode 100644 index 000000000000..6c24c7786295 --- /dev/null +++ b/functions-and-operators/functions-and-operators-overview.md @@ -0,0 +1,13 @@ +--- +title: 函数和操作符概述 +category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/reference/'] +--- + +# 函数和操作符概述 + +TiDB 中函数和操作符使用方法与 MySQL 基本一致,详情参见: [Functions and Operators](https://dev.mysql.com/doc/refman/5.7/en/functions.html)。 + +在 SQL 语句中,表达式可用于诸如 `SELECT` 语句的 `ORDER BY` 或 `HAVING` 子句,`SELECT`/`DELETE`/`UPDATE` 语句的 `WHERE` 子句,或 `SET` 语句之类的地方。 + +可使用字面值,列名,NULL,内置函数,操作符等来书写表达式。其中有些表达式下推到 TiKV 上执行,详见[下推到 TiKV 的表达式列表](/functions-and-operators/expressions-pushed-down.md)。 diff --git a/reference/sql/functions-and-operators/information-functions.md b/functions-and-operators/information-functions.md similarity index 96% rename from reference/sql/functions-and-operators/information-functions.md rename to functions-and-operators/information-functions.md index b3ec39c0d40a..25aba69f29db 100644 --- a/reference/sql/functions-and-operators/information-functions.md +++ b/functions-and-operators/information-functions.md @@ -1,6 +1,7 @@ --- title: 信息函数 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/information-functions/'] --- # 信息函数 diff --git a/functions-and-operators/json-functions.md b/functions-and-operators/json-functions.md new file mode 100644 index 000000000000..ed697804c252 --- /dev/null +++ b/functions-and-operators/json-functions.md @@ -0,0 +1,91 @@ +--- +title: JSON 函数及语法糖 +category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/json-functions/'] +--- + +# JSON 函数及语法糖 + +> **警告:** +> +> 当前该功能为实验特性,不建议在生产环境中使用。 + +TiDB 支持 MySQL 5.7 GA 版本发布的大多数 JSON 函数。MySQL 5.7 发布后,又增加了更多 JSON 函数,TiDB 并未支持所有这些函数(参见[未支持的函数](#未支持的函数))。 + +## 创建 JSON 值的函数 + +| 函数及语法糖 | 功能描述 | +| ------------------------------------------------------------------ | ---------------------------------------------------------- | +| [JSON_ARRAY([val[, val] ...])][json_array] | 根据一系列元素创建一个 JSON 文档 | +| [JSON_OBJECT(key, val[, key, val] ...)][json_object] | 根据一系列 K/V 对创建一个 JSON 文档 | +| [JSON_QUOTE(string)][json_quote] | 返回一个字符串,该字符串为带引号的 JSON 值 | + +## 搜索 JSON 值的函数 + +| 函数及语法糖 | 功能描述 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| [JSON_CONTAINS(target, candidate[, path])][json_contains] | 通过返回 1 或 0 来表示目标 JSON 文档中是否包含给定的 candidate JSON 文档 | +| [JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...)][json_contains_path] | 通过返回 0 或 1 来表示一个 JSON 文档在给定路径是否包含数据 | +| [JSON_EXTRACT(json_doc, path[, path] ...)][json_extract] | 从 JSON 文档中解出某一路径对应的子文档 | +| [->][json_short_extract] | 返回执行路径后面的 JSON 列的值;`JSON_EXTRACT(doc, path_literal)` 的语法糖 | +| [->>][json_short_extract_unquote] | 返回执行路径后面的 JSON 列的值和转义后的结果; `JSON_UNQUOTE(JSON_EXTRACT(doc, path_literal))` 的语法糖 | +| [JSON_KEYS(json_doc[, path])][json_keys] | 返回从 JSON 对象的顶级值作为 JSON array 的键,如果给定了路径参数,则从选定路径中获取顶级键 | +| [JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...])][json_search] | 返回指定字符在 JSON 文档中的路径 | + +## 修改 JSON 值的函数 + +| 函数及语法糖 | 功能描述 | +| --------------------------------- | ----------- | +| [JSON_INSERT(json_doc, path, val[, path, val] ...)][json_insert] | 在 JSON 文档中在某一路径下插入子文档 | +| [JSON_MERGE(json_doc, json_doc[, json_doc] ...)][json_merge] | 已废弃的 `JSON_MERGE_PRESERVE` 别名 | +| [JSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc] ...)][json_merge_preserve] | 将两个或多个 JSON 文档合并成一个文档,并返回合并结果 | +| [JSON_REMOVE(json_doc, path[, path] ...)][json_remove] | 移除 JSON 文档中某一路径下的子文档 | +| [JSON_REPLACE(json_doc, path, val[, path, val] ...)][json_replace] | 替换 JSON 文档中的某一路径下的子文档 | +| [JSON_SET(json_doc, path, val[, path, val] ...)][json_set] | 在 JSON 文档中为某一路径设置子文档 | +| [JSON_UNQUOTE(json_val)][json_unquote] | 去掉 JSON 值外面的引号,返回结果为字符串 | +| [JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)][json_array_append] | 将值添加到 JSON 文档指定数组的末尾,并返回添加结果 | +| [JSON_ARRAY_INSERT(json_doc, path, val[, path, val] ...)][json_array_insert] | 将值插入到 JSON 文档的指定位置,并返回插入结果 | + +## 返回 JSON 值属性的函数 + +| 函数及语法糖 | 功能描述 | +| --------------------------------- | ----------- | +| [JSON_DEPTH(json_doc)][json_depth] | 返回 JSON 文档的最大深度 | +| [JSON_LENGTH(json_doc[, path])][json_length] | 返回 JSON 文档的长度;如果路径参数已定,则返回该路径下值的长度 | +| [JSON_TYPE(json_val)][json_type] | 检查某 JSON 文档内部内容的类型 | +| [JSON_VALID(json_val)][json_valid] | 检查某 JSON 文档的内容是否有效 | + +## 未支持的函数 + +TiDB 暂未支持以下 JSON 函数。相关进展参见 [TiDB #7546](https://github.com/pingcap/tidb/issues/7546): + +* `JSON_MERGE_PATCH` +* `JSON_PRETTY` +* `JSON_STORAGE_SIZE` +* `JSON_ARRAYAGG` +* `JSON_OBJECTAGG` + +[json_extract]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-extract +[json_short_extract]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#operator_json-column-path +[json_short_extract_unquote]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#operator_json-inline-path +[json_unquote]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-unquote +[json_type]: https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-type +[json_set]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-set +[json_insert]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-insert +[json_replace]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-replace +[json_remove]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-remove +[json_merge]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge +[json_merge_preserve]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge-preserve +[json_object]: https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-object +[json_array]: https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-array +[json_keys]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-keys +[json_length]: https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-length +[json_valid]: https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-valid +[json_quote]: https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-quote +[json_contains]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-contains +[json_contains_path]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-contains-path +[json_arrayagg]: https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_json-arrayagg +[json_depth]: https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-depth +[json_array_append]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-array-append +[json_array_insert]: https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-array-insert +[json_search]: https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-search diff --git a/reference/sql/functions-and-operators/miscellaneous-functions.md b/functions-and-operators/miscellaneous-functions.md similarity index 97% rename from reference/sql/functions-and-operators/miscellaneous-functions.md rename to functions-and-operators/miscellaneous-functions.md index 6d6c68fd6fc2..d375b50f3f0d 100644 --- a/reference/sql/functions-and-operators/miscellaneous-functions.md +++ b/functions-and-operators/miscellaneous-functions.md @@ -1,6 +1,7 @@ --- title: 其他函数 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/miscellaneous-functions/'] --- # 其他函数 diff --git a/reference/sql/functions-and-operators/numeric-functions-and-operators.md b/functions-and-operators/numeric-functions-and-operators.md similarity index 98% rename from reference/sql/functions-and-operators/numeric-functions-and-operators.md rename to functions-and-operators/numeric-functions-and-operators.md index afd6772b2ad4..1bb14693d4e9 100644 --- a/reference/sql/functions-and-operators/numeric-functions-and-operators.md +++ b/functions-and-operators/numeric-functions-and-operators.md @@ -1,6 +1,7 @@ --- title: 数值函数与操作符 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/numeric-functions-and-operators/'] --- # 数值函数与操作符 diff --git a/reference/sql/functions-and-operators/operators.md b/functions-and-operators/operators.md similarity index 99% rename from reference/sql/functions-and-operators/operators.md rename to functions-and-operators/operators.md index 5873bd446bf4..9ed84343485c 100644 --- a/reference/sql/functions-and-operators/operators.md +++ b/functions-and-operators/operators.md @@ -1,6 +1,7 @@ --- title: 操作符 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/operators/'] --- # 操作符 diff --git a/reference/sql/functions-and-operators/precision-math.md b/functions-and-operators/precision-math.md similarity index 98% rename from reference/sql/functions-and-operators/precision-math.md rename to functions-and-operators/precision-math.md index dc6953bb5a23..2b73420af4c4 100644 --- a/reference/sql/functions-and-operators/precision-math.md +++ b/functions-and-operators/precision-math.md @@ -1,6 +1,7 @@ --- title: 精度数学 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/precision-math/'] --- # 精度数学 diff --git a/reference/sql/functions-and-operators/string-functions.md b/functions-and-operators/string-functions.md similarity index 98% rename from reference/sql/functions-and-operators/string-functions.md rename to functions-and-operators/string-functions.md index 6ebc49116845..b4887f71b214 100644 --- a/reference/sql/functions-and-operators/string-functions.md +++ b/functions-and-operators/string-functions.md @@ -1,6 +1,7 @@ --- title: 字符串函数 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/string-functions/'] --- # 字符串函数 diff --git a/functions-and-operators/type-conversion-in-expression-evaluation.md b/functions-and-operators/type-conversion-in-expression-evaluation.md new file mode 100644 index 000000000000..56f3673f513a --- /dev/null +++ b/functions-and-operators/type-conversion-in-expression-evaluation.md @@ -0,0 +1,9 @@ +--- +title: 表达式求值的类型转换 +category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/type-conversion/'] +--- + +# 表达式求值的类型转换 + +TiDB 中表达式求值的类型转换与 MySQL 基本一致,详情参见 [MySQL 表达式求值的类型转换](https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html)。 diff --git a/reference/sql/functions-and-operators/window-functions.md b/functions-and-operators/window-functions.md similarity index 96% rename from reference/sql/functions-and-operators/window-functions.md rename to functions-and-operators/window-functions.md index e9f47078d46f..8fb3f7d4d6d1 100644 --- a/reference/sql/functions-and-operators/window-functions.md +++ b/functions-and-operators/window-functions.md @@ -1,6 +1,7 @@ --- title: 窗口函数 category: reference +aliases: ['/docs-cn/stable/reference/sql/functions-and-operators/window-functions/'] --- # 窗口函数 diff --git a/garbage-collection-configuration.md b/garbage-collection-configuration.md new file mode 100644 index 000000000000..7aee4b8d9d64 --- /dev/null +++ b/garbage-collection-configuration.md @@ -0,0 +1,147 @@ +--- +title: GC 配置 +category: reference +aliases: ['/docs-cn/stable/reference/garbage-collection/configuration/'] +--- + +# GC 配置 + +TiDB 的 GC 相关的配置存储于 `mysql.tidb` 系统表中,可以通过 SQL 语句对这些参数进行查询和更改: + +{{< copyable "sql" >}} + +```sql +select VARIABLE_NAME, VARIABLE_VALUE from mysql.tidb where VARIABLE_NAME like "tikv_gc%"; +``` + +``` ++--------------------------+----------------------------------------------------------------------------------------------------+ +| VARIABLE_NAME | VARIABLE_VALUE | ++--------------------------+----------------------------------------------------------------------------------------------------+ +| tikv_gc_leader_uuid | 5afd54a0ea40005 | +| tikv_gc_leader_desc | host:tidb-cluster-tidb-0, pid:215, start at 2019-07-15 11:09:14.029668932 +0000 UTC m=+0.463731223 | +| tikv_gc_leader_lease | 20190715-12:12:14 +0000 | +| tikv_gc_enable | true | +| tikv_gc_run_interval | 10m0s | +| tikv_gc_life_time | 10m0s | +| tikv_gc_last_run_time | 20190715-12:09:14 +0000 | +| tikv_gc_safe_point | 20190715-11:59:14 +0000 | +| tikv_gc_auto_concurrency | true | +| tikv_gc_mode | distributed | ++--------------------------+----------------------------------------------------------------------------------------------------+ +13 rows in set (0.00 sec) +``` + +例如,如果需要将 GC 调整为保留最近一天以内的数据,只需执行下列语句即可: + +{{< copyable "sql" >}} + +```sql +update mysql.tidb set VARIABLE_VALUE="24h" where VARIABLE_NAME="tikv_gc_life_time"; +``` + +> **注意:** +> +> `mysql.tidb` 系统表中除了下文列出的 GC 的配置以外,还包含一些 TiDB 用于储存部分集群状态(包括 GC 状态)的记录。请勿手动更改这些记录。其中,与 GC 有关的记录如下: +> +> - `tikv_gc_leader_uuid`,`tikv_gc_leader_desc` 和 `tikv_gc_leader_lease` 用于记录 GC leader 的状态 +> - `tikv_gc_last_run_time`:最近一次 GC 运行的时间(每轮 GC 开始时更新) +> - `tikv_gc_safe_point`:当前的 safe point (每轮 GC 开始时更新) + +## `tikv_gc_enable` + +- 控制是否启用 GC。 +- 默认值:`true` + +## `tikv_gc_run_interval` + +- 指定 GC 运行时间间隔。Duration 类型,使用 Go 的 Duration 字符串格式,如 `"1h30m"`,`"15m"` 等。 +- 默认值:`"10m0s"` + +## `tikv_gc_life_time` + +- 每次 GC 时,保留数据的时限。Duration 类型。每次 GC 时将以当前时间减去该配置的值作为 safe point。 +- 默认值:`"10m0s"` + +> **注意:** +> +> - 在数据更新频繁的场景下,如果将 `tikv_gc_life_time` 设置得比较大(如数天甚至数月),可能会有一些潜在的问题,如: +> - 磁盘空间占用较多。 +> - 大量的历史版本会在一定程度上影响性能,尤其是范围查询(如 `select count(*) from t`)。 +> - 如果存在运行时间很长、超过了 `tikv_gc_life_time` 的事务,那么在 GC 时,会保留自该事务的开始时间 (start_ts) 以来的数据,以允许该事务继续运行。例如,如果 `tikv_gc_life_time` 配置为 10 分钟,而某次 GC 时,集群中正在运行的事务中开始时间最早的一个事务已经运行了 15 分钟,那么本次 GC 便会保留最近 15 分钟的数据。 + +## `tikv_gc_mode` + +指定 GC 模式。可选值如下: + +- `"distributed"`(默认):分布式 GC 模式。在此模式下,[Do GC](/garbage-collection-overview.md#do-gc) 阶段由 TiDB 上的 GC leader 向 PD 发送 safe point,每个 TiKV 节点各自获取该 safe point 并对所有当前节点上作为 leader 的 Region 进行 GC。此模式于 TiDB 3.0 引入。 + +- `"central"`:集中 GC 模式。在此模式下,[Do GC](/garbage-collection-overview.md#do-gc) 阶段由 GC leader 向所有的 Region 发送 GC 请求。TiDB 2.1 及更早版本采用此 GC 模式。 + +## `tikv_gc_auto_concurrency` + +控制是否由 TiDB 自动决定 GC concurrency,即同时进行 GC 的线程数。 + +当 `tikv_gc_mode` 设为 `"distributed"`,GC concurrency 将应用于 [Resolve Locks](/garbage-collection-overview.md#resolve-locks) 阶段。当 [`tikv_gc_mode`](#tikv_gc_mode) 设为 `"central"` 时,GC concurrency 将应用于 Resolve Locks 以及 [Do GC](/garbage-collection-overview.md#do-gc) 两个阶段。 + +- `true`(默认):自动以 TiKV 节点的个数作为 GC concurrency +- `false`:使用 [`tikv_gc_concurrency`](#tikv_gc_concurrency) 的值作为 GC 并发数 + +## `tikv_gc_concurrency` + +- 手动设置 GC concurrency。要使用该参数,必须将 [`tikv_gc_auto_concurrency`](#tikv_gc_auto_concurrency) 设为 `false` 。 +- 默认值:2 + +## `tikv_gc_scan_lock_mode` + +> **注意:** +> +> 该功能目前为实验特性,不建议在生产环境中使用。 + +设定 GC 的 Resolve Locks 阶段中,扫描锁的方式,即是否开启 Green GC(实验性特性)。Resolve Locks 阶段需要扫描整个集群的锁。在不开启 Green GC 的情况下,TiDB 会以 Region 为单位进行扫描。Green GC 提供了“物理扫描”的功能,即每台 TiKV 节点分别绕过 Raft 层直接扫描数据。该功能可以有效缓解 [Hibernate Region](/tikv-configuration-file.md#raftstorehibernate-regions-实验特性) 功能开启时,GC 唤醒全部 Region 的现象,并一定程度上提升 Resolve Locks 阶段的执行速度。 + +- `"legacy"`(默认):使用旧的扫描方式,即关闭 Green GC。 +- `"physical"`:使用物理扫描的方式,即开启 Green GC。 + +> **注意:** +> +> Green GC 目前是实验性功能,不建议在生产环境中使用。 +> +> 该项配置是隐藏配置。首次开启需要执行: +> +> {{< copyable "sql" >}} +> +> ```sql +> insert into mysql.tidb values ('tikv_gc_scan_lock_mode', 'legacy', ''); +> ``` + +## 关于 GC 流程的说明 + +从 TiDB 3.0 版本起,由于对分布式 GC 模式和并行 Resolve Locks 的支持,部分配置选项的作用发生了变化。可根据下表理解不同版本中这些配置的区别: + +| 版本/配置 | Resolve Locks | Do GC | +|-------------------|---------------|----------------| +| 2.x | 串行 | 并行 | +| 3.0
`tikv_gc_mode = centered`
`tikv_gc_auto_concurrency = false` | 并行 | 并行 | +| 3.0
`tikv_gc_mode = centered`
`tikv_gc_auto_concurrency = true` | 自动并行 | 自动并行 | +| 3.0
`tikv_gc_mode = distributed`
`tikv_gc_auto_concurrency = false` | 并行 | 分布式 | +| 3.0
`tikv_gc_mode = distributed`
`tikv_gc_auto_concurrency = true`
(默认配置) | 自动并行 | 分布式 | + +表格内容说明: + +- 串行:由 TiDB 逐个向 Region 发送请求。 +- 并行:使用 `tikv_gc_concurrency` 选项所指定的线程数,并行地向每个 Region 发送请求。 +- 自动并行:使用 TiKV 节点的个数作为线程数,并行地向每个 Region 发送请求。 +- 分布式:无需 TiDB 通过对 TiKV 发送请求的方式来驱动,而是每台 TiKV 自行工作。 + +另外,如果 Green GC (实验特性)开启(即 [`tikv_gc_scan_lock_mode`](#tikv_gc_scan_lock_mode-实验特性) 配置项设为 `"physical"`),Resolve Lock 的执行将不受上述并行配置的影响。 + +## 流控 + +TiKV 在 3.0.6 版本开始支持 GC 流控,可通过配置 `gc.max-write-bytes-per-sec` 限制 GC worker 每秒数据写入量,降低对正常请求的影响,`0` 为关闭该功能。该配置可通过 tikv-ctl 动态修改: + +{{< copyable "shell-regular" >}} + +```bash +tikv-ctl --host=ip:port modify-tikv-config -m server -n gc.max_write_bytes_per_sec -v 10MB +``` diff --git a/garbage-collection-overview.md b/garbage-collection-overview.md new file mode 100644 index 000000000000..deac71f1bd43 --- /dev/null +++ b/garbage-collection-overview.md @@ -0,0 +1,45 @@ +--- +title: GC 机制简介 +category: reference +aliases: ['/docs-cn/stable/reference/garbage-collection/overview/'] +--- + +# GC 机制简介 + +TiDB 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。GC 的任务便是清理不再需要的旧数据。 + +## 整体流程 + +一个 TiDB 集群中会有一个 TiDB 实例被选举为 GC leader,GC 的运行由 GC leader 来控制。 + +GC 会被定期触发。每次 GC 时,首先,TiDB 会计算一个称为 safe point 的时间戳,接下来 TiDB 会在保证 safe point 之后的快照全部拥有正确数据的前提下,删除更早的过期数据。每一轮 GC 分为以下三个步骤: + +1. Resolve Locks。该阶段会对所有 Region 扫描 safe point 之前的锁,并清理这些锁。 +2. Delete Ranges。该阶段快速地删除由于 `DROP TABLE`/`DROP INDEX` 等操作产生的整区间的废弃数据。 +3. Do GC。该阶段每个 TiKV 节点将会各自扫描该节点上的数据,并对每一个 key 删除其不再需要的旧版本。 + +默认配置下,GC 每 10 分钟触发一次,每次 GC 会保留最近 10 分钟内的数据(即默认 GC life time 为 10 分钟,safe point 的计算方式为当前时间减去 GC life time)。如果一轮 GC 运行时间太久,那么在一轮 GC 完成之前,即使到了下一次触发 GC 的时间也不会开始下一轮 GC。另外,为了使持续时间较长的事务能在超过 GC life time 之后仍然可以正常运行,safe point 不会超过正在执行中的事务的开始时间 (start_ts)。 + +## 实现细节 + +### Resolve Locks(清理锁) + +TiDB 的事务是基于 [Google Percolator](https://ai.google/research/pubs/pub36726) 模型实现的,事务的提交是一个两阶段提交的过程。第一阶段完成时,所有涉及的 key 都会上锁,其中一个锁会被选为 Primary,其余的锁 (Secondary) 则会存储一个指向 Primary 的指针;第二阶段会将 Primary 锁所在的 key 加上一个 Write 记录,并去除锁。这里的 Write 记录就是历史上对该 key 进行写入或删除,或者该 key 上发生事务回滚的记录。Primary 锁被替换为何种 Write 记录标志着该事务提交成功与否。接下来,所有 Secondary 锁也会被依次替换。如果因为某些原因(如发生故障等),这些 Secondary 锁没有完成替换、残留了下来,那么也可以根据锁中的信息取找到 Primary,并根据 Primary 是否提交来判断整个事务是否提交。但是,如果 Primary 的信息在 GC 中被删除了,而该事务又存在未成功提交的 Secondary 锁,那么就永远无法得知该锁是否可以提交。这样,数据的正确性就无法保证。 + +Resolve Locks 这一步的任务即对 safe point 之前的锁进行清理。即如果一个锁对应的 Primary 已经提交,那么该锁也应该被提交;反之,则应该回滚。而如果 Primary 仍然是上锁的状态(没有提交也没有回滚),则应当将该事务视为超时失败而回滚。 + +Resolve Locks 的执行方式是由 GC leader 对所有的 Region 发送请求扫描过期的锁,并对扫到的锁查询 Primary 的状态,再发送请求对其进行提交或回滚。这个过程默认会并行地执行,并发数量默认与 TiKV 节点个数相同。 + +### Delete Ranges(删除区间) + +在执行 `DROP TABLE/INDEX` 等操作时,会有大量连续的数据被删除。如果对每个 key 都进行删除操作、再对每个 key 进行 GC 的话,那么执行效率和空间回收速度都可能非常的低下。事实上,这种时候 TiDB 并不会对每个 key 进行删除操作,而是将这些待删除的区间及删除操作的时间戳记录下来。Delete Ranges 会将这些时间戳在 safe point 之前的区间进行快速的物理删除。 + +### Do GC(进行 GC 清理) + +这一步即删除所有 key 的过期版本。为了保证 safe point 之后的任何时间戳都具有一致的快照,这一步删除 safe point 之前提交的数据,但是会对每个 key 保留 safe point 前的最后一次写入(除非最后一次写入是删除)。 + +在进行这一步时,TiDB 只需要将 safe point 发送给 PD,即可结束整轮 GC。TiKV 会自行检测到 safe point 发生了更新,会对当前节点上所有作为 Region leader 进行 GC。与此同时,GC leader 可以继续触发下一轮 GC。 + +> **注意:** +> +> TiDB v2.1 以及更早的版本中,Do GC 这一步是通过由 TiDB 对每个 Region 发送请求的方式实现的。在 v3.0 及更新的版本中,通过修改配置可以继续使用旧的 GC 方式,详情请参考 [GC 配置](/garbage-collection-configuration.md#tikv_gc_mode)。 diff --git a/generate-self-signed-certificates.md b/generate-self-signed-certificates.md new file mode 100644 index 000000000000..243cf3759d75 --- /dev/null +++ b/generate-self-signed-certificates.md @@ -0,0 +1,177 @@ +--- +title: 生成自签名证书 +category: how-to +aliases: ['/docs-cn/stable/how-to/secure/generate-self-signed-certificates/'] +--- + +# 生成自签名证书 + +本文档提供使用 `openssl` 生成自签名证书的一个示例,用户也可以根据自己的需求生成符合要求的证书和密钥。 + +假设实例集群拓扑如下: + +| Name | Host IP | Services | +| ----- | ----------- | ---------- | +| node1 | 172.16.10.11 | PD1, TiDB1 | +| node2 | 172.16.10.12 | PD2 | +| node3 | 172.16.10.13 | PD3 | +| node4 | 172.16.10.14 | TiKV1 | +| node5 | 172.16.10.15 | TiKV2 | +| node6 | 172.16.10.16 | TiKV3 | + +## 安装 OpenSSL + +对于 Debian 或 Ubuntu 操作系统: + +{{< copyable "shell-regular" >}} + +```bash +apt install openssl +``` + +对于 RedHat 或 CentOS 操作系统: + +{{< copyable "shell-regular" >}} + +```bash +yum install openssl +``` + +也可以参考 OpenSSL 官方的[下载文档](https://www.openssl.org/source/) 进行安装。 + +## 生成 CA 证书 + +CA 的作用是签发证书。实际情况中,请联系你的管理员签发证书或者使用信任的 CA 机构。CA 会管理多个证书对,这里只需生成原始的一对证书,步骤如下: + +1. 生成 root 密钥: + + {{< copyable "shell-regular" >}} + + ```bash + openssl genrsa -out root.key 4096 + ``` + +2. 生成 root 证书: + + {{< copyable "shell-regular" >}} + + ```bash + openssl req -new -x509 -days 1000 -key root.key -out root.crt + ``` + +3. 验证 root 证书: + + {{< copyable "shell-regular" >}} + + ```bash + openssl x509 -text -in root.crt -noout + ``` + +## 签发各个组件的证书 + +### 集群中可能使用到的证书 + +- tidb certificate 由 TiDB 使用,为其他组件和客户端验证 TiDB 身份。 +- tikv certificate 由 TiKV 使用,为其他组件和客户端验证 TiKV 身份。 +- pd certificate 由 PD 使用,为其他组件和客户端验证 PD 身份。 +- client certificate 用于 PD、TiKV、TiDB 验证客户端。例如 `pd-ctl`,`tikv-ctl` 等。 + +### 给 TiKV 实例签发证书 + +给 TiKV 实例签发证书的步骤如下: + +1. 生成该证书对应的私钥: + + {{< copyable "shell-regular" >}} + + ```bash + openssl genrsa -out tikv.key 2048 + ``` + +2. 拷贝一份 OpenSSL 的配置模板文件。 + + 模板文件可能存在多个位置,请以实际位置为准: + + {{< copyable "shell-regular" >}} + + ```bash + cp /usr/lib/ssl/openssl.cnf . + ``` + + 如果不知道实际位置,请在根目录下查找: + + ```bash + find / -name openssl.cnf + ``` + +3. 编辑 `openssl.cnf`,在 `[ req ]` 字段下加入 `req_extensions = v3_req`,然后在 `[ v3_req ]` 字段下加入 `subjectAltName = @alt_names`。最后新建一个字段,并编辑 SAN 的信息: + + ``` + [ alt_names ] + IP.1 = 127.0.0.1 + IP.2 = 172.16.10.14 + IP.3 = 172.16.10.15 + IP.4 = 172.16.10.16 + ``` + +4. 保存 `openssl.cnf` 文件后,生成证书请求文件(在这一步也可以为该证书指定 Common Name,其作用是让服务端验证接入的客户端的身份,各个组件默认不会开启验证,需要在配置文件中启用该功能才生效): + + {{< copyable "shell-regular" >}} + + ```bash + openssl req -new -key tikv.key -out tikv.csr -config openssl.cnf + ``` + +5. 签发生成证书: + + {{< copyable "shell-regular" >}} + + ```bash + openssl x509 -req -days 365 -CA root.crt -CAkey root.key -CAcreateserial -in tikv.csr -out tikv.crt -extensions v3_req -extfile openssl.cnf + ``` + +6. 验证证书携带 SAN 字段信息(可选): + + {{< copyable "shell-regular" >}} + + ```bash + openssl x509 -text -in tikv.crt -noout + ``` + +7. 确认在当前目录下得到如下文件: + + ``` + root.crt + tikv.crt + tikv.key + ``` + +为其它 TiDB 组件签发证书的过程类似,此文档不再赘述。 + +### 为客户端签发证书 + +为客户端签发证书的步骤如下。 + +1. 生成该证书对应的私钥: + + {{< copyable "shell-regular" >}} + + ```bash + openssl genrsa -out client.key 2048 + ``` + +2. 生成证书请求文件(在这一步也可以为该证书指定 Common Name,其作用是让服务端验证接入的客户端的身份,默认不会开启对各个组件的验证,需要在配置文件中启用该功能才生效) + + {{< copyable "shell-regular" >}} + + ```bash + openssl req -new -key client.key -out client.csr + ``` + +3. 签发生成证书: + + {{< copyable "shell-regular" >}} + + ```bash + openssl x509 -req -days 365 -CA root.crt -CAkey root.key -CAcreateserial -in client.csr -out client.crt + ``` diff --git a/generated-columns.md b/generated-columns.md new file mode 100644 index 000000000000..b07568979431 --- /dev/null +++ b/generated-columns.md @@ -0,0 +1,160 @@ +--- +title: 生成列 +category: reference +aliases: ['/docs-cn/stable/reference/sql/generated-columns/'] +--- + +# 生成列 + +> **警告:** +> +> 当前该功能为实验特性,不建议在生产环境中使用。 + +本文介绍生成列的概念以及用法。 + +## 生成列的基本概念 + +与一般的列不同,生成列的值由列定义中表达式计算得到。对生成列进行插入或更新操作时,并不能对之赋值,只能使用 `DEFAULT`。 + +生成列包括存储生成列和虚拟生成列。存储生成列会将计算得到的值存储起来,在读取时不需要重新计算。虚拟生成列不会存储其值,在读取时会重新计算。存储生成列和虚拟生成列相比,前者在读取时性能更好,但是要占用更多的磁盘空间。 + +无论是存储生成列还是虚拟列,都可以在其上面建立索引。 + +## 生成列的应用 + +生成列的主要的作用之一:从 JSON 数据类型中解出数据,并为该数据建立索引。 + +MySQL 5.7 及 TiDB 都不能直接为 JSON 类型的列添加索引,即不支持在如下表结构中的 `address_info` 上建立索引: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE person ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + address_info JSON, + KEY (address_info) +); +``` + +如果要为 JSON 列某个字段添加索引,可以抽取该字段为生成列。 + +以 `city` 这一 `address_info` 中的字段为例,可以为其建立一个虚拟生成列并添加索引: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE person ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + address_info JSON, + city VARCHAR(64) AS (JSON_UNQUOTE(JSON_EXTRACT(address_info, '$.city'))), + KEY (city) +); +``` + +该表中,`city` 列是一个虚拟生成列。并且在该列上建立了索引。以下语句能够利用索引加速语句的执行速度: + +{{< copyable "sql" >}} + +```sql +SELECT name, id FROM person WHERE city = 'Beijing'; +``` + +{{< copyable "sql" >}} + +```sql +EXPLAIN SELECT name, id FROM person WHERE city = 'Beijing'; +``` + +``` ++---------------------------------+---------+-----------+--------------------------------+-------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++---------------------------------+---------+-----------+--------------------------------+-------------------------------------------------------------+ +| Projection_4 | 10.00 | root | | test.person.name, test.person.id | +| └─IndexLookUp_10 | 10.00 | root | | | +| ├─IndexRangeScan_8(Build) | 10.00 | cop[tikv] | table:person, index:city(city) | range:["Beijing","Beijing"], keep order:false, stats:pseudo | +| └─TableRowIDScan_9(Probe) | 10.00 | cop[tikv] | table:person | keep order:false, stats:pseudo | ++---------------------------------+---------+-----------+--------------------------------+-------------------------------------------------------------+ +``` + +从执行计划中,可以看出使用了 `city` 这个索引来读取满足 `city = 'Beijing'` 这个条件的行的 `HANDLE`,再用这个 `HANDLE` 来读取该行的数据。 + +如果 `$.city` 路径中无数据,则 `JSON_EXTRACT` 返回 `NULL`。如果想增加约束,`city` 列必须是 `NOT NULL`,则可按照以下方式定义虚拟生成列: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE person ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + address_info JSON, + city VARCHAR(64) AS (JSON_UNQUOTE(JSON_EXTRACT(address_info, '$.city'))) NOT NULL, + KEY (city) +); +``` + +## 生成列在 INSERT 和 UPDATE 语句中的行为 + +`INSERT` 和 `UPDATE` 语句都会检查生成列计算得到的值是否满足生成列的定义。未通过有效性检测的行会返回错误: + +{{< copyable "sql" >}} + +```sql +INSERT INTO person (name, address_info) VALUES ('Morgan', JSON_OBJECT('Country', 'Canada')); +``` + +``` +ERROR 1048 (23000): Column 'city' cannot be null +``` + +## 索引生成列替换 + +当查询中出现的某个表达式与一个含索引的生成列同等时,TiDB 会将这个表达式替换为对应的生成列,这样就可以在生成查询计划时考虑使用这个索引。 + +例如,下面的例子为 `a+1` 这个表达式创建生成列并添加索引,从而加速了查询。 + +{{< copyable "sql" >}} + +```sql +create table t(a int); +desc select a+1 from t where a+1=3; ++---------------------------+----------+-----------+---------------+--------------------------------+ +| id | estRows | task | access object | operator info | ++---------------------------+----------+-----------+---------------+--------------------------------+ +| Projection_4 | 8000.00 | root | | plus(test.t.a, 1)->Column#3 | +| └─TableReader_7 | 8000.00 | root | | data:Selection_6 | +| └─Selection_6 | 8000.00 | cop[tikv] | | eq(plus(test.t.a, 1), 3) | +| └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo | ++---------------------------+----------+-----------+---------------+--------------------------------+ +4 rows in set (0.00 sec) + +alter table t add column b bigint as (a+1) virtual; +alter table t add index idx_b(b); +desc select a+1 from t where a+1=3; ++------------------------+---------+-----------+-------------------------+---------------------------------------------+ +| id | estRows | task | access object | operator info | ++------------------------+---------+-----------+-------------------------+---------------------------------------------+ +| IndexReader_6 | 10.00 | root | | index:IndexRangeScan_5 | +| └─IndexRangeScan_5 | 10.00 | cop[tikv] | table:t, index:idx_b(b) | range:[3,3], keep order:false, stats:pseudo | ++------------------------+---------+-----------+-------------------------+---------------------------------------------+ +2 rows in set (0.01 sec) +``` + +> **注意:** +> +> 只有当待替换的表达式类型和生成列类型严格相等时,才会进行转换。 +> +> 上例中,`a` 的类型是 int,而 `a+1` 的列类型是 bigint,如果将生成列的类型定为 int,就不会发生替换。 +> +> 关于类型转换规则,可以参见[表达式求值的类型转换](/functions-and-operators/type-conversion-in-expression-evaluation.md)。 + +## 生成列的局限性 + +目前生成列有以下局限性: + +- 不能通过 `ALTER TABLE` 增加存储生成列; +- 不能通过 `ALTER TABLE` 将存储生成列转换为普通列,也不能将普通列转换成存储生成列; +- 不能通过 `ALTER TABLE` 修改存储生成列的生成列表达式; +- 并未支持所有的 [JSON 函数](/functions-and-operators/json-functions.md); +- 目前仅当生成列是虚拟生成列时索引生成列替换规则有效,暂不支持将表达式替换为存储生成列,但仍然可以通过直接使用该生成列本身来使用索引。 diff --git a/geo-distributed-deployment-topology.md b/geo-distributed-deployment-topology.md new file mode 100644 index 000000000000..9ec378ad0017 --- /dev/null +++ b/geo-distributed-deployment-topology.md @@ -0,0 +1,86 @@ +--- +title: 跨数据中心部署拓扑 +summary: 介绍跨数据中心部署 TiDB 集群的拓扑结构。 +category: how-to +--- + +# 跨数据中心部署拓扑 + +本文以典型的两地三中心为例,介绍跨数据中心部署的拓扑以及关键参数。 + +## 拓扑信息 + +|实例 | 个数 | 物理机配置 | BJ IP | SH IP |配置 | +| :-- | :-- | :-- | :-- | :-- | :-- | +| TiDB |3 | 16 VCore 32GB * 1 | 10.0.1.1
10.0.1.2
10.0.1.3
10.0.1.4 | 10.0.1.5 | 默认端口
全局目录配置 | +| PD | 3 | 4 VCore 8GB * 1 |10.0.1.6
10.0.1.7
10.0.1.8
10.0.1.9 | 10.0.1.10 | 默认端口
全局目录配置 | +| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) * 1 | 10.0.1.11
10.0.1.12
10.0.1.13
10.0.1.14 | 10.0.1.15 | 默认端口
全局目录配置 | +| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.16 || 默认端口
全局目录配置 | + +### 拓扑模版 + +[跨机房配置模板](https://github.com/pingcap/docs-cn/blob/release-4.0/config-templates/geo-redundancy-deployment.yaml) + +### 关键参数配置 + +本节介绍跨数据中心部署 TiDB 集群的关键参数配置。 + +#### TiKV 参数 + +- 设置 gRPC 的压缩格式,默认为 `none`。为提高跨机房部署场景的目标节点间 gRPC 包的传输速度,建议设置为 gzip 格式。 + + ```yaml + server.grpc-compression-type: gzip + ``` + +- label 配置 + + 由于采用跨机房部署 TiKV,为了避免物理机宕机导致 Region Group 默认的 5 副本中丢失 3 副本,使集群不可用的问题,可以通过 label 来实现 PD 智能调度,保证同中心、同机柜、同机器 TiKV 实例不会出现 Region Group 有 3 副本的情况。 + +- TiKV 配置 + + 相同物理机配置相同的 host 级别 label 信息: + + ```yaml + config: + server.labels: + zone: bj + dc: bja + rack: rack1 + host: host2 + ``` + +- 防止异地 TiKV 节点发起不必要的 Raft 选举,需要将异地 TiKV 节点发起选举时经过最少的 tick 个数和最多经过的 tick 个数都调大,这两个参数默认设置均为 `0`。 + + ```yaml + raftstore.raft-min-election-timeout-ticks: 1000 + raftstore.raft-max-election-timeout-ticks: 1020 + ``` + +#### PD 参数 + +- PD 元数据信息记录 TiKV 集群的拓扑信息,根据四个维度调度 Raft Group 副本。 + + ```yaml + replication.location-labels: ["zone","dc","rack","host"] + ``` + +- 调整 Raft Group 的副本数据量为 5 ,保证集群的高可用性。 + + ```yaml + replication.max-replicas: 5 + ``` + +- 拒绝异地机房 TiKV 的 Raft 副本选举为 Leader。 + + ```yaml + label-property: + reject-leader: + - key: "dc" + value: "sha" + ``` + +> **注意:** +> +> - 无需手动创建配置文件中的 `tidb` 用户,TiUP cluster 组件会在目标主机上自动创建该用户。可以自定义用户,也可以和中控机的用户保持一致。 +> - 如果部署目录配置为相对路径,会部署在用户家目录下。 diff --git a/geo-redundancy-deployment.md b/geo-redundancy-deployment.md new file mode 100644 index 000000000000..818d0c2a9895 --- /dev/null +++ b/geo-redundancy-deployment.md @@ -0,0 +1,71 @@ +--- +title: 跨数据中心部署方案 +category: how-to +aliases: ['/docs-cn/stable/how-to/deploy/geographic-redundancy/overview/'] +--- + +# 跨数据中心部署方案 + +作为 NewSQL 数据库,TiDB 兼顾了传统关系型数据库的优秀特性以及 NoSQL 数据库可扩展性,以及跨数据中心(下文简称“中心”)场景下的高可用。本文档旨在介绍跨数据中心部署的不同解决方案。 + +## 三中心部署方案 + +TiDB, TiKV, PD 分别分布在 3 个不同的中心,这是最常规,可用性最高的方案。 + +![三中心部署](/media/deploy-3dc.png) + +### 优点 + +所有数据的副本分布在三个数据中心,任何一个数据中心失效后,另外两个数据中心会自动发起 leader election,并在合理长的时间内(通常情况 20s 以内)恢复服务,并且不会产生数据丢失。 + +![三中心部署容灾](/media/deploy-3dc-dr.png) + +### 缺点 + +性能受网络延迟影响。 + +- 对于写入的场景,所有写入的数据需要同步复制到至少 2 个数据中心,由于 TiDB 写入过程使用两阶段提交,故写入延迟至少需要 2 倍数据中心间的延迟。 +- 对于读请求来说,如果数据 leader 与发起读取的 TiDB 节点不在同一个数据中心,也会受网络延迟影响。 +- TiDB 中的每个事务都需要向 PD leader 获取 TSO,当 TiDB 与 PD leader 不在同一个数据中心时,它上面运行的事务也会因此受网络延迟影响,每个有写入的事务会获取两次 TSO。 + +### 读性能优化 + +如果不需要每个数据中心同时对外提供服务,可以将业务流量全部派发到一个数据中心,并通过调度策略把 Region leader 和 PD leader 都迁移到同一个数据中心(我们在上文所述的测试中也做了这个优化)。这样一来,不管是从 PD 获取 TSO 还是读取 Region 都不受数据中心间网络的影响。当该数据中心失效后,PD leader 和 Region leader 会自动在其它数据中心选出,只需要把业务流量转移至其他存活的数据中心即可。 + +![三中心部署读性能优化](/media/deploy-3dc-optimize.png) + +## 两地三中心部署方案 + +两地三中心的方案与三数据中心类似,算是三机房方案根据业务特点进行的优化,区别是其中有两个数据中心距离很近(通常在同一个城市),网络延迟相对很小。这种场景下,我们可以把业务流量同时派发到同城的两个数据中心,同时控制 Region leader 和 PD leader 也分布在同城的两个数据中心。 + +![两地三中心部署方案](/media/deploy-2city3dc.png) + +与三数据中心方案相比,两地三中心有以下优势: + +- 写入速度更优 +- 两中心同时提供服务资源利用率更高 +- 依然能保证任何一个数据中心失效后保持可用并且不发生数据丢失 + +但是,缺陷是如果同城的两个数据中心同时失效(理论上讲要高于异地三数据中心损失 2 个的概率),将会导致不可用以及部分数据丢失。 + +## 两数据中心 + binlog 同步方案 + +两数据中心 + binlog 同步类似于传统的 MySQL 中 master/slave 方案。两个数据中心分别部署一套完整的 TiDB 集群,我们称之为主集群和从集群。正常情况下所有的请求都在主集群,写入的数据通过 binlog 异步同步至从集群并写入。 + +![binlog 同步部署方案](/media/deploy-binlog.png) + +当主集群整个数据中心失效后,业务可以切换至从集群,与 MySQL 类似,这种情况下会有一些数据缺失。对比 MySQL,这个方案的优势是数据中心内的 HA -- 少部分节点故障时,通过重新选举 leader 自动恢复服务,不需要人工干预。 + +![两中心 binlog 相互备份方案](/media/deploy-backup.png) + +另外部分用户采用这种方式做双数据中心多活,两个数据中心各有一个集群,将业务分为两个库,每个库服务一部分数据,每个数据中心的业务只会访问一个库,两个集群之间通过 binlog 将本数据中心业务所涉及的库中的数据变更同步到对端机房,形成环状备份。 + +> **注意:** +> +> 在两数据中心 + binlog 同步部署方案中,数据中心之间只有 binlog 异步复制。在数据中心间的延迟较高的情况下,从集群落后主集群的数据量会增大。当主集群故障后(DR),会造成数据丢失,丢失的数据量受网络延迟等因素影响。 + +## 高可用和容灾分析 + +对于三数据中心方案和两地三中心方案,我们能得到的保障是任意一个数据中心故障时,集群能自动恢复服务,不需要人工介入,并能保证数据一致性。注意各种调度策略都是用于帮助性能优化的,当发生故障时调度机制总是第一优先考虑可用性而不是性能。 + +对于两数据中心 + binlog 同步的方案,主集群内少量节点故障时也能自动恢复服务,不需要人工介入,并能保证数据一致性。当整个主集群故障时,需要人工切换至从集群,并可能发生一些数据丢失,数据丢失的数量取决于同步延迟,和网络条件有关。 diff --git a/get-started-with-tidb-lightning.md b/get-started-with-tidb-lightning.md new file mode 100644 index 000000000000..3c30a35c89dc --- /dev/null +++ b/get-started-with-tidb-lightning.md @@ -0,0 +1,121 @@ +--- +title: TiDB Lightning 教程 +category: how-to +aliases: ['/docs-cn/stable/how-to/get-started/tidb-lightning/'] +--- + +# TiDB Lightning 教程 + +TiDB Lightning 是一个将全量数据高速导入到 TiDB 集群的工具,目前支持 Mydumper 或 CSV 输出格式的数据源。你可以在以下两种场景下使用 Lightning: + +- **迅速**导入**大量新**数据。 +- 备份恢复所有数据。 + +TiDB Lightning 主要包含两个部分: + +- **`tidb-lightning`**(“前端”):主要完成适配工作,通过读取数据源,在下游 TiDB 集群建表、将数据转换成键/值对 (KV 对) 发送到 `tikv-importer`、检查数据完整性等。 +- **`tikv-importer`**(“后端”):主要完成将数据导入 TiKV 集群的工作,把 `tidb-lightning` 写入的 KV 对缓存、排序、切分并导入到 TiKV 集群。 + +![TiDB Lightning 整体架构](/media/tidb-lightning-architecture.png) + +本教程假设使用的是若干新的、纯净版 CentOS 7 实例,你可以(使用 VMware、VirtualBox 及其他工具)在本地虚拟化或在供应商提供的平台上部署一台小型的云虚拟主机。因为 TiDB Lightning 对计算机资源消耗较高,建议分配 4 GB 以上的内存。 + +> **警告:** +> +> 本教程中的部署方法只适用于测试及功能体验,并不适用于生产或开发环境。 + +## 准备全量备份数据 + +我们使用 [`mydumper`](/mydumper-overview.md) 从 MySQL 导出数据,如下: + +{{< copyable "shell-regular" >}} + +```sh +./bin/mydumper -h 127.0.0.1 -P 3306 -u root -t 16 -F 256 -B test -T t1,t2 --skip-tz-utc -o /data/my_database/ +``` + +其中: + +- `-B test`:从 `test` 数据库导出。 +- `-T t1,t2`:只导出 `t1` 和 `t2` 这两个表。 +- `-t 16`:使用 16 个线程导出数据。 +- `-F 256`:将每张表切分成多个文件,每个文件大小约为 256 MB。 +- `--skip-tz-utc`:添加这个参数则会忽略掉 TiDB 与导数据的机器之间时区设置不一致的情况,禁止自动转换。 + +这样全量备份数据就导出到了 `/data/my_database` 目录中。 + +## 部署 TiDB Lightning + +### 第 1 步:部署 TiDB 集群 + +在开始数据导入之前,需先部署一套要进行导入的 TiDB 集群(版本要求 2.0.9 以上),本教程使用 TiDB 3.0.4 版本。部署方法可参考 [TiDB 快速入门指南](/overview.md#部署方式)。 + +### 第 2 步:下载 TiDB Lightning 安装包 + +通过以下链接获取 TiDB Lightning 安装包(选择与 TiDB 集群相同的版本): + +- **v3.0.4**: [tidb-toolkit-v3.0.4-linux-amd64.tar.gz](https://download.pingcap.org/tidb-toolkit-v3.0.0-linux-amd64.tar.gz) + +### 第 3 步:启动 `tikv-importer` + +1. 将安装包里的 `bin/tikv-importer` 上传至部署 TiDB Lightning 的服务器。 + +2. 配置 `tikv-importer.toml`。 + + ```toml + # TiKV Importer 配置文件模版 + + # 日志文件。 + log-file = "tikv-importer.log" + # 日志等级:trace、debug、info、warn、error、off。 + log-level = "info" + + [server] + # tikv-importer 监听的地址,tidb-lightning 需要连到这个地址进行数据写入。 + addr = "192.168.20.10:8287" + + [import] + # 存储引擎文档 (engine file) 的文件夹路径。 + import-dir = "/mnt/ssd/data.import/" + ``` + +3. 运行 `tikv-importer`。 + + {{< copyable "shell-regular" >}} + + ```sh + nohup ./tikv-importer -C tikv-importer.toml > nohup.out & + ``` + +### 第 4 步:启动 `tidb-lightning` + +1. 将安装包里的 `bin/tidb-lightning` 及 `bin/tidb-lightning-ctl` 上传至部署 TiDB Lightning 的服务器。 + +2. 将数据源也上传到同样的服务器。 + +3. 配置合适的参数运行 `tidb-lightning`。如果直接在命令行中用 `nohup` 启动程序,可能会因为 SIGHUP 信号而退出,建议把 `nohup` 放到脚本里面,如: + + {{< copyable "shell-regular" >}} + + ```sh + #!/bin/bash + nohup ./tidb-lightning \ + --importer 172.16.31.10:8287 \ + -d /data/my_database/ \ + --tidb-host 172.16.31.2 \ + --tidb-user root \ + --log-file tidb-lightning.log \ + > nohup.out & + ``` + +### 第 5 步:检查数据 + +导入完毕后,TiDB Lightning 会自动退出。若导入成功,日志的最后一行会显示 `tidb lightning exit`。 + +如果出错,请参见 [TiDB Lightning 错误排解](/troubleshoot-tidb-lightning.md)。 + +## 总结 + +本教程对 TiDB Lightning 进行了简单的介绍,并快速部署了一套简单的 TiDB Lightning 集群,将全量备份数据导入到 TiDB 集群中。 + +关于 TiDB Lightning 的详细功能和使用,参见 [TiDB Lightning 简介](/tidb-lightning/tidb-lightning-overview.md)。 diff --git a/get-started-with-tispark.md b/get-started-with-tispark.md new file mode 100644 index 000000000000..3f9448374b1b --- /dev/null +++ b/get-started-with-tispark.md @@ -0,0 +1,221 @@ +--- +title: TiSpark 快速上手 +category: how-to +aliases: ['/docs-cn/stable/how-to/get-started/tispark/'] +--- + +# TiSpark 快速上手 + +为了让大家快速体验 [TiSpark](/tispark-overview.md),通过 TiDB Ansible 安装的 TiDB 集群中默认已集成 Spark、TiSpark jar 包及 TiSpark sample data。 + +## 部署信息 + +- Spark 默认部署在 TiDB 实例部署目录下 spark 目录中 +- TiSpark jar 包默认部署在 Spark 部署目录 jars 文件夹下:`spark/jars/tispark-${name_with_version}.jar` +- TiSpark 示例数据和导入脚本可点击 [TiSpark 示例数据](http://download.pingcap.org/tispark-sample-data.tar.gz)下载。 + + {{< copyable "" >}} + + ``` + tispark-sample-data/ + ``` + +## 环境准备 + +### 在 TiDB 实例上安装 JDK + +在 [Oracle JDK 官方下载页面](http://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html) 下载 JDK 1.8 当前最新版,本示例中下载的版本为 `jdk-8u141-linux-x64.tar.gz`。 + +解压并根据您的 JDK 部署目录设置环境变量,编辑 `~/.bashrc` 文件,比如: + +{{< copyable "shell-regular" >}} + +```bash +export JAVA_HOME=/home/pingcap/jdk1.8.0_144 && +export PATH=$JAVA_HOME/bin:$PATH +``` + +验证 JDK 有效性: + +```bash +java -version +``` + +``` +java version "1.8.0_144" +Java(TM) SE Runtime Environment (build 1.8.0_144-b01) +Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode) +``` + +### 导入样例数据 + +假设 TiDB 集群已启动,其中一台 TiDB 实例服务 IP 为 192.168.0.2,端口为 4000,用户名为 root, 密码为空。 + +{{< copyable "shell-regular" >}} + +```bash +wget http://download.pingcap.org/tispark-sample-data.tar.gz && \ +tar -zxvf tispark-sample-data.tar.gz && \ +cd tispark-sample-data +``` + +修改 `sample_data.sh` 中 TiDB 登录信息,比如: + +{{< copyable "shell-regular" >}} + +```bash +mysql --local-infile=1 -h 192.168.0.2 -P 4000 -u root < dss.ddl +``` + +执行脚本 + +{{< copyable "shell-regular" >}} + +```bash +./sample_data.sh +``` + +> **注意:** +> +> 执行脚本的机器上需要安装 MySQL client,CentOS 用户可通过 `yum -y install mysql`来安装。 + +登录 TiDB 并验证数据包含 `TPCH_001` 库及以下表: + +{{< copyable "shell-regular" >}} + +```bash +mysql -uroot -P4000 -h192.168.0.2 +``` + +{{< copyable "sql" >}} + +```sql +show databases; +``` + +``` ++--------------------+ +| Database | ++--------------------+ +| INFORMATION_SCHEMA | +| PERFORMANCE_SCHEMA | +| TPCH_001 | +| mysql | +| test | ++--------------------+ +5 rows in set (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +use TPCH_001; +``` + +``` +Reading table information for completion of table and column names +You can turn off this feature to get a quicker startup with -A + +Database changed +``` + +{{< copyable "sql" >}} + +```sql +show tables; +``` + +``` ++--------------------+ +| Tables_in_TPCH_001 | ++--------------------+ +| CUSTOMER | +| LINEITEM | +| NATION | +| ORDERS | +| PART | +| PARTSUPP | +| REGION | +| SUPPLIER | ++--------------------+ +8 rows in set (0.00 sec) +``` + +## 使用范例 + +进入 spark 部署目录启动 spark-shell: + +{{< copyable "shell-regular" >}} + +```bash +cd spark && +bin/spark-shell +``` + +然后像使用原生 Spark 一样查询 TiDB 表: + +```shell +scala> spark.sql("select count(*) from lineitem").show +``` + +结果为 + +``` ++--------+ +|count(1)| ++--------+ +| 60175| ++--------+ +``` + +下面执行另一个复杂一点的 Spark SQL: + +```shell +scala> spark.sql( + """select + | l_returnflag, + | l_linestatus, + | sum(l_quantity) as sum_qty, + | sum(l_extendedprice) as sum_base_price, + | sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + | sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + | avg(l_quantity) as avg_qty, + | avg(l_extendedprice) as avg_price, + | avg(l_discount) as avg_disc, + | count(*) as count_order + |from + | lineitem + |where + | l_shipdate <= date '1998-12-01' - interval '90' day + |group by + | l_returnflag, + | l_linestatus + |order by + | l_returnflag, + | l_linestatus + """.stripMargin).show +``` + +结果为: + +``` ++------------+------------+---------+--------------+--------------+ +|l_returnflag|l_linestatus| sum_qty|sum_base_price|sum_disc_price| ++------------+------------+---------+--------------+--------------+ +| A| F|380456.00| 532348211.65|505822441.4861| +| N| F| 8971.00| 12384801.37| 11798257.2080| +| N| O|742802.00| 1041502841.45|989737518.6346| +| R| F|381449.00| 534594445.35|507996454.4067| ++------------+------------+---------+--------------+--------------+ +(续) +-----------------+---------+------------+--------+-----------+ + sum_charge| avg_qty| avg_price|avg_disc|count_order| +-----------------+---------+------------+--------+-----------+ + 526165934.000839|25.575155|35785.709307|0.050081| 14876| + 12282485.056933|25.778736|35588.509684|0.047759| 348| +1029418531.523350|25.454988|35691.129209|0.049931| 29181| + 528524219.358903|25.597168|35874.006533|0.049828| 14902| +-----------------+---------+------------+--------+-----------+ +``` + +更多样例请参考 [`pingcap/tispark-test`](https://github.com/pingcap/tispark-test/tree/master/tpch/sparksql) diff --git a/glossary.md b/glossary.md index 3b31e69e5d20..d3d61c492c85 100644 --- a/glossary.md +++ b/glossary.md @@ -62,6 +62,10 @@ TiKV 集群中的 Region 不是一开始就划分好的,而是随着数据写 其机制是集群初始化时构建一个初始 Region 覆盖整个 key space,随后在运行过程中每当 Region 数据达到一定量之后就通过 Split 产生新的 Region。 +### Restore + +备份操作的逆过程,即利用保存的备份数据还原出原始数据的过程。 + ## S ### Scheduler diff --git a/grafana-overview-dashboard.md b/grafana-overview-dashboard.md new file mode 100644 index 000000000000..e87da15dca25 --- /dev/null +++ b/grafana-overview-dashboard.md @@ -0,0 +1,87 @@ +--- +title: Overview 面板重要监控指标详解 +category: reference +aliases: ['/docs-cn/stable/reference/key-monitoring-metrics/overview-dashboard/'] +--- + +# Overview 面板重要监控指标详解 + +使用 TiDB Ansible 或 TiUP 部署 TiDB 集群时,一键部署监控系统 (Prometheus & Grafana),监控架构参见 [TiDB 监控框架概述](/tidb-monitoring-framework.md)。 + +目前 Grafana Dashboard 整体分为 PD、TiDB、TiKV、Node\_exporter、Overview 等。 + +对于日常运维,我们单独挑选出重要的 Metrics 放在 Overview 页面,方便日常运维人员观察集群组件 (PD, TiDB, TiKV) 使用状态以及集群使用状态。 + +以下为 Overview Dashboard 监控说明: + +## Services Port Status + +- Services Up:各服务在线节点数量 + +## PD + +- PD role:当前 PD 的角色 +- Storage capacity:TiDB 集群总可用数据库空间大小 +- Current storage size:TiDB 集群目前已用数据库空间大小,TiKV 多副本的空间占用也会包含在内 +- Normal stores:处于正常状态的节点数目 +- Abnormal stores:处于异常状态的节点数目,正常情况应当为 0 +- Number of Regions:当前集群的 Region 总量,请注意 Region 数量与副本数无关 +- 99% completed\_cmds\_duration\_seconds:单位时间内,99% 的 pd-server 请求执行时间小于监控曲线的值,一般 <= 5ms +- Handle\_requests\_duration\_seconds:PD 发送请求的网络耗时 +- Region health:每个 Region 的状态,通常情况下,pending 的 peer 应该少于 100,miss 的 peer 不能一直大于 0 +- Hot write Region's leader distribution:每个 TiKV 实例上是写入热点的 leader 的数量 +- Hot read Region's leader distribution:每个 TiKV 实例上是读取热点的 leader 的数量 +- Region heartbeat report:TiKV 向 PD 发送的心跳个数 +- 99% Region heartbeat latency:99% 的情况下,心跳的延迟 + +## TiDB + +- Statement OPS:不同类型 SQL 语句每秒执行的数量。按 `SELECT`、`INSERT`、`UPDATE` 等来统计 +- Duration:执行的时间 + - 客户端网络请求发送到 TiDB,到 TiDB 执行结束后返回给客户端的时间。一般情况下,客户端请求都是以 SQL 语句的形式发送,但也可以包含 `COM_PING`、`COM_SLEEP`、`COM_STMT_FETCH`、`COM_SEND_LONG_DATA` 之类的命令执行的时间 + - 由于 TiDB 支持 Multi-Query,因此,可以接受客户端一次性发送的多条 SQL 语句,如:`select 1; select 1; select 1;`。此时,统计的执行时间是所有 SQL 执行完之后的总时间 +- QPS By Instance:每个 TiDB 上的 QPS。按照命令和执行结果成功或失败来统计 +- Failed Query OPM:每个 TiDB 实例上,每秒钟执行 SQL 语句发生错误按照错误类型的统计(例如语法错误、主键冲突等)。包含了错误所属的模块和错误码 +- Connection count:每个 TiDB 的连接数 +- Memory Usage:每个 TiDB 实例的内存使用统计,分为进程占用内存和 Golang 在堆上申请的内存 +- Transaction OPS:每秒事务执行数量统计 +- Transaction Duration:事务执行的时间 +- KV Cmd OPS:KV 命令执行数量统计 +- KV Cmd Duration 99:KV 命令执行的时间 +- PD TSO OPS:TiDB 每秒从 PD 获取 TSO 的数量 +- PD TSO Wait Duration:TiDB 等待从 PD 获取 TS 的时间 +- TiClient Region Error OPS:TiKV 返回 Region 相关错误信息的数量 +- Lock Resolve OPS:TiDB 清理锁操作的数量。当 TiDB 的读写请求遇到锁时,会尝试进行锁清理 +- Load Schema Duration:TiDB 从 TiKV 获取 Schema 的时间 +- KV Backoff OPS:TiKV 返回错误信息的数量 + +## TiKV + +- leader:各个 TiKV 节点上 Leader 的数量分布 +- region:各个 TiKV 节点上 Region 的数量分布 +- CPU:各个 TiKV 节点的 CPU 使用率 +- Memory:各个 TiKV 节点的内存使用量 +- store size:每个 TiKV 实例的使用的存储空间的大小 +- cf size:每个列族的大小 +- channel full:每个 TiKV 实例上 channel full 错误的数量,正常情况下应当为 0 +- server report failures:每个 TiKV 实例上报错的消息个数,正常情况下应当为 0 +- scheduler pending commands:每个 TiKV 实例上 pending 命令的个数 +- coprocessor executor count:TiKV 每秒收到的 coprocessor 操作数量,按照 coprocessor 类型统计 +- coprocessor request duration:处理 coprocessor 读请求所花费的时间 +- raft store CPU:raftstore 线程的 CPU 使用率,线程数量默认为 2 (通过 `raftstore.store-pool-size` 配置)。如果单个线程使用率超过 80%,说明使用率很高 +- Coprocessor CPU:coprocessor 线程的 CPU 使用率 + +## System Info + +- Vcores:CPU 核心数量 +- Memory:内存总大小 +- CPU Usage:CPU 使用率,最大为 100% +- Load [1m]:1 分钟的负载情况 +- Memory Available:剩余内存大小 +- Network Traffic:网卡流量统计 +- TCP Retrans:TCP 重传数量统计 +- IO Util:磁盘使用率,最高为 100%,一般到 80% - 90% 就需要考虑加节点 + +## 图例 + +![overview](/media/grafana_monitor_overview.png) diff --git a/grafana-pd-dashboard.md b/grafana-pd-dashboard.md new file mode 100644 index 000000000000..873974d694cc --- /dev/null +++ b/grafana-pd-dashboard.md @@ -0,0 +1,155 @@ +--- +title: PD 重要监控指标详解 +category: reference +aliases: ['/docs-cn/stable/reference/key-monitoring-metrics/pd-dashboard/'] +--- + +# PD 重要监控指标详解 + +使用 TiDB Ansible 部署 TiDB 集群时,一键部署监控系统 (Prometheus/Grafana),监控架构请看 [TiDB 监控框架概述](/tidb-monitoring-framework.md)。 + +目前 Grafana Dashboard 整体分为 PD、TiDB、TiKV、Node\_exporter、Overview 等。 + +对于日常运维,我们通过观察 PD 面板上的 Metrics,可以了解 PD 当前的状态。 + +以下为 PD Dashboard 监控说明: + +- PD role:当前 PD 的角色 +- Storage capacity:TiDB 集群总可用数据库空间大小 +- Current storage size:TiDB 集群目前已用数据库空间大小 +- Current storage usage:TiDB 集群存储空间的使用率 +- Normal stores:处于正常状态的节点数目 +- Number of Regions:当前集群的 Region 总量 +- Abnormal stores:处于异常状态的节点数目,正常情况应当为 0 +- Region health:集群所有 Region 的状态。通常情况下,pending 或 down 的 peer 应该少于 100,miss 的 peer 不能一直大于 0,empty Region 过多需及时打开 Region Merge +- Current peer count:当前集群 peer 的总量 +![PD Dashboard - Header](/media/pd-dashboard-header-v4.png) + +## Cluster + +- PD scheduler config:PD 调度配置列表 +- Cluster ID:集群的 cluster id,唯一标识 +- Current TSO:当前分配 TSO 的物理时间戳部分 +- Current ID allocation:当前可分配 ID 的最大值 +- Region label isolation level:不同 label 所在的 level 的 Region 数量 +- Label distribution:集群中 TiKV 节点的 label 分布情况 +![PD Dashboard - Cluster metrics](/media/pd-dashboard-cluster-v4.png) + +## Operator + +- Schedule operator create:新创建的不同 operator 的数量,单位 opm 代表一分钟内创建的个数 +- Schedule operator check:已检查的 operator 的次数,主要检查是否当前步骤已经执行完成,如果是,则执行下一个步骤 +- Schedule operator finish:已完成调度的 operator 的数量 +- Schedule operator timeout:已超时的 operator 的数量 +- Schedule operator replaced or canceled:已取消或者被替换的 operator 的数量 +- Schedule operators count by state:不同状态的 operator 的数量 +- Operator finish duration:已完成的 operator 所花费的最长时间 +- Operator step duration:已完成的 operator 的步骤所花费的最长时间 + +![PD Dashboard - Operator metrics](/media/pd-dashboard-operator-v4.png) + +## Statistics - Balance + +- Store capacity:每个 TiKV 实例的总的空间大小 +- Store available:每个 TiKV 实例的可用空间大小 +- Store used:每个 TiKV 实例的已使用空间大小 +- Size amplification:每个 TiKV 实例的空间放大比率 +- Size available ratio:每个 TiKV 实例的可用空间比率 +- Store leader score:每个 TiKV 实例的 leader 分数 +- Store Region score:每个 TiKV 实例的 Region 分数 +- Store leader size:每个 TiKV 实例上所有 leader 的大小 +- Store Region size:每个 TiKV 实例上所有 Region 的大小 +- Store leader count:每个 TiKV 实例上所有 leader 的数量 +- Store Region count:每个 TiKV 实例上所有 Region 的数量 + +![PD Dashboard - Balance metrics](/media/pd-dashboard-balance-v4.png) + +## Statistics - hot write + +- Hot Region's leader distribution:每个 TiKV 实例上成为写入热点的 leader 的数量 +- Total written bytes on hot leader Regions:每个 TiKV 实例上所有成为写入热点的 leader 的总的写入流量大小 +- Hot write Region's peer distribution:每个 TiKV 实例上成为写入热点的 peer 的数量 +- Total written bytes on hot peer Regions:每个 TiKV 实例上所有成为写入热点的 peer 的写入流量大小 +- Store Write rate bytes:每个 TiKV 实例总的写入的流量 +- Store Write rate keys:每个 TiKV 实例总的写入 keys +- Hot cache write entry number:每个 TiKV 实例进入热点统计模块的 peer 的数量 +- Selector events: 热点调度中选择器的事件发生次数 +- Direction of hotspot move leader:热点调度中 leader 的调度方向,正数代表调入,负数代表调出 +- Direction of hotspot move peer:热点调度中 peer 的调度方向,正数代表调入,负数代表调出 + +![PD Dashboard - Hot write metrics](/media/pd-dashboard-hotwrite-v4.png) + +## Statistics - hot read + +- Hot Region's leader distribution:每个 TiKV 实例上成为读取热点的 leader 的数量 +- Total read bytes on hot leader Regions:每个 TiKV 实例上所有成为读取热点的 leader 的总的读取流量大小 +- Store read rate bytes:每个 TiKV 实例总的读取的流量 +- Store read rate keys:每个 TiKV 实例总的读取 keys +- Hot cache read entry number:每个 TiKV 实例进入热点统计模块的 peer 的数量 + +![PD Dashboard - Hot read metrics](/media/pd-dashboard-hotread-v4.png) + +## Scheduler + +- Scheduler is running:所有正在运行的 scheduler +- Balance leader movement:leader 移动的详细情况 +- Balance Region movement:Region 移动的详细情况 +- Balance leader event:balance leader 的事件数量 +- Balance Region event:balance Region 的事件数量 +- Balance leader scheduler:balance-leader scheduler 的状态 +- Balance Region scheduler:balance-region scheduler 的状态 +- Replica checker:replica checker 的状态 +- Rule checker:rule checker 的状态 +- Region merge checker:merge checker 的状态 +- Filter target:尝试选择 Store 作为调度 taget 时没有通过 Filter 的计数 +- Filter source:尝试选择 Store 作为调度 source 时没有通过 Filter 的计数 +- Balance Direction:Store 被选作调度 target 或 source 的次数 +- Store Limit:Store 的调度限流状态 + +![PD Dashboard - Scheduler metrics](/media/pd-dashboard-scheduler-v4.png) + +## gRPC + +- Completed commands rate:gRPC 命令的完成速率 +- 99% Completed commands duration:99% 命令的最长消耗时间 + +![PD Dashboard - gRPC metrics](/media/pd-dashboard-grpc-v2.png) + +## etcd + +- Handle transactions count:etcd 的事务个数 +- 99% Handle transactions duration:99% 的情况下,处理 etcd 事务所需花费的时间 +- 99% WAL fsync duration:99% 的情况下,持久化 WAL 所需花费的时间,这个值通常应该小于 1s +- 99% Peer round trip time seconds:99% 的情况下,etcd 的网络延时,这个值通常应该小于 1s +- etcd disk WAL fsync rate:etcd 持久化 WAL 的速率 +- Raft term:当前 Raft 的 term +- Raft committed index:最后一次 commit 的 Raft index +- Raft applied index:最后一次 apply 的 Raft index + +![PD Dashboard - etcd metrics](/media/pd-dashboard-etcd-v2.png) + +## TiDB + +- PD Server TSO handle time and Client recv time:从 PD 开始处理 TSO 请求到 client 端接收到 TSO 的总耗时 +- Handle requests count:TiDB 的请求数量 +- Handle requests duration:每个请求所花费的时间,99% 的情况下,应该小于 100ms + +![PD Dashboard - TiDB metrics](/media/pd-dashboard-tidb-v4.png) + +## Heartbeat + +- Heartbeat region event QPS:心跳处理 region 的 QPS, 包括更新缓存和持久化 +- Region heartbeat report:TiKV 向 PD 发送的心跳个数 +- Region heartbeat report error:TiKV 向 PD 发送的异常的心跳个数 +- Region heartbeat report active:TiKV 向 PD 发送的正常的心跳个数 +- Region schedule push:PD 向 TiKV 发送的调度命令的个数 +- 99% Region heartbeat latency:99% 的情况下,心跳的延迟 + +![PD Dashboard - Heartbeat metrics](/media/pd-dashboard-heartbeat-v4.png) + +## Region storage + +- Syncer Index:Leader 记录 Region 变更历史的最大 index +- history last index:Follower 成功同步的 Region 变更历史的 index + +![PD Dashboard - Region storage](/media/pd-dashboard-region-storage.png) diff --git a/grafana-tidb-dashboard.md b/grafana-tidb-dashboard.md new file mode 100644 index 000000000000..7dc5f49d0b35 --- /dev/null +++ b/grafana-tidb-dashboard.md @@ -0,0 +1,166 @@ +--- +title: TiDB 重要监控指标详解 +category: reference +aliases: ['/docs-cn/stable/reference/key-monitoring-metrics/tidb-dashboard/'] +--- + +# TiDB 重要监控指标详解 + +使用 TiDB Ansible 或 TiUP 部署 TiDB 集群时,一键部署监控系统 (Prometheus & Grafana),监控架构参见 [TiDB 监控框架概述](/tidb-monitoring-framework.md)。 + +目前 Grafana Dashboard 整体分为 PD、TiDB、TiKV、Node\_exporter、Overview 等。TiDB 分为 TiDB 和 TiDB Summary 面板,两个面板的区别如下: + +- TiDB 面板:提供尽可能全面的信息,供排查集群异常。 +- TiDB Summary 面板:将 TiDB 面板中用户最为关心的部分抽取出来,并做了些许修改。主要用于提供数据库日常运行中用户关心的数据,如 QPS、TPS、响应延迟等,以便作为外部展示、汇报用的监控信息。 + +以下为 **TiDB Dashboard** 部分监控说明: + +## 说明 + +- Query Summary + - Duration:执行时间 + - 客户端网络请求发送到 TiDB,到 TiDB 执行结束后返回给客户端的时间。一般情况下,客户端请求都是以 SQL 语句的形式发送,但也可以包含 `COM_PING`、`COM_SLEEP`、`COM_STMT_FETCH`、`COM_SEND_LONG_DATA` 之类的命令执行时间 + - 由于 TiDB 支持 Multi-Query,因此,可以接受客户端一次性发送多条 SQL 语句,如 `select 1; select 1; select 1;`。此时,统计的执行时间是所有 SQL 语句执行完之后的总时间 + - QPS:所有 TiDB 实例上的每秒执行的 SQL 语句数量。按照执行成功或失败(OK/Error)进行了区分 + - Statement OPS:不同类型的 SQL 语句每秒执行的数量。按 `SELECT`、`INSERT`、`UPDATE` 等来统计 + - QPS By Instance:每个 TiDB 实例上的 QPS。按照命令和执行结果成功或失败来统计 + - Failed Query OPM:每个 TiDB 实例上,对每秒钟执行 SQL 语句发生的错误按照错误类型的统计(例如语法错误、主键冲突等)。包含了错误所属的模块和错误码 + - Slow query:慢查询处理时间统计(整个慢查询耗时、Coprocessor 耗时、Coprocessor 调度等待时间) + - 999/99/95/80 Duration:不同类型的 SQL 语句执行耗时统计(不同百分位) + +- Query Detail + - Duration 80/95/99/999 By Instance:每个 TiDB 实例执行 SQL 语句的耗时统计(不同百分位)。 + - Failed Query OPM Detail:每个 TiDB 实例执行 SQL 语句发生的错误按照错误类型统计(例如语法错误、主键冲突等)。 + - Internal SQL OPS:整个 TiDB 集群内部 SQL 语句执行的 QPS。内部 SQL 语句是 TiDB 内部自动执行的 SQL 语句,一般由用户 SQL 语句来触发或者内部定时任务触发。 + +- Server + - Uptime:每个 TiDB 实例的运行时间 + - Memory Usage:每个 TiDB 实例的内存使用统计,分为进程占用内存和 Golang 在堆上申请的内存 + - CPU Usage:每个 TiDB 实例的 CPU 使用统计 + - Connection Count:每个 TiDB 的连接数 + - Open FD Count:每个 TiDB 实例的打开的文件描述符统计 + - Goroutine Count:每个 TiDB 实例的 Goroutine 数量 + - Go GC Duration:每个 TiDB 实例的 Golang GC 耗时 + - Go Threads:每个 TiDB 实例的线程数量 + - Go GC Count:每个 TiDB 实例的 Golang GC 执行次数 + - Go GC CPU Usage:每个 TiDB 实例的 Golang GC 使用的 CPU + - Events OPM:每个 TiDB 实例关键事件统计,例如 start,close,graceful-shutdown,kill,hang 等 + - Keep Alive OPM:每个 TiDB 实例每分钟刷新监控的次数,通常不需要关注 + - Prepare Statement Count:每个 TiDB 实例现存的 `Prepare` 语句数以及总数 + - Time Jump Back OPS:每个 TiDB 实例上每秒操作系统时间回跳的次数 + - Write Binlog Error:每个 TiDB 每秒写入 Binlog 失败的次数 + - Get Token Duration:每个连接获取 Token 的耗时 + - Handshake Error OPS:每个 TiDB 实例每秒握手错误的次数 + +- Transaction + - Transaction OPS:每秒事务的执行数量 + - Duration:事务执行的时间 + - Transaction Statement Num:事务中的 SQL 语句数量 + - Transaction Retry Num:事务重试次数 + - Session Retry Error OPS:每秒事务重试时遇到的错误数量 + - KV Transaction OPS:每个 TiDB 内部每秒执行的事务数量 + - 一个用户的事务,在 TiDB 内部可能会触发多次事务执行,其中包含,内部元数据的读取,用户事务原子性地多次重试执行等 + - TiDB 内部的定时任务也会通过事务来操作数据库,这部分也包含在这个面板里 + - KV Transaction Duration:每个 TiDB 内部执行事务的耗时 + - Commit Token Wait Duration:事务提交时的流控队列等待耗时。当出现较长等待时,代表提交事务过大,正在限流。如果系统还有资源可以使用,可以通过增大 TiDB 配置文件中 `committer-concurrency` 来加速提交 + - Transaction Max Write KV Num:单个事务写入的最大键值对数量 + - Transaction Max Write Size Bytes:单个事务写入的最大键值对大小 + - Transaction Regions Num 90:单个事务写入的 Region 数量的 90% 分位 + - Send HeartBeat Duration:事务发送心跳的时间间隔 + - TTL Lifetime Reach Counter:事务的 TTL 达到了上限的数量。TTL 上限默认值 10 分钟,它的含义是从悲观事务第一次加锁,或者乐观事务的第一个 prewrite 开始,超过了 10 分钟。可以通过修改 TiDB 配置文件中 `max-txn-ttl` 来改变 TTL 寿命上限 + - Statement Lock Keys:单个语句的加锁个数 + - Acquire Pessimistic Locks Duration:加锁所消耗的时间 + - Pessimistic Statement Retry OPS:悲观语句重试次数统计。当语句尝试加锁时,可能遇到写入冲突,此时,语句会重新获取新的 snapshot 并再次加锁 + - Load Safepoint OPS:加载 Safepoint 的次数统计。Safepoint 作用是在事务读数据时,保证不读到 Safepoint 之前的数据,保证数据安全。因为,Safepoint 之前的数据有可能被 GC 清理掉 + +- Executor + - Parse Duration:SQL 语句解析耗时统计 + - Compile Duration:将解析后的 SQL AST 编译成执行计划耗时统计 + - Execution Duration:执行 SQL 语句执行计划耗时统计 + - Expensive Executor OPS:每秒消耗系统资源比较多的算子统计,包括 Merge Join,Hash Join,Index Look Up Join,Hash Agg,Stream Agg,Sort,TopN 等 + - Queries Using Plan Cache OPS:每秒使用 Plan Cache 的查询数量统计 + +- Distsql + - Distsql Duration:Distsql 处理的时长 + - Distsql QPS:Distsql 的数量统计 + - Distsql Partial QPS:每秒 Partial Results 的数量 + - Scan Keys Num:每个 Query 扫描的 Key 的数量 + - Scan Keys Partial Num:每一个 Partial Result 扫描的 Key 的数量 + - Partial Num:每个 SQL 语句 Partial Results 的数量 + +- KV Errors + - KV Backoff Duration:KV 每个请求重试的总时间。TiDB 向 TiKV 发送请求时可能遇到错误,TiDB 对每个向 TiKV 的请求都有重试机制,这里记录的是一个请求重试的总时间 + - TiClient Region Error OPS:TiKV 返回 Region 相关错误信息的数量 + - KV Backoff OPS:TiKV 返回错误信息的数量 + - Lock Resolve OPS:TiDB 清理锁操作的数量。当 TiDB 的读写请求遇到锁时,会尝试进行锁清理 + - Other Errors OPS:其他类型的错误数量,包括清锁和更新 SafePoint + +- KV Request + - KV Request OPS:KV Request 执行次数,根据 TiKV 显示 + - KV Request Duration 99 by store:KV Request 执行时间,根据 TiKV 显示 + - KV Request Duration 99 by type:KV Request 执行时间,根据类型显示 + +- PD Client + - PD Client CMD OPS:PD Client 每秒执行命令数量统计 + - PD Client CMD Duration:PD Client 执行命令耗时 + - PD Client CMD Fail OPS:PD Client 每秒执行命令失败统计 + - PD TSO OPS:TiDB 每秒从 PD 获取 TSO 的数量 + - PD TSO Wait Duration:TiDB 等待从 PD 返回 TSO 的时间 + - PD TSO RPC Duration:TiDB 从向 PD 发送获取 TSO 的请求到接收到 TSO 花费的时间 + - Start TSO Wait Duration:TiDB 从向 PD 发送获取 start tso 请求开始到开始等待 tso 返回的时间 + +- Schema Load + - Load Schema Duration:TiDB 从 TiKV 获取 Schema 的时间 + - Load Schema OPS:TiDB 从 TiKV 每秒获取 Schema 的数量统计 + - Schema Lease Error OPM:Schema Lease 出错,包括 change 和 outdate 两种,change 代表 schema 发生了变化,outdate 代表无法更新 schema,属于较严重错误,出现 outdate 错误时会报警 + - Load Privilege OPS:TiDB 从 TiKV 每秒获取权限信息的数量统计 + +- DDL + - DDL Duration 95:DDL 语句处理时间的 95% 分位 + - Batch Add Index Duration 100:创建索引时每个 Batch 所花费的最大时间统计 + - DDL Waiting Jobs Count:等待的 DDL 任务数量 + - DDL META OPM:DDL 每分钟获取 META 的次数 + - DDL Worker Duration 99:每个 DDL worker 执行时间 99% 分位 + - Deploy Syncer Duration:Schema Version Syncer 初始化,重启,清空等操作耗时 + - Owner Handle Syncer Duration:DDL Owner 在执行更新,获取以及检查 Schema Version 的耗时 + - Update Self Version Duration:Schema Version Syncer 更新版本信息耗时 + - DDL OPM:DDL 语句的每秒执行次数 + - DDL add index progress in percentage:添加索引的进度展示 + +- Statistics + - Auto Analyze Duration 95:自动 ANALYZE 耗时统计 + - Auto Analyze QPS:自动 ANALYZE 数量统计 + - Stats Inaccuracy Rate:统计信息不准确度统计 + - Pseudo Estimation OPS:使用假的统计信息优化 SQL 的数量统计 + - Dump Feedback OPS:存储统计信息 Feedback 的数量统计 + - Store Query Feedback QPS:存储合并查询的 Feedback 信息的每秒操作数量,该操作在 TiDB 内存中进行 + - Significant Feedback:重要的 Feedback 更新统计信息的数量统计 + - Update Stats OPS:利用 Feedback 更新统计信息的数量统计 + - Fast Analyze Status 100:快速收集统计信息的状态统计 + +- Owner + - New ETCD Session Duration 95:创建一个新的 etcd 会话花费的时间。TiDB 通过 etcd client 连接 PD 中的 etcd 保存/读取部分元数据信息。这里记录了创建会话花费的时间 + - Owner Watcher OPS:DDL owner watch PD 的 etcd 的元数据的 goroutine 的每秒操作次数 + +- Meta + - AutoID QPS:AutoID 相关操作的数量统计,包括全局 ID 分配、单个 Table AutoID 分配、单个 Table AutoID Rebase 三种操作 + - AutoID Duration:AutoID 相关操作的耗时 + - Region Cache Error OPS:TiDB 缓存的 region 信息每秒遇到的错误次数 + - Meta Operations Duration 99:元数据操作延迟 + +- GC + - Worker Action OPM:GC 相关操作的数量,包括 run\_job,resolve\_lock,delete\_range 等操作 + - Duration 99:GC 相关操作的耗时统计 + - Config:GC 的数据保存时长(life time)和 GC 运行间隔(run interval)配置 + - GC Failure OPM:GC 相关操作失败数量统计 + - Delete Range Failure OPM:Delete range 失败的次数 + - Too Many Locks Error OPM:GC 清锁过多错误的数量 + - Action Result OPM:GC 相关操作结果数量 + - Delete Range Task Status:Delete range 的任务状态,包含完成和失败状态 + - Push Task Duration 95:将 GC 子任务推送给 GC worker 的耗时 + +- Batch Client + - Pending Request Count by TiKV:等待处理的 Batch 消息数量 + - Wait Duration 95:等待处理的 Batch 消息延迟 + - Batch Client Unavailable Duration 95:Batch 客户端不可用的时间 + - No Available Connection Counter:Batch 客户端找不到可用链接的次数 diff --git a/grafana-tikv-dashboard.md b/grafana-tikv-dashboard.md new file mode 100644 index 000000000000..5aebea6d0561 --- /dev/null +++ b/grafana-tikv-dashboard.md @@ -0,0 +1,420 @@ +--- +title: TiKV 监控指标详解 +category: reference +aliases: ['/docs-cn/stable/reference/key-monitoring-metrics/tikv-dashboard/'] +--- + +# TiKV 监控指标详解 + +使用 TiUP 部署 TiDB 集群时,可以一键部署监控系统 (Prometheus/Grafana),监控架构请看 [TiDB 监控框架概述](/tidb-monitoring-framework.md)。 + +目前默认的 Grafana Dashboard 整体分为 PD、TiDB、TiKV、Node_exporter、Overview 等。 + +对于日常运维,我们通过观察 **TiKV-Details** 面板上的指标,可以了解 TiKV 当前的状态。根据 [性能地图](https://asktug.com/_/tidb-performance-map/#/) 可以检查集群的状态是否符合预期。 + +以下为 **TiKV-Details** 默认的监控信息: + +## Cluster + +- Store size:每个 TiKV 实例的使用的存储空间的大小 +- Available size:每个 TiKV 实例的可用的存储空间的大小 +- Capacity size:每个 TiKV 实例的存储容量的大小 +- CPU:每个 TiKV 实例 CPU 的使用率 +- Memory:每个 TiKV 实例内存的使用情况 +- IO utilization:每个 TiKV 实例 IO 的使用率 +- MBps:每个 TiKV 实例写入和读取的数据量大小 +- QPS:每个 TiKV 实例上各种命令的 QPS +- Errps:每个 TiKV 实例上 gRPC 消息失败的速率 +- leader:每个 TiKV 实例 leader 的个数 +- Region:每个 TiKV 实例 Region 的个数 +- Uptime:自上次重启以来 TiKV 正常运行的时间 + +![TiKV Dashboard - Cluster metrics](/media/tikv-dashboard-cluster.png) + +## Errors + +- Critical error:严重错误的数量 +- Server is busy:各种会导致 TiKV 实例暂时不可用的事件个数,如 write stall,channel full 等,正常情况下应当为 0 +- Server report failures:server 报错的消息个数,正常情况下应当为 0 +- Raftstore error:每个 TiKV 实例上 raftstore 发生错误的个数 +- Scheduler error:每个 TiKV 实例上 scheduler 发生错误的个数 +- Coprocessor error:每个 TiKV 实例上 coprocessor 发生错误的个数 +- gRPC message error:每个 TiKV 实例上 gRPC 消息发生错误的个数 +- Leader drop:每个 TiKV 实例上 drop leader 的个数 +- Leader missing:每个 TiKV 实例上 missing leader 的个数 + +![TiKV Dashboard - Errors metrics](/media/tikv-dashboard-errors.png) + +## Server + +- CF size:每个列族的大小 +- Store size:每个 TiKV 实例的使用的存储空间的大小 +- Channel full:每个 TiKV 实例上 channel full 错误的数量,正常情况下应当为 0 +- Active written leaders:各个 TiKV 实例中正在被写入的 Leader 的数量 +- Approximate Region size:每个 Region 近似的大小 +- Approximate Region size Histogram:每个 Region 近似大小的直方图 +- Region average written keys:每个 TiKV 实例上所有 Region 的平均 key 写入个数 +- Region average written bytes:每个 TiKV 实例上所有 Region 的平均写入大小 + +![TiKV Dashboard - Server metrics](/media/tikv-dashboard-server.png) + +## gRPC + +- gRPC message count:每种 gRPC 请求的速度 +- gRPC message failed:失败的 gRPC 请求的速度 +- 99% gRPC message duration:99% gRPC 请求的执行时间小于该值 +- Average gRPC message duration:gRPC 请求平均的执行时间 +- gRPC batch size:TiDB 与 TiKV 之间 grpc 请求的 batch 大小 +- raft message batch size:TiKV 与 TiKV 之间 raft 消息的 batch 大小 + +## Thread CPU + +- Raft store CPU:raftstore 线程的 CPU 使用率,通常应低于 80% * `raftstore.store-pool-size` +- Async apply CPU:async apply 线程的 CPU 使用率,通常应低于 90% * `raftstore.apply-pool-size` +- Scheduler worker CPU:scheduler worker 线程的 CPU 使用率,通常应低于 90% * `storage.scheduler-worker-pool-size` +- gRPC poll CPU:gRPC 线程的 CPU 使用率,通常应低于 80% * `server.grpc-concurrency` +- Unified read pool CPU:unified read pool 线程的 CPU 使用率 +- Storage ReadPool CPU:storage read pool 线程的 CPU 使用率 +- Coprocessor CPU:coprocessor 线程的 CPU 使用率 +- RocksDB CPU:RocksDB 线程的 CPU 使用率 +- Split check CPU:split check 线程的 CPU 使用率 +- GC worker CPU:GC worker 线程的 CPU 使用率 +- Snapshot worker CPU:snapshot worker 线程的 CPU 使用率 + +## PD + +- PD requests:TiKV 发送给 PD 的请求速度 +- PD request duration (average):TiKV 发送给 PD 的请求处理的平均时间 +- PD heartbeats:发送给 PD 的心跳的速度 +- PD validate peers:TiKV 发送给 PD 用于验证 TiKV 的 peer 有效的消息的速度 + +## Raft IO + +- Apply log duration:Raft apply 日志所花费的时间 +- Apply log duration per server:每个 TiKV 实例上 Raft apply 日志所花费的时间 +- Append log duration:Raft append 日志所花费的时间 +- Append log duration per server:每个 TiKV 实例上 Raft append 日志所花费的时间 +- Commit log duration:Raft commit 日志所花费的时间 +- Commit log duration per server:每个 TiKV 实例上 Raft commit 日志所花费的时间 + +![TiKV Dashboard - Raft IO metrics](/media/tikv-dashboard-raftio.png) + +## Raft process + +- Ready handled:Raft 中不同 ready 类型的 ops +- 0.99 Duration of Raft store events:99% 的 raftstore 事件所花费的时间 +- Process ready duration:处理 ready 所花费的时间 +- Process ready duration per server:每个 TiKV 实例处理 ready 所花费的时间,99.99% 的情况下,应该小于 2s + +![TiKV Dashboard - Raft process metrics](/media/tikv-dashboard-raft-process.png) + +## Raft message + +- Sent messages per server:每个 TiKV 实例发送 Raft 消息的 ops +- Flush messages per server:每个 TiKV 实例中 raft client 往外 flush Raft 消息的 ops +- Receive messages per server:每个 TiKV 实例接受 Raft 消息的 ops +- Messages:发送不同类型的 Raft 消息的 ops +- Vote:Raft 投票消息发送的 ops +- Raft dropped messages:每秒钟丢弃不同类型的 Raft 消息的个数 + +![TiKV Dashboard - Raft message metrics](/media/tikv-dashboard-raft-message.png) + +## Raft propose + +- Raft apply proposals per ready:在一个 batch 内,apply proposal 时每个 ready 中包含 proposal 的个数的直方图 +- Raft read/write proposals:不同类型的 proposal 的 ops +- Raft read proposals per server:每个 TiKV 实例发起读 proposal 的 ops +- Raft write proposals per server:每个 TiKV 实例发起写 proposal 的 ops +- Propose wait duration:proposal 的等待时间的直方图 +- Propose wait duration per server:每个 TiKV 实例上每个 proposal 的等待时间的直方图 +- Apply wait duration:apply 的等待时间的直方图 +- Apply wait duration per server:每个 TiKV 实例上每个 apply 的等待时间的直方图 +- Raft log speed:peer propose 日志的平均速度 + +![TiKV Dashboard - Raft propose metrics](/media/tikv-dashboard-raft-propose.png) + +## Raft admin + +- Admin proposals:admin proposal 的 ops +- Admin apply:apply 命令的 ops +- Check split:split check 命令的 ops +- 99.99% Check split duration:99.99% 的情况下,split check 所需花费的时间 + +![TiKV Dashboard - Raft admin metrics](/media/tikv-dashboard-raft-admin.png) + +## Local reader + +- Local reader requests:所有请求的总数以及 local read 线程拒绝的请求数量 + +![TiKV Dashboard - Local reader metrics](/media/tikv-dashboard-local-reader.png) + +## Unified Read Pool + +- Time used by level:在 unified read pool 中每个级别使用的时间,级别 0 指小查询 +- Level 0 chance:在 unified read pool 中调度的 level 0 任务的比例 +- Running tasks:在 unified read pool 中并发运行的任务数量 + +## Storage + +- Storage command total:收到不同命令的 ops +- Storage async request error:异步请求出错的 ops +- Storage async snapshot duration:异步处理 snapshot 所花费的时间,99% 的情况下,应该小于 1s +- Storage async write duration:异步写所花费的时间,99% 的情况下,应该小于 1s + +![TiKV Dashboard - Storage metrics](/media/tikv-dashboard-storage.png) + +## Scheduler + +- Scheduler stage total:每种命令不同阶段的 ops,正常情况下,不会在短时间内出现大量的错误 +- Scheduler writing bytes:每个 TiKV 实例正在处理的命令的写入字节数量 +- Scheduler priority commands:不同优先级命令的 ops +- Scheduler pending commands:每个 TiKV 实例上 pending 命令的 ops + +![TiKV Dashboard - Scheduler metrics](/media/tikv-dashboard-scheduler.png) + +## Scheduler - commit + +- Scheduler stage total:commit 中每个命令所处不同阶段的 ops,正常情况下,不会在短时间内出现大量的错误 +- Scheduler command duration:执行 commit 命令所需花费的时间,正常情况下,应该小于 1s +- Scheduler latch wait duration:由于 latch wait 造成的时间开销,正常情况下,应该小于 1s +- Scheduler keys read:commit 命令读取 key 的个数 +- Scheduler keys written:commit 命令写入 key 的个数 +- Scheduler scan details:执行 commit 命令时,扫描每个 CF 中 key 的详细情况 +- Scheduler scan details [lock]:执行 commit 命令时,扫描每个 lock CF 中 key 的详细情况 +- Scheduler scan details [write]:执行 commit 命令时,扫描每个 write CF 中 key 的详细情况 +- Scheduler scan details [default]:执行 commit 命令时,扫描每个 default CF 中 key 的详细情况 + +![TiKV Dashboard - Scheduler commit metrics](/media/tikv-dashboard-scheduler-commit.png) + +## Scheduler - pessimistic_rollback + +- Scheduler stage total:pessimistic_rollback 中每个命令所处不同阶段的 ops,正常情况下,不会在短时间内出现大量的错误 +- Scheduler command duration:执行 pessimistic_rollback 命令所需花费的时间,正常情况下,应该小于 1s +- Scheduler latch wait duration:由于 latch wait 造成的时间开销,正常情况下,应该小于 1s +- Scheduler keys read:pessimistic_rollback 命令读取 key 的个数 +- Scheduler keys written:pessimistic_rollback 命令写入 key 的个数 +- Scheduler scan details:执行 pessimistic_rollback 命令时,扫描每个 CF 中 key 的详细情况 +- Scheduler scan details [lock]:执行 pessimistic_rollback 命令时,扫描每个 lock CF 中 key 的详细情况 +- Scheduler scan details [write]:执行 pessimistic_rollback 命令时,扫描每个 write CF 中 key 的详细情况 +- Scheduler scan details [default]:执行 pessimistic_rollback 命令时,扫描每个 default CF 中 key 的详细情况 + +## Scheduler - prewrite + +- Scheduler stage total:prewrite 中每个命令所处不同阶段的 ops,正常情况下,不会在短时间内出现大量的错误 +- Scheduler command duration:执行 prewrite 命令所需花费的时间,正常情况下,应该小于 1s +- Scheduler latch wait duration:由于 latch wait 造成的时间开销,正常情况下,应该小于 1s +- Scheduler keys read:prewrite 命令读取 key 的个数 +- Scheduler keys written:prewrite 命令写入 key 的个数 +- Scheduler scan details:执行 prewrite 命令时,扫描每个 CF 中 key 的详细情况 +- Scheduler scan details [lock]:执行 prewrite 命令时,扫描每个 lock CF 中 key 的详细情况 +- Scheduler scan details [write]:执行 prewrite 命令时,扫描每个 write CF 中 key 的详细情况 +- Scheduler scan details [default]:执行 prewrite 命令时,扫描每个 default CF 中 key 的详细情况 + +## Scheduler - rollback + +- Scheduler stage total:rollback 中每个命令所处不同阶段的 ops,正常情况下,不会在短时间内出现大量的错误 +- Scheduler command duration:执行 rollback 命令所需花费的时间,正常情况下,应该小于 1s +- Scheduler latch wait duration:由于 latch wait 造成的时间开销,正常情况下,应该小于 1s +- Scheduler keys read:rollback 命令读取 key 的个数 +- Scheduler keys written:rollback 命令写入 key 的个数 +- Scheduler scan details:执行 rollback 命令时,扫描每个 CF 中 key 的详细情况 +- Scheduler scan details [lock]:执行 rollback 命令时,扫描每个 lock CF 中 key 的详细情况 +- Scheduler scan details [write]:执行 rollback 命令时,扫描每个 write CF 中 key 的详细情况 +- Scheduler scan details [default]:执行 rollback 命令时,扫描每个 default CF 中 key 的详细情况 + +## GC + +- MVCC versions:每个 key 的版本个数 +- MVCC delete versions:GC 删除掉的每个 key 的版本个数 +- GC tasks:由 gc_worker 处理的 GC 任务的个数 +- GC tasks Duration:执行 GC 任务时所花费的时间 +- GC keys (write CF):在 GC 过程中,write CF 中 受影响的 key 的个数 +- TiDB GC worker actions:TiDB GC worker 的不同 action 的个数 +- TiDB GC seconds:TiDB 执行 GC 花费的时间 +- GC speed:GC 每秒删除的 key 的数量 +- TiKV AutoGC Working:Auto GC 管理器的工作状态 +- ResolveLocks Progress:GC 第一阶段(ResolveLocks)的进度 +- TiKV Auto GC Progress:GC 第二阶段的进度 +- TiKV Auto GC SafePoint:TiKV GC 的 safe point 的数值,safe point 为当前 GC 的时间戳 +- GC lifetime:TiDB 设置的 GC lifetime +- GC interval:TiDB 设置的 GC 间隔 + +## Snapshot + +- Rate snapshot message:发送 Raft snapshot 消息的速率 +- 99% Handle snapshot duration:99% 的情况下,处理 snapshot 所需花费的时间 +- Snapshot state count:不同状态的 snapshot 的个数 +- 99.99% Snapshot size:99.99% 的 snapshot 的大小 +- 99.99% Snapshot KV count:99.99% 的 snapshot 包含的 key 的个数 + +## Task + +- Worker handled tasks:worker 每秒钟处理的任务的数量 +- Worker pending tasks:当前 worker 中,每秒钟 pending 和 running 的任务的数量,正常情况下,应该小于 1000 +- FuturePool handled tasks:future pool 每秒钟处理的任务的数量 +- FuturePool pending tasks:当前 future pool 中,每秒钟 pending 和 running 的任务的数量 + +## Coprocessor Overview + +- Request duration:从收到 coprocessor 请求到处理结束所消耗的总时间 +- Total Requests:每种类型的总请求的 ops +- Handle duration:每分钟实际处理 coprocessor 请求所消耗的时间的直方图 +- Total Request Errors:Coprocessor 每秒请求错误的数量,正常情况下,短时间内不应该有大量的错误 +- Total KV Cursor Operations:各种类型的 KV cursor 操作的总数量的 ops,例如 select、index、analyze_table、analyze_index、checksum_table、checksum_index 等 +- KV Cursor Operations:每秒各种类型的 KV cursor 操作的数量,以直方图形式显示 +- Total RocksDB Perf Statistics:RocksDB 性能统计数据 +- Total Response Size:coprocessor 回应的数据大小 + +## Coprocessor Detail + +- Handle duration:每秒钟实际处理 coprocessor 请求所消耗的时间的直方图 +- 95% Handle duration by store:每秒钟中 95% 的情况下,每个 TiKV 实例处理 coprocessor 请求所花费的时间 +- Wait duration:coprocessor 每秒钟内请求的等待时间,99.99% 的情况下,应该小于 10s +- 95% Wait duration by store:每秒钟 95% 的情况下,每个 TiKV 实例上 coprocessor 请求的等待时间 +- Total DAG Requests:DAG 请求的总数量的 ops +- Total DAG Executors:DAG executor 的总数量的 ops +- Total Ops Details (Table Scan):coprocessor 中请求为 select 的 scan 过程中每秒钟各种事件发生的次数 +- Total Ops Details (Index Scan):coprocessor 中请求为 index 的 scan 过程中每秒钟各种事件发生的次数 +- Total Ops Details by CF (Table Scan):coprocessor 中对于每个 CF 请求为 select 的 scan 过程中每秒钟各种事件发生的次数 +- Total Ops Details by CF (Index Scan):coprocessor 中对于每个 CF 请求为 index 的 scan 过程中每秒钟各种事件发生的次数 + +## Threads + +- Threads state:TiKV 线程的状态 +- Threads IO:TiKV 各个线程的 I/O 流量 +- Thread Voluntary Context Switches:TiKV 线程自主切换的次数 +- Thread Nonvoluntary Context Switches:TiKV 线程被动切换的次数 + +## RocksDB - kv/raft + +- Get operations:get 操作的 ops +- Get duration:get 操作的耗时 +- Seek operations:seek 操作的 ops +- Seek duration:seek 操作的耗时 +- Write operations:write 操作的 ops +- Write duration:write 操作的耗时 +- WAL sync operations:sync WAL 操作的 ops +- Write WAL duration:write 操作中写 WAL 的耗时 +- WAL sync duration:sync WAL 操作的耗时 +- Compaction operations:compaction 和 flush 操作的 ops +- Compaction duration:compaction 和 flush 操作的耗时 +- SST read duration:读取 SST 所需的时间 +- Write stall duration:由于 write stall 造成的时间开销,正常情况下应为 0 +- Memtable size:每个 CF 的 memtable 的大小 +- Memtable hit:memtable 的命中率 +- Block cache size:block cache 的大小。如果将 `shared block cache` 禁用,即为每个 CF 的 block cache 的大小 +- Block cache hit:block cache 的命中率 +- Block cache flow:不同 block cache 操作的流量 +- Block cache operations 不同 block cache 操作的个数 +- Keys flow:不同操作造成的 key 的流量 +- Total keys:每个 CF 中 key 的个数 +- Read flow:不同读操作的流量 +- Bytes / Read:每次读的大小 +- Write flow:不同写操作的流量 +- Bytes / Write:每次写的大小 +- Compaction flow:compaction 相关的流量 +- Compaction pending bytes:等待 compaction 的大小 +- Read amplification:每个 TiKV 实例的读放大 +- Compression ratio:每一层的压缩比 +- Number of snapshots:每个 TiKV 的 snapshot 的数量 +- Oldest snapshots duration:最旧的 snapshot 保留的时间 +- Number files at each level:每一层的文件个数 +- Ingest SST duration seconds:ingest SST 所花费的时间 +- Stall conditions changed of each CF:每个 CF stall 的原因 + +## Titan - All + +- Blob file count:Titan blob 文件的数量 +- Blob file size:Titan blob 文件总大小 +- Live blob size:有效 blob record 的总大小 +- Blob cache hit:Titan 的 blob cache 命中率 +- Iter touched blob file count:单个 Iterator 所涉及到 blob 文件的数量 +- Blob file discardable ratio distribution:blob 文件的失效 blob record 比例的分布情况 +- Blob key size:Titan 中 blob key 的大小 +- Blob value size:Titan 中 blob value 的大小 +- Blob get operations:blob 的 get 操作的数量 +- Blob get duration:blob 的 get 操作的耗时 +- Blob iter operations:blob 的 iter 操作的耗时 +- Blob seek duration:blob 的 seek 操作的耗时 +- Blob next duration:blob 的 next 操作的耗时 +- Blob prev duration:blob 的 prev 操作的耗时 +- Blob keys flow:Titan blob 读写的 key 数量 +- Blob bytes flow:Titan blob 读写的 bytes 数量 +- Blob file read duration:blob 文件的读取耗时 +- Blob file write duration:blob 文件的写入耗时 +- Blob file sync operations:blob 文件 sync 次数 +- Blob file sync duration:blob 文件 sync 耗时 +- Blob GC action:Titan GC 细分动作的次数 +- Blob GC duration:Titan GC 的耗时 +- Blob GC keys flow:Titan GC 读写的 key 数量 +- Blob GC bytes flow:Titan GC 读写的 bytes 数量 +- Blob GC input file size:Titan GC 输入文件的大小 +- Blob GC output file size:Titan GC 输出文件的大小 +- Blob GC file count:Titan GC 涉及的 blob 文件数量 + +## Lock manager + +- Thread CPU:lock manager 的线程 CPU 使用率 +- Handled tasks:lock manager 处理的任务数量 +- Waiter lifetime duration:事务等待锁释放的时间 +- Wait table:wait table 的状态信息,包括锁的数量和等锁事务的数量 +- Deadlock detect duration:处理死锁检测请求的耗时 +- Detect error:死锁检测遇到的错误数量,包含死锁的数量 +- Deadlock detector leader:死锁检测器 leader 所在节点的信息 + +## Memory + +- Allocator Stats:内存分配器的统计信息 + +## Backup + +- Backup CPU:backup 的线程 CPU 使用率 +- Range Size:backup range 的大小直方图 +- Backup Duration:backup 的耗时 +- Backup Flow:backup 总的字节大小 +- Disk Throughput:实例磁盘的吞吐量 +- Backup Range Duration:backup range 的耗时 +- Backup Errors:backup 中发生的错误数量 + +## Encryption + +- Encryption data keys:正在使用的加密 data key 的总数量 +- Encrypted files:被加密的文件数量 +- Encryption initialized:显示加密是否被启用,`1` 代表已经启用 +- Encryption meta files size:加密相关的元数据文件的大小 +- Encrypt/decrypt data nanos:每次加密/解密数据的耗时的直方图 +- Read/write encryption meta duration:每秒钟读写加密文件所耗费的时间 + +## 面板常见参数的解释 + +### gRPC 消息类型 + +1. 使用事务型接口的命令: + + - kv_get:事务型的 get 命令,获取指定 ts 能读到的最新版本数据 + - kv_scan:扫描连续的一段数据 + - kv_prewrite:2PC 的第一阶段,预写入事务要提交的数据 + - kv_pessimistic_lock:对 key 加悲观锁,防止其他事务修改 + - kv_pessimistic_rollback:删除 key 上的悲观锁 + - kv_txn_heart_beat:更新悲观事务或大事务的 `lock_ttl` 以防止其被回滚 + - kv_check_txn_status:检查事务的状态 + - kv_commit:2PC 的第二阶段,提交 prewrite 阶段写入的数据 + - kv_cleanup:回滚一个事务(此命令将会在 4.0 中废除) + - kv_batch_get:与 `kv_get` 类似,一次性获取批量 key 的 value + - kv_batch_rollback:批量回滚多个预写的事务 + - kv_scan_lock:扫描所有版本号在 `max_version` 之前的锁,用于清理过期的事务 + - kv_resolve_lock:根据事务状态,提交或回滚事务的锁 + - kv_gc:触发垃圾回收 + - kv_delete_range:从 TiKV 中删除连续的一段数据 + +2. 非事务型的裸命令: + + - raw_get:获取 key 所对应的 value + - raw_batch_get:获取一批 key 所对应的 value + - raw_scan:扫描一段连续的数据 + - raw_batch_scan:扫描多段连续的数据 + - raw_put:写入一个 key/value 对 + - raw_batch_put:直接写入一批 key/value 对 + - raw_delete:删除一个 key/value 对 + - raw_batch_delete:删除一批 key/value 对 + - raw_delete_range:删除连续的一段区间 diff --git a/hardware-and-software-requirements.md b/hardware-and-software-requirements.md new file mode 100644 index 000000000000..2e6c0af910e6 --- /dev/null +++ b/hardware-and-software-requirements.md @@ -0,0 +1,119 @@ +--- +title: TiDB 软件和硬件环境建议配置 +category: how-to +aliases: ['/docs-cn/stable/how-to/deploy/hardware-recommendations/'] +--- + +# TiDB 软件和硬件环境建议配置 + +TiDB 作为一款开源分布式 NewSQL 数据库,可以很好的部署和运行在 Intel 架构服务器环境、ARM 架构的服务器环境及主流虚拟化环境,并支持绝大多数的主流硬件网络。作为一款高性能数据库系统,TiDB 支持主流的 Linux 操作系统环境。 + +## Linux 操作系统版本要求 + +| Linux 操作系统平台 | 版本 | +| :----------------------- | :----------: | +| Red Hat Enterprise Linux | 7.3 及以上 | +| CentOS | 7.3 及以上 | +| Oracle Enterprise Linux | 7.3 及以上 | +| Ubuntu LTS | 16.04 及以上 | + +> **注意:** +> +> - TiDB 只支持 Red Hat 兼容内核 (RHCK) 的 Oracle Enterprise Linux,不支持 Oracle Enterprise Linux 提供的 Unbreakable Enterprise Kernel。 +> - TiDB 在 CentOS 7.3 的环境下进行过大量的测试,同时社区也有很多该操作系统部署的最佳实践,因此,建议使用 CentOS 7.3 以上的 Linux 操作系统来部署 TiDB。 +> - 以上 Linux 操作系统可运行在物理服务器以及 VMware、KVM、XEN 主流虚拟化环境上。 + +## 软件配置要求 + +### 中控机软件配置 + +| 软件 | 版本 | +| :----------------------- | :----------: | +| sshpass | 1.06 及以上 | +| TiUP | 0.6.2 及以上 | + +> **注意:** +> +> 中控机需要部署 [TiUP 软件](/tiup/tiup-documentation-guide.md)来完成 TiDB 集群运维管理。 + +### 目标主机建议配置软件 + +| 软件 | 版本 | +| :----- | :----------: | +| sshpass | 1.06 及以上 | +| numa | 2.0.12 及以上 | + +## 服务器建议配置 + +TiDB 支持部署和运行在 Intel x86-64 架构的 64 位通用硬件服务器平台或者 ARM 架构的硬件服务器平台。对于开发,测试,及生产环境的服务器硬件配置(不包含操作系统 OS 本身的占用)有以下要求和建议: + +### 开发及测试环境 + +| **组件** | **CPU** | **内存** | **本地存储** | **网络** | **实例数量(最低要求)** | +| --- | --- | --- | --- | --- | --- | +| TiDB | 8 核+ | 16 GB+ | 无特殊要求 | 千兆网卡 | 1(可与 PD 同机器) | +| PD | 4 核+ | 8 GB+ | SAS, 200 GB+ | 千兆网卡 | 1(可与 TiDB 同机器) | +| TiKV | 8 核+ | 32 GB+ | SSD, 200 GB+ | 千兆网卡 | 3 | +| TiFlash | 32 核+ | 64 GB+ | SSD, 200 GB+ | 千兆网卡 | 1 | +| TiCDC | 8 核+ | 16 GB+ | SAS, 200 GB+ | 千兆网卡 | 1 | + +> **注意:** +> +> - 验证测试环境中的 TiDB 和 PD 可以部署在同一台服务器上。 +> - 如进行性能相关的测试,避免采用低性能存储和网络硬件配置,防止对测试结果的正确性产生干扰。 +> - TiKV 的 SSD 盘推荐使用 NVME 接口以保证读写更快。 +> - 如果仅验证功能,建议使用 [TiDB 数据库快速上手指南](/quick-start-with-tidb.md)进行单机功能测试。 +> - TiDB 对于磁盘的使用以存放日志为主,因此在测试环境中对于磁盘类型和容量并无特殊要求。 + +### 生产环境 + +| **组件** | **CPU** | **内存** | **硬盘类型** | **网络** | **实例数量(最低要求)** | +| --- | --- | --- | --- | --- | --- | +| TiDB | 16 核+ | 32 GB+ | SAS | 万兆网卡(2 块最佳) | 2 | +| PD | 4核+ | 8 GB+ | SSD | 万兆网卡(2块最佳) | 3 | +| TiKV | 16 核+ | 32 GB+ | SSD | 万兆网卡(2 块最佳) | 3 | +| TiFlash | 48 核+ | 128 GB+ | 1 or more SSDs | 万兆网卡(2 块最佳) | 2 | +| TiCDC | 16 核+ | 64 GB+ | SSD | 万兆网卡(2 块最佳) | 2 | +| 监控 | 8 核+ | 16 GB+ | SAS | 千兆网卡 | 1 | + +> **注意:** +> +> - 生产环境中的 TiDB 和 PD 可以部署和运行在同服务器上,如对性能和可靠性有更高的要求,应尽可能分开部署。 +> - 生产环境强烈推荐使用更高的配置。 +> - TiKV 硬盘大小配置建议 PCI-E SSD 不超过 2 TB,普通 SSD 不超过 1.5 TB。 +> - TiFlash 支持[多盘部署](/tiflash/tiflash-configuration.md#多盘部署),所以无需使用 RAID。 +> - TiFlash 数据目录的第一块磁盘推荐用高性能 SSD 来缓冲 TiKV 同步数据的实时写入,该盘性能应不低于 TiKV 所使用的磁盘,比如 PCI-E SSD。并且该磁盘容量建议不小于总容量的 10%,否则它可能成为这个节点的能承载的数据量的瓶颈。而其他磁盘可以根据需求部署多块普通 SSD,当然更好的 PCI-E SSD 硬盘会带来更好的性能。 +> - TiFlash 推荐与 TiKV 部署在不同节点,如果条件所限必须将 TiFlash 与 TiKV 部署在相同节点,则需要适当增加 CPU 核数和内存,且尽量将 TiFlash 与 TiKV 部署在不同的磁盘,以免互相干扰。 +> - TiFlash 硬盘总容量大致为:`整个 TiKV 集群的需同步数据容量 / TiKV 副本数 * TiFlash 副本数`。例如整体 TiKV 的规划容量为 1 TB、TiKV 副本数为 3、TiFlash 副本数为 2,则 TiFlash 的推荐总容量为 `1024 GB / 3 * 2`。用户可以选择同步部分表数据而非全部,具体容量可以根据需要同步的表的数据量具体分析。 +> - TiCDC 硬盘配置建议 200 GB+ PCIE-SSD。 + +## 网络要求 + +TiDB 作为开源分布式 NewSQL 数据库,其正常运行需要网络环境提供如下的网络端口配置要求,管理员可根据实际环境中 TiDB 组件部署的方案,在网络侧和主机侧开放相关端口: + +| 组件 | 默认端口 | 说明 | +| :-- | :-- | :-- | +| TiDB | 4000 | 应用及 DBA 工具访问通信端口 | +| TiDB | 10080 | TiDB 状态信息上报通信端口 | +| TiKV | 20160 | TiKV 通信端口 | +| PD | 2379 | 提供 TiDB 和 PD 通信端口 | +| PD | 2380 | PD 集群节点间通信端口 | +|TiFlash|9000|TiFlash TCP 服务端口| +|TiFlash|8123|TiFlash HTTP 服务端口| +|TiFlash|3930|TiFlash RAFT 服务和 Coprocessor 服务端口| +|TiFlash|20170|TiFlash Proxy 服务端口| +|TiFlash|20292|Prometheus 拉取 TiFlash Proxy metrics 端口| +|TiFlash|8234|Prometheus 拉取 TiFlash metrics 端口| +| Pump | 8250 | Pump 通信端口 | +| Drainer | 8249 | Drainer 通信端口 | +| CDC | 8300 | CDC 通信接口 | +| Prometheus | 9090 | Prometheus 服务通信端口 | +| Node_exporter | 9100 | TiDB 集群每个节点的系统信息上报通信端口 | +| Blackbox_exporter | 9115 | Blackbox_exporter 通信端口,用于 TiDB 集群端口监控 | +| Grafana | 3000 | Web 监控服务对外服务和客户端(浏览器)访问端口 | +| Alertmanager | 9093 | 告警 web 服务端口 | +| Alertmanager | 9094 | 告警通信端口 | + +## 客户端 Web 浏览器要求 + +TiDB 提供了基于 [Grafana](https://grafana.com/) 的技术平台,对数据库集群的各项指标进行可视化展现。采用支持 Javascript 的微软 IE、Google Chrome、Mozilla Firefox 的较新版本即可访问监控入口。 diff --git a/how-to/configure/memory-control.md b/how-to/configure/memory-control.md deleted file mode 100644 index 6616a180cfcf..000000000000 --- a/how-to/configure/memory-control.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: TiDB 内存控制文档 -category: how-to ---- - -# TiDB 内存控制文档 - -目前 TiDB 已经能够做到追踪单条 SQL 查询过程中的内存使用情况,当内存使用超过一定阈值后也能采取一些操作来预防 OOM 或者排查 OOM 原因。在 TiDB 的配置文件中,我们可以使用如下配置来控制内存使用超阈值时 TiDB 的行为: - -{{< copyable "" >}} - -``` -# Valid options: ["log", "cancel"] -oom-action = "log" -``` - -- 如果上面的配置项使用的是 "log",那么当一条 SQL 的内存使用超过一定阈值(由 session 变量 `tidb_mem_quota_query` 来控制)后,TiDB 会在 log 文件中打印一条 LOG,然后这条 SQL 继续执行,之后如果发生了 OOM 可以在 LOG 中找到对应的 SQL。 -- 如果上面的配置项使用的是 "cancel",那么当一条 SQL 的内存使用超过一定阈值后,TiDB 会立即中断这条 SQL 的执行并给客户端返回一个 error,error 信息中会详细写明这条 SQL 执行过程中各个占用内存比较多的物理执行算子的内存使用情况。 - -## 如何配置一条 SQL 执行过程中的内存使用阈值 - -可以在配置文件中设置每个 Query 默认的 Memory Quota,例如将其设置为 32GB: - -{{< copyable "" >}} - -``` -mem-quota-query = 34359738368 -``` - -此外还可通过如下几个 session 变量来控制一条 Query 中的内存使用,大多数用户只需要设置 `tidb_mem_quota_query` 即可,其他变量是高级配置,大多数用户不需要关心: - -| 变量名 | 作用 | 单位 | 默认值 | -|:-----------------------------------|:---------------------------------------------------|:-------|:-----------| -| tidb_mem_quota_query | 配置整条 SQL 的内存使用阈值 | Byte | 32 << 30 | -| tidb_mem_quota_hashjoin | 配置 Hash Join 的内存使用阈值 | Byte | 32 << 30 | -| tidb_mem_quota_mergejoin | 配置 Merge Join 的内存使用阈值 | Byte | 32 << 30 | -| tidb_mem_quota_sort | 配置 Sort 的内存使用阈值 | Byte | 32 << 30 | -| tidb_mem_quota_topn | 配置 TopN 的内存使用阈值 | Byte | 32 << 30 | -| tidb_mem_quota_indexlookupreader | 配置 Index Lookup Reader 的内存使用阈值 | Byte | 32 << 30 | -| tidb_mem_quota_indexlookupjoin | 配置 Index Lookup Join 的内存使用阈值 | Byte | 32 << 30 | -| tidb_mem_quota_nestedloopapply | 配置 Nested Loop Apply 的内存使用阈值 | Byte | 32 << 30 | - -几个使用例子: - -配置整条 SQL 的内存使用阈值为 8GB: - -{{< copyable "sql" >}} - -```sql -set @@tidb_mem_quota_query = 8 << 30; -``` - -配置整条 SQL 的内存使用阈值为 8MB: - -{{< copyable "sql" >}} - -```sql -set @@tidb_mem_quota_query = 8 << 20; -``` - -配置整条 SQL 的内存使用阈值为 8KB: - -{{< copyable "sql" >}} - -```sql -set @@tidb_mem_quota_query = 8 << 10; -``` diff --git a/how-to/configure/placement-rules.md b/how-to/configure/placement-rules.md deleted file mode 100644 index 44dd393a3e97..000000000000 --- a/how-to/configure/placement-rules.md +++ /dev/null @@ -1,347 +0,0 @@ ---- -title: Placement Rules 使用文档 -summary: 如何配置 Placement Rules -category: how-to ---- - -# Placement Rules 使用文档 - -Placement Rules 是 PD 在 4.0 版本引入的试验特性,它是一套副本规则系统,用于指导 PD 针对不同类型的数据生成对应的调度。通过组合不同的调度规则,用户可以精细地控制任何一段连续数据的副本数量、存放位置、主机类型、是否参与 Raft 投票、是否可以担任 Raft leader 等属性。 - -## 规则系统介绍 - -整个规则系统的配置由多条规则即 Rule 组成。每条 Rule 可以指定不同的副本数量、Raft 角色、放置位置等属性,以及这条规则生效的 key range。PD 在进行调度时,会先根据 Region 的 key range 在规则系统中查到该 Region 对应的规则,然后再生成对应的调度,来使得 Region 副本的分布情况符合 Rule。 - -多条规则的 key range 可以有重叠部分的,即一个 Region 能匹配到多条规则。这种情况下 PD 根据 Rule 的属性来决定规则是相互覆盖还是同时生效。如果有多条规则同时生效,PD 会按照规则的堆叠次序依次去生成调度进行规则匹配。 - -此外,为了满足不同来源的规则相互隔离的需求,还引入了分组(Group)的概念。如果某条规则不希望与系统中的其他规则相互影响(比如被覆盖),可以使用单独的分组。 - -Placement Rules 示意图如下所示: - -![Placement rules overview](/media/placement-rules-1.png) - -### 规则字段 - -以下是每条规则中各个字段的具体含义: - -| 字段名 | 类型及约束 | 说明 | -| :--- | :--- | :--- | -| `GroupID` | `string` | 分组 ID,标识规则的来源 | -| `ID` | `string` | 分组内唯一 ID | -| `Index` | `int` | 分组内堆叠次序 | -| `Override` | `true`/`false` | 是否覆盖 index 的更小 Rule(限分组内) | -| `StartKey` | `string`,十六进制编码 | 适用 Range 起始 key | -| `EndKey` | `string`,十六进制编码 | 适用 Range 终止 key | -| `Role` | `string` | 副本角色,包括 leader/follower/learner | -| `Count` | `int`,正整数 | 副本数量 | -| `LabelConstraint` | `[]Constraint` | 用于按 label 筛选节点 | -| `LocationLabels` | `[]string` | 用于物理隔离 | - -`LabelConstraint` 与 Kubernetes 中的功能类似,支持通过 `in`、`notIn`、`exists` 和 `notExists` 四种原语来筛选 label。这四种原语的意义如下: - -+ `in`:给定 key 的 label value 包含在给定列表中。 -+ `notIn`:给定 key 的 label value 不包含在给定列表中。 -+ `exists`:包含给定的 label key。 -+ `notExists`:不包含给定的 label key。 - -`LocationLabels` 的意义和作用与 PD v4.0 之前的版本相同。比如配置 `[zone,rack,host]` 定义了三层的拓扑结构:集群分为多个 zone(可用区),每个 zone 下有多个 rack(机架),每个 rack 下有多个 host(主机)。PD 在调度时首先会尝试将 Region 的 Peer 放置在不同的 zone,假如无法满足(比如配置 3 副本但总共只有 2 个 zone)则保证放置在不同的 rack;假如 rack 的数量也不足以保证隔离,那么再尝试 host 级别的隔离,以此类推。 - -## 配置规则操作步骤 - -本节的操作步骤以使用 [pd-ctl](/reference/tools/pd-control.md) 工具为例,涉及到的命令也支持通过 HTTP API 进行调用。 - -### 开启 Placement Rules 特性 - -默认情况下,Placement Rules 特性是关闭的。要开启这个特性,可以集群初始化以前设置 PD 配置文件: - -{{< copyable "" >}} - -```toml -[replication] -enable-placement-rules = true -``` - -这样,PD 在初始化成功后会开启这个特性,并根据 `max-replicas` 及 `location-labels` 配置生成对应的规则: - -{{< copyable "" >}} - -```json -{ - "group_id": "pd", - "id": "default", - "start_key": "", - "end_key": "", - "role": "voter", - "count": 3, - "location_labels": ["zone", "rack", "host"] -} -``` - -如果是已经初始化过的集群,也可以通过 pd-ctl 进行在线开启: - -{{< copyable "shell-regular" >}} - -```bash -pd-ctl config placement-rules enable -``` - -PD 同样将根据系统的 `max-replicas` 及 `location-labels` 生成默认的规则。 - -### 关闭 Placement Rules 特性 - -使用 pd-ctl 可以关闭 Placement Rules 特性,切换为之前的调度策略。 - -{{< copyable "shell-regular" >}} - -```bash -pd-ctl config placement-rules disable -``` - -> **注意:** -> -> 关闭 Placement Rules 后,PD 将使用原先的 `max-replicas` 及 `location-labels` 配置。在 Placement Rules 开启期间对 Rule 的修改不会导致这两项配置的同步更新。此外,设置好的所有 Rule 都会保留在系统中,会在下次开启 Placement Rules 时被使用。 - -### 使用 pd-ctl 设置规则 - -> **注意:** -> -> 规则的变更将实时地影响 PD 调度,不恰当的规则设置可能导致副本数较少,影响系统的高可用。 - -pd-ctl 支持使用多种方式查看系统中的 Rule,输出是 json 格式的 Rule 或 Rule 列表: - -**查看所有规则列表** - -{{< copyable "shell-regular" >}} - -```bash -pd-ctl config placement-rules show -``` - -**查看 PD Group 的所有规则列表** - -{{< copyable "shell-regular" >}} - -```bash -pd-ctl config placement-rules show --group=pd -``` - -**查看对应 Group 和 ID 的某条规则** - -{{< copyable "shell-regular" >}} - -```bash -pd-ctl config placement-rules show --group=pd --id=default -``` - -**查看 Region 所匹配的规则列表** - -{{< copyable "shell-regular" >}} - -```bash -pd-ctl config placement-rules show --region=2 -``` - -上面的例子中 `2` 为 Region ID。 - -新增和编辑规则是类似的,需要把对应的规则写进文件,然后使用 `save` 命令保存至 PD: - -{{< copyable "shell-regular" >}} - -```bash -cat > rules.json <}} - -```bash -cat > rules.json <}} - -```bash -pd-ctl config placement-rules load -``` - -以上命令将所有规则转存至 rules.json 文件。 - -{{< copyable "shell-regular" >}} - -```bash -pd-ctl config placement-rules load --group=pd --out=rule.txt -``` - -以上命令将 PD Group 的规则转存至 rule.txt 文件。 - -### 使用 tidb-ctl 查询表相关的 key range - -若需要针对元数据或某个特定的表进行特殊配置,可以通过 [tidb-ctl](https://github.com/pingcap/tidb-ctl) 的 [`keyrange` 命令](https://github.com/pingcap/tidb-ctl/blob/master/doc/tidb-ctl_keyrange.md) 来查询相关的 key。注意要添加 `--encode` 返回 PD 中的表示形式。 - -{{< copyable "shell-regular" >}} - -```bash -tidb-ctl keyrange --database test --table ttt --encode -``` - -```text -global ranges: - meta: (6d00000000000000f8, 6e00000000000000f8) - table: (7400000000000000f8, 7500000000000000f8) -table ttt ranges: (NOTE: key range might be changed after DDL) - table: (7480000000000000ff2d00000000000000f8, 7480000000000000ff2e00000000000000f8) - table indexes: (7480000000000000ff2d5f690000000000fa, 7480000000000000ff2d5f720000000000fa) - index c2: (7480000000000000ff2d5f698000000000ff0000010000000000fa, 7480000000000000ff2d5f698000000000ff0000020000000000fa) - index c3: (7480000000000000ff2d5f698000000000ff0000020000000000fa, 7480000000000000ff2d5f698000000000ff0000030000000000fa) - index c4: (7480000000000000ff2d5f698000000000ff0000030000000000fa, 7480000000000000ff2d5f698000000000ff0000040000000000fa) - table rows: (7480000000000000ff2d5f720000000000fa, 7480000000000000ff2e00000000000000f8) -``` - -> **注意:** -> -> DDL 等操作会导致 table ID 发生变化,需要同步更新对应的规则。 - -## 典型场景示例 - -本部分介绍 Placement Rules 的使用场景示例。 - -### 场景一:普通的表使用 3 副本,元数据使用 5 副本提升集群容灾能力 - -只需要增加一条规则,将 key range 限定在 meta 数据的范围,并把 `count` 值设为 `5`。添加规则示例如下: - -{{< copyable "" >}} - -```json -{ - "group_id": "pd", - "id": "meta", - "index": 1, - "override": true, - "start_key": "6d00000000000000f8", - "end_key": "6e00000000000000f8", - "role": "voter", - "count": "5", - "location_labels": ["zone", "rack", "host"] -} -``` - -### 场景二:5 副本按 2-2-1 的比例放置在 3 个数据中心,且第 3 个中心不产生 Leader - -创建三条规则,分别设置副本数为 2、2、1,并且在每个规则内通过 `label_constraint` 将副本限定在对应的数据中心内。另外,不需要 leader 的数据中心将 `role` 改为 `follower`。 - -{{< copyable "" >}} - -```json -[ - { - "group_id": "pd", - "id": "zone1", - "start_key": "", - "end_key": "", - "role": "voter", - "count": 2, - "label_constraints": [ - {"key": "zone", "op": "in", "values": ["zone1"]} - ], - "location_labels": ["rack", "host"] - }, - { - "group_id": "pd", - "id": "zone2", - "start_key": "", - "end_key": "", - "role": "voter", - "count": 2, - "label_constraints": [ - {"key": "zone", "op": "in", "values": ["zone2"]} - ], - "location_labels": ["rack", "host"] - }, - { - "group_id": "pd", - "id": "zone3", - "start_key": "", - "end_key": "", - "role": "follower", - "count": 1, - "label_constraints": [ - {"key": "zone", "op": "in", "values": ["zone3"]} - ], - "location_labels": ["rack", "host"] - } -] -``` - -### 场景三:为某张表添加 2 个 TiFlash Learner 副本 - -为表的 row key 单独添加一条规则,限定数量为 2,并且通过 `label_constraint` 保证副本产生在 `engine=tiflash` 的节点。注意这里使用了单独的 `group_id`,保证这条规则不会与系统中其他来源的规则互相覆盖或产生冲突。 - -{{< copyable "" >}} - -```json -{ - "group_id": "tiflash", - "id": "learner-replica-table-ttt", - "start_key": "7480000000000000ff2d5f720000000000fa", - "end_key": "7480000000000000ff2e00000000000000f8", - "role": "learner", - "count": 2, - "label_constraints": [ - {"key": "engine", "op": "in", "values": ["tiflash"]} - ], - "location_labels": ["host"] -} -``` - -### 场景四:为某张表在有高性能磁盘的北京节点添加 2 个 Follower 副本 - -这个例子展示了比较复杂的 `label_constaint` 配置,下面的例子限定了副本放置在 bj1 或 bj2 机房,且磁盘类型不能为 hdd。 - -{{< copyable "" >}} - -```json -{ - "group_id": "follower-read", - "id": "follower-read-table-ttt", - "start_key": "7480000000000000ff2d00000000000000f8", - "end_key": "7480000000000000ff2e00000000000000f8", - "role": "follower", - "count": 2, - "label_constraints": [ - {"key": "zone", "op": "in", "values": ["bj1", "bj2"]}, - {"key": "disk", "op": "notIn", "values": ["hdd"]} - ], - "location_labels": ["host"] -} -``` diff --git a/how-to/configure/time-zone.md b/how-to/configure/time-zone.md deleted file mode 100644 index 9c515419adde..000000000000 --- a/how-to/configure/time-zone.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: 时区支持 -category: how-to ---- - -# 时区支持 - -TiDB 使用的时区由 `time_zone` 全局变量和 session 变量决定。`time_zone` 的默认值是 `System`,`System` 对应的实际时区在 `TiDB` 集群 bootstrap 初始化时设置。具体逻辑如下: - -* 优先使用 `TZ` 环境变量 -* 如果失败,则从 `/etc/localtime` 的实际软链地址提取。 -* 如果上面两种都失败则使用 `UTC` 作为系统时区。 - -在运行过程中可以修改全局时区: - -{{< copyable "sql" >}} - -```sql -SET GLOBAL time_zone = timezone; -``` - -TiDB 还可以通过设置 session 变量 `time_zone` 为每个连接维护各自的时区。默认条件下,这个值取的是全局变量 `time_zone` 的值。修改 session 使用的时区: - -{{< copyable "sql" >}} - -```sql -SET time_zone = timezone; -``` - -查看当前使用的时区的值: - -{{< copyable "sql" >}} - -```sql -SELECT @@global.time_zone, @@session.time_zone; -``` - -设置 `time_zone` 的值的格式: - -* 'SYSTEM' 表明使用系统时间 -* 相对于 UTC 时间的偏移,比如 '+10:00' 或者 '-6:00' -* 某个时区的名字,比如 'Europe/Helsinki', 'US/Eastern' 或 'MET' - -`NOW()` 和 `CURTIME()` 的返回值都受到时区设置的影响。 - -> **注意:** -> -> 只有 Timestamp 数据类型的值是受时区影响的。可以理解为,Timestamp 数据类型的实际表示使用的是 (字面值 + 时区信息)。其它时间和日期类型,比如 Datetime/Date/Time 是不包含时区信息的,所以也不受到时区变化的影响。 - -{{< copyable "sql" >}} - -{{< copyable "sql" >}} - -```sql -create table t (ts timestamp, dt datetime); -``` - -``` -Query OK, 0 rows affected (0.02 sec) -``` - -{{< copyable "sql" >}} - -```sql -set @@time_zone = 'UTC'; -``` - -``` -Query OK, 0 rows affected (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -insert into t values ('2017-09-30 11:11:11', '2017-09-30 11:11:11'); -``` - -``` -Query OK, 1 row affected (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -set @@time_zone = '+8:00'; -``` - -``` -Query OK, 0 rows affected (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -select * from t; -``` - -``` -+---------------------|---------------------+ -| ts | dt | -+---------------------|---------------------+ -| 2017-09-30 19:11:11 | 2017-09-30 11:11:11 | -+---------------------|---------------------+ -1 row in set (0.00 sec) -``` - -上面的例子中,无论怎么调整时区的值,Datetime 类型字段的值是不受影响的,而 Timestamp 则随着时区改变,显示的值会发生变化。其实 Timestamp 持久化到存储的值始终没有变化过,只是根据时区的不同显示值不同。 - -Timestamp 类型和 Datetime 等类型的值,两者相互转换的过程中,会涉及到时区。这种情况一律基于 session 的当前 `time_zone` 时区处理。 - -另外,用户在导数据的过程中,也要需注意主库和从库之间的时区设定是否一致。 diff --git a/how-to/deploy/geographic-redundancy/location-awareness.md b/how-to/deploy/geographic-redundancy/location-awareness.md deleted file mode 100644 index 723742fcde32..000000000000 --- a/how-to/deploy/geographic-redundancy/location-awareness.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: 集群拓扑信息配置 -category: how-to ---- - -# 集群拓扑信息配置 - -## 概述 - -PD 能够根据 TiKV 集群的拓扑结构进行调度,使得 TiKV 的容灾能力最大化。 - -阅读本章前,请先确保阅读 [TiDB Ansible 部署方案](/how-to/deploy/orchestrated/ansible.md) 和 [Docker 部署方案](/how-to/deploy/orchestrated/docker.md)。 - -## TiKV 上报拓扑信息 - -可以通过 TiKV 的启动参数或者配置文件来让 TiKV 上报拓扑信息给 PD。 - -假设拓扑结构分为三级:zone > rack > host,可以通过 labels 来指定这些信息。 - -启动参数: - -``` -tikv-server --labels zone=,rack=,host= -``` - -配置文件: - -{{< copyable "" >}} - -```toml -[server] -labels = "zone=,rack=,host=" -``` - -## PD 理解 TiKV 拓扑结构 - -可以通过 PD 的配置文件让 PD 理解 TiKV 集群的拓扑结构。 - -{{< copyable "" >}} - -```toml -[replication] -max-replicas = 3 -location-labels = ["zone", "rack", "host"] -``` - -其中 `location-labels` 需要与 TiKV 的 `labels` 名字对应,这样 PD 才能知道这些 `labels` 代表了 TiKV 的拓扑结构。 - -> **注意:** -> -> 必须同时配置 PD 的 `location-labels` 和 TiKV 的 `labels` 参数,否则 `labels` 不会生效。 - -## PD 基于 TiKV 拓扑结构进行调度 - -PD 能够根据我们提供的拓扑信息作出最优的调度,我们只需要关心什么样的拓扑结构能够达到我们想要的效果。 - -假设我们使用三副本,并且希望一个数据中心挂掉的情况下,还能继续保持 TiDB 集群的高可用状态,我们至少需要四个数据中心。 - -假设我们有四个数据中心 (zone),每个数据中心有两个机架 (rack),每个机架上有两个主机 (host)。 -每个主机上面启动一个 TiKV 实例: - -``` -# zone=z1 -tikv-server --labels zone=z1,rack=r1,host=h1 -tikv-server --labels zone=z1,rack=r1,host=h2 -tikv-server --labels zone=z1,rack=r2,host=h1 -tikv-server --labels zone=z1,rack=r2,host=h2 - -# zone=z2 -tikv-server --labels zone=z2,rack=r1,host=h1 -tikv-server --labels zone=z2,rack=r1,host=h2 -tikv-server --labels zone=z2,rack=r2,host=h1 -tikv-server --labels zone=z2,rack=r2,host=h2 - -# zone=z3 -tikv-server --labels zone=z3,rack=r1,host=h1 -tikv-server --labels zone=z3,rack=r1,host=h2 -tikv-server --labels zone=z3,rack=r2,host=h1 -tikv-server --labels zone=z3,rack=r2,host=h2 - -# zone=z4 -tikv-server --labels zone=z4,rack=r1,host=h1 -tikv-server --labels zone=z4,rack=r1,host=h2 -tikv-server --labels zone=z4,rack=r2,host=h1 -tikv-server --labels zone=z4,rack=r2,host=h2 -``` - -也就是说,我们有 16 个 TiKV 实例,分布在 4 个不同的数据中心,8 个不同的机架,16 个不同的机器。 - -在这种拓扑结构下,PD 会优先把每一份数据的不同副本调度到不同的数据中心。 -这时候如果其中一个数据中心挂了,不会影响 TiDB 集群的高可用状态。 -如果这个数据中心一段时间内恢复不了,PD 会把这个数据中心的副本迁移出去。 - -总的来说,PD 能够根据当前的拓扑结构使得集群容灾能力最大化,所以如果我们希望达到某个级别的容灾能力, -就需要根据拓扑机构在不同的地理位置提供多于备份数 (`max-replicas`) 的机器。 diff --git a/how-to/deploy/geographic-redundancy/overview.md b/how-to/deploy/geographic-redundancy/overview.md deleted file mode 100644 index 80daae48a75e..000000000000 --- a/how-to/deploy/geographic-redundancy/overview.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: 跨数据中心部署方案 -category: how-to ---- - -# 跨数据中心部署方案 - -作为 NewSQL 数据库,TiDB 兼顾了传统关系型数据库的优秀特性以及 NoSQL 数据库可扩展性,以及跨数据中心(下文简称“中心”)场景下的高可用。本文档旨在介绍跨数据中心部署的不同解决方案。 - -## 三中心部署方案 - -TiDB, TiKV, PD 分别分布在 3 个不同的中心,这是最常规,可用性最高的方案。 - -![三中心部署](/media/deploy-3dc.png) - -### 优点 - -所有数据的副本分布在三个数据中心,任何一个数据中心失效后,另外两个数据中心会自动发起 leader election,并在合理长的时间内(通常情况 20s 以内)恢复服务,并且不会产生数据丢失。 - -![三中心部署容灾](/media/deploy-3dc-dr.png) - -### 缺点 - -性能受网络延迟影响。 - -- 对于写入的场景,所有写入的数据需要同步复制到至少 2 个数据中心,由于 TiDB 写入过程使用两阶段提交,故写入延迟至少需要 2 倍数据中心间的延迟。 -- 对于读请求来说,如果数据 leader 与发起读取的 TiDB 节点不在同一个数据中心,也会受网络延迟影响。 -- TiDB 中的每个事务都需要向 PD leader 获取 TSO,当 TiDB 与 PD leader 不在同一个数据中心时,它上面运行的事务也会因此受网络延迟影响,每个有写入的事务会获取两次 TSO。 - -### 读性能优化 - -如果不需要每个数据中心同时对外提供服务,可以将业务流量全部派发到一个数据中心,并通过调度策略把 Region leader 和 PD leader 都迁移到同一个数据中心(我们在上文所述的测试中也做了这个优化)。这样一来,不管是从 PD 获取 TSO 还是读取 Region 都不受数据中心间网络的影响。当该数据中心失效后,PD leader 和 Region leader 会自动在其它数据中心选出,只需要把业务流量转移至其他存活的数据中心即可。 - -![三中心部署读性能优化](/media/deploy-3dc-optimize.png) - -## 两地三中心部署方案 - -两地三中心的方案与三数据中心类似,算是三机房方案根据业务特点进行的优化,区别是其中有两个数据中心距离很近(通常在同一个城市),网络延迟相对很小。这种场景下,我们可以把业务流量同时派发到同城的两个数据中心,同时控制 Region leader 和 PD leader 也分布在同城的两个数据中心。 - -![两地三中心部署方案](/media/deploy-2city3dc.png) - -与三数据中心方案相比,两地三中心有以下优势: - -- 写入速度更优 -- 两中心同时提供服务资源利用率更高 -- 依然能保证任何一个数据中心失效后保持可用并且不发生数据丢失 - -但是,缺陷是如果同城的两个数据中心同时失效(理论上讲要高于异地三数据中心损失 2 个的概率),将会导致不可用以及部分数据丢失。 - -## 两数据中心 + binlog 同步方案 - -两数据中心 + binlog 同步类似于传统的 MySQL 中 master/slave 方案。两个数据中心分别部署一套完整的 TiDB 集群,我们称之为主集群和从集群。正常情况下所有的请求都在主集群,写入的数据通过 binlog 异步同步至从集群并写入。 - -![binlog 同步部署方案](/media/deploy-binlog.png) - -当主集群整个数据中心失效后,业务可以切换至从集群,与 MySQL 类似,这种情况下会有一些数据缺失。对比 MySQL,这个方案的优势是数据中心内的 HA -- 少部分节点故障时,通过重新选举 leader 自动恢复服务,不需要人工干预。 - -![两中心 binlog 相互备份方案](/media/deploy-backup.png) - -另外部分用户采用这种方式做双数据中心多活,两个数据中心各有一个集群,将业务分为两个库,每个库服务一部分数据,每个数据中心的业务只会访问一个库,两个集群之间通过 binlog 将本数据中心业务所涉及的库中的数据变更同步到对端机房,形成环状备份。 - -> **注意:** -> -> 在两数据中心 + binlog 同步部署方案中,数据中心之间只有 binlog 异步复制。在数据中心间的延迟较高的情况下,从集群落后主集群的数据量会增大。当主集群故障后(DR),会造成数据丢失,丢失的数据量受网络延迟等因素影响。 - -## 高可用和容灾分析 - -对于三数据中心方案和两地三中心方案,我们能得到的保障是任意一个数据中心故障时,集群能自动恢复服务,不需要人工介入,并能保证数据一致性。注意各种调度策略都是用于帮助性能优化的,当发生故障时调度机制总是第一优先考虑可用性而不是性能。 - -对于两数据中心 + binlog 同步的方案,主集群内少量节点故障时也能自动恢复服务,不需要人工介入,并能保证数据一致性。当整个主集群故障时,需要人工切换至从集群,并可能发生一些数据丢失,数据丢失的数量取决于同步延迟,和网络条件有关。 diff --git a/how-to/deploy/hardware-recommendations.md b/how-to/deploy/hardware-recommendations.md deleted file mode 100644 index 7d157a5486c6..000000000000 --- a/how-to/deploy/hardware-recommendations.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: TiDB 软件和硬件环境建议配置 -category: how-to ---- - -# TiDB 软件和硬件环境建议配置 - -TiDB 作为一款开源分布式 NewSQL 数据库,可以很好的部署和运行在 Intel 架构服务器环境及主流虚拟化环境,并支持绝大多数的主流硬件网络。作为一款高性能数据库系统,TiDB 支持主流的 Linux 操作系统环境。 - -## Linux 操作系统版本要求 - -| Linux 操作系统平台 | 版本 | -| :----------------------- | :----------: | -| Red Hat Enterprise Linux | 7.3 及以上 | -| CentOS | 7.3 及以上 | -| Oracle Enterprise Linux | 7.3 及以上 | -| Ubuntu LTS | 16.04 及以上 | - -> **注意:** -> -> - TiDB 只支持 Red Hat 兼容内核 (RHCK) 的 Oracle Enterprise Linux,不支持 Oracle Enterprise Linux 提供的 Unbreakable Enterprise Kernel。 -> - TiDB 在 CentOS 7.3 的环境下进行过大量的测试,同时社区也有很多该操作系统部署的最佳实践,因此,建议使用 CentOS 7.3 以上的 Linux 操作系统来部署 TiDB。 -> - 以上 Linux 操作系统可运行在物理服务器以及 VMware、KVM、XEN 主流虚拟化环境上。 - -## 服务器建议配置 - -TiDB 支持部署和运行在 Intel x86-64 架构的 64 位通用硬件服务器平台。对于开发,测试,及生产环境的服务器硬件配置有以下要求和建议: - -### 开发及测试环境 - -| **组件** | **CPU** | **内存** | **本地存储** | **网络** | **实例数量(最低要求)** | -| --- | --- | --- | --- | --- | --- | -| TiDB | 8核+ | 16 GB+ | 无特殊要求 | 千兆网卡 | 1(可与 PD 同机器) | -| PD | 4核+ | 8 GB+ | SAS, 200 GB+ | 千兆网卡 | 1(可与 TiDB 同机器) | -| TiKV | 8核+ | 32 GB+ | SSD, 200 GB+ | 千兆网卡 | 3 | - -> **注意:** -> -> - 验证测试环境中的 TiDB 和 PD 可以部署在同一台服务器上。 -> - 如进行性能相关的测试,避免采用低性能存储和网络硬件配置,防止对测试结果的正确性产生干扰。 -> - TiKV 的 SSD 盘推荐使用 NVME 接口以保证读写更快。 -> - 如果仅验证功能,建议使用 [Docker Compose 部署方案](/how-to/get-started/deploy-tidb-from-docker-compose.md)单机进行测试。 -> - TiDB 对于磁盘的使用以存放日志为主,因此在测试环境中对于磁盘类型和容量并无特殊要求。 - -### 生产环境 - -| **组件** | **CPU** | **内存** | **硬盘类型** | **网络** | **实例数量(最低要求)** | -| --- | --- | --- | --- | --- | --- | -| TiDB | 16核+ | 32 GB+ | SAS | 万兆网卡(2块最佳) | 2 | -| PD | 4核+ | 8 GB+ | SSD | 万兆网卡(2块最佳) | 3 | -| TiKV | 16核+ | 32 GB+ | SSD | 万兆网卡(2块最佳) | 3 | -| 监控 | 8核+ | 16 GB+ | SAS | 千兆网卡 | 1 | - -> **注意:** -> -> - 生产环境中的 TiDB 和 PD 可以部署和运行在同服务器上,如对性能和可靠性有更高的要求,应尽可能分开部署。 -> - 生产环境强烈推荐使用更高的配置。 -> - TiKV 硬盘大小配置建议 PCI-E SSD 不超过 2 TB,普通 SSD 不超过 1.5 TB。 - -## 网络要求 - -TiDB 作为开源分布式 NewSQL 数据库,其正常运行需要网络环境提供如下的网络端口配置要求,管理员可根据实际环境中 TiDB 组件部署的方案,在网络侧和主机侧开放相关端口: - -| 组件 | 默认端口 | 说明 | -| :-- | :-- | :-- | -| TiDB | 4000 | 应用及 DBA 工具访问通信端口 | -| TiDB | 10080 | TiDB 状态信息上报通信端口 | -| TiKV | 20160 | TiKV 通信端口 | -| PD | 2379 | 提供 TiDB 和 PD 通信端口 | -| PD | 2380 | PD 集群节点间通信端口 | -| Pump | 8250 | Pump 通信端口 | -| Drainer | 8249 | Drainer 通信端口 | -| Prometheus | 9090 | Prometheus 服务通信端口 | -| Pushgateway | 9091 | tikv-importer 聚合和上报端口 | -| Node_exporter | 9100 | TiDB 集群每个节点的系统信息上报通信端口 | -| Blackbox_exporter | 9115 | Blackbox_exporter 通信端口,用于 TiDB 集群端口监控 | -| Grafana | 3000 | Web 监控服务对外服务和客户端(浏览器)访问端口 | -| Grafana | 8686 | grafana_collector 通信端口,用于将 Dashboard 导出为 PDF 格式 | -| Kafka_exporter | 9308 | Kafka_exporter 通信端口,用于监控 binlog kafka 集群 | - -## 客户端 Web 浏览器要求 - -TiDB 提供了基于 [Grafana](https://grafana.com/) 的技术平台,对数据库集群的各项指标进行可视化展现。采用支持 Javascript 的微软 IE、Google Chrome、Mozilla Firefox 的较新版本即可访问监控入口。 diff --git a/how-to/deploy/orchestrated/ansible.md b/how-to/deploy/orchestrated/ansible.md deleted file mode 100644 index c69d2f94e615..000000000000 --- a/how-to/deploy/orchestrated/ansible.md +++ /dev/null @@ -1,968 +0,0 @@ ---- -title: 使用 TiDB Ansible 部署 TiDB 集群 -category: how-to ---- - -# 使用 TiDB Ansible 部署 TiDB 集群 - -## 概述 - -Ansible 是一款自动化运维工具,[TiDB Ansible](https://github.com/pingcap/tidb-ansible) 是 PingCAP 基于 Ansible playbook 功能编写的集群部署工具。本文档介绍如何使用 TiDB Ansible 部署一个完整的 TiDB 集群。 - -本部署工具可以通过配置文件设置集群拓扑,完成以下各项运维工作: - -- 初始化操作系统参数 -- 部署 TiDB 集群(包括 PD、TiDB、TiKV 等组件和监控组件) -- [启动集群](/how-to/maintain/ansible-operations.md#启动集群) -- [关闭集群](/how-to/maintain/ansible-operations.md#关闭集群) -- [变更组件配置](/how-to/upgrade/from-previous-version.md#编辑-tidb-集群组件配置文件) -- [集群扩容缩容](/how-to/scale/with-ansible.md) -- [升级组件版本](/how-to/upgrade/from-previous-version.md#滚动升级-tidb-集群组件) -- [集群开启 binlog](/reference/tidb-binlog/overview.md) -- [清除集群数据](/how-to/maintain/ansible-operations.md#清除集群数据) -- [销毁集群](/how-to/maintain/ansible-operations.md#销毁集群) - -> **注意:** -> -> 对于生产环境,须使用 TiDB Ansible 部署 TiDB 集群。如果只是用于测试 TiDB 或体验 TiDB 的特性,建议[使用 Docker Compose 在单机上快速部署 TiDB 集群](/how-to/get-started/deploy-tidb-from-docker-compose.md)。 - -## 准备机器 - -1. 部署目标机器若干 - - - 建议 4 台及以上,TiKV 至少 3 实例,且与 TiDB、PD 模块不位于同一主机,详见[部署建议](/how-to/deploy/hardware-recommendations.md)。 - - 目前支持在 x86_64 (AMD64) 和 ARM64 两种架构上部署 TiDB 集群。在 AMD64 架构下,建议使用 CentOS 7.3 及以上版本 Linux 操作系统;在 ARM 架构下,建议使用 CentOS 7.6 1810 版本 Linux 操作系统。 - - 机器之间内网互通。 - - > **注意:** - > - > 使用 TiDB Ansible 方式部署时,TiKV 及 PD 节点数据目录所在磁盘请使用 SSD 磁盘,否则无法通过检测。**如果仅验证功能,建议使用 [Docker Compose 部署方案](/how-to/get-started/deploy-tidb-from-docker-compose.md)单机进行测试。** - -2. 部署中控机一台 - - - 中控机可以是部署目标机器中的某一台。 - - 推荐安装 CentOS 7.3 及以上版本 Linux 操作系统(默认包含 Python 2.7)。 - - 该机器需开放外网访问,用于下载 TiDB 及相关软件安装包。 - -## 第 1 步:在中控机上安装系统依赖包 - -以 `root` 用户登录中控机,然后根据操作系统类型执行相应的安装命令。 - -- 如果中控机使用的是 CentOS 7 系统,执行以下命令: - - {{< copyable "shell-root" >}} - - ```bash - yum -y install epel-release git curl sshpass && \ - yum -y install python2-pip - ``` - -- 如果中控机使用的是 Ubuntu 系统,执行以下命令: - - {{< copyable "shell-root" >}} - - ```bash - apt-get -y install git curl sshpass python-pip - ``` - -## 第 2 步:在中控机上创建 `tidb` 用户,并生成 SSH key - -以 `root` 用户登录中控机,执行以下步骤: - -1. 创建 `tidb` 用户。 - - {{< copyable "shell-root" >}} - - ```bash - useradd -m -d /home/tidb tidb - ``` - -2. 设置 `tidb` 用户密码。 - - {{< copyable "shell-root" >}} - - ```bash - passwd tidb - ``` - -3. 配置 `tidb` 用户 sudo 免密码,将 `tidb ALL=(ALL) NOPASSWD: ALL` 添加到文件末尾即可。 - - {{< copyable "shell-root" >}} - - ```bash - visudo - ``` - - ``` - tidb ALL=(ALL) NOPASSWD: ALL - ``` - -4. 生成 SSH key。 - - 执行 `su` 命令,从 `root` 用户切换到 `tidb` 用户下。 - - {{< copyable "shell-root" >}} - - ```bash - su - tidb - ``` - - 创建 `tidb` 用户 SSH key,提示 `Enter passphrase` 时直接回车即可。执行成功后,SSH 私钥文件为 `/home/tidb/.ssh/id_rsa`,SSH 公钥文件为 `/home/tidb/.ssh/id_rsa.pub`。 - - {{< copyable "shell-regular" >}} - - ```bash - ssh-keygen -t rsa - ``` - - ``` - Generating public/private rsa key pair. - Enter file in which to save the key (/home/tidb/.ssh/id_rsa): - Created directory '/home/tidb/.ssh'. - Enter passphrase (empty for no passphrase): - Enter same passphrase again: - Your identification has been saved in /home/tidb/.ssh/id_rsa. - Your public key has been saved in /home/tidb/.ssh/id_rsa.pub. - The key fingerprint is: - SHA256:eIBykszR1KyECA/h0d7PRKz4fhAeli7IrVphhte7/So tidb@172.16.10.49 - The key's randomart image is: - +---[RSA 2048]----+ - |=+o+.o. | - |o=o+o.oo | - | .O.=.= | - | . B.B + | - |o B * B S | - | * + * + | - | o + . | - | o E+ . | - |o ..+o. | - +----[SHA256]-----+ - ``` - -## 第 3 步:在中控机器上下载 TiDB Ansible - -以 `tidb` 用户登录中控机并进入 `/home/tidb` 目录。使用以下命令从 [TiDB Ansible 项目](https://github.com/pingcap/tidb-ansible)上下载 master 分支的 TiDB Ansible,默认的文件夹名称为 `tidb-ansible`。 - -{{< copyable "shell-regular" >}} - -```bash -git clone https://github.com/pingcap/tidb-ansible.git -``` - -> **注意:** -> -> - 部署和升级 TiDB 集群需使用对应的 tidb-ansible 版本,通过改 `inventory.ini` 文件中的版本来混用可能会产生一些错误。 -> - 请务必按文档操作,将 `tidb-ansible` 下载到 `/home/tidb` 目录下,权限为 `tidb` 用户,不要下载到 `/root` 下,否则会遇到权限问题。 - -## 第 4 步:在中控机器上安装 TiDB Ansible 及其依赖 - -以 `tidb` 用户登录中控机,请务必按以下方式通过 `pip` 安装 TiDB Ansible 及其相关依赖的指定版本,否则会有兼容问题。目前,TiDB release-2.0、release-2.1、release-3.0、release-3.1 以及最新开发版本兼容 Ansible 2.4 ~ 2.7.11 (2.4 ≤ Ansible ≤ 2.7.11)。 - -1. 在中控机器上安装 TiDB Ansible 及其依赖。 - - {{< copyable "shell-regular" >}} - - ```bash - cd /home/tidb/tidb-ansible && \ - sudo pip install -r ./requirements.txt - ``` - - Ansible 及相关依赖的版本信息记录在 `tidb-ansible/requirements.txt` 文件中。 - -2. 查看 Ansible 的版本。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible --version - ``` - - ``` - ansible 2.7.11 - ``` - -## 第 5 步:在中控机上配置部署机器 SSH 互信及 sudo 规则 - -以 `tidb` 用户登录中控机,然后执行以下步骤: - -1. 将你的部署目标机器 IP 添加到 `hosts.ini` 文件的 `[servers]` 区块下。 - - {{< copyable "shell-regular" >}} - - ```bash - cd /home/tidb/tidb-ansible && \ - vi hosts.ini - ``` - - ```ini - [servers] - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - 172.16.10.4 - 172.16.10.5 - 172.16.10.6 - - [all:vars] - username = tidb - ntp_server = pool.ntp.org - ``` - -2. 执行以下命令,按提示输入部署目标机器的 `root` 用户密码。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook -i hosts.ini create_users.yml -u root -k - ``` - - 该步骤将在部署目标机器上创建 `tidb` 用户,并配置 sudo 规则,配置中控机与部署目标机器之间的 SSH 互信。 - -如果要手工配置 SSH 互信及 sudo 免密码,可参考[如何手工配置 ssh 互信及 sudo 免密码](#如何手工配置-ssh-互信及-sudo-免密码)。 - -## 第 6 步:在部署目标机器上安装 NTP 服务 - -> **注意:** -> -> 如果你的部署目标机器时间、时区设置一致,已开启 NTP 服务且在正常同步时间,此步骤可忽略。可参考[如何检测 NTP 服务是否正常](#如何检测-ntp-服务是否正常)。 - -以 `tidb` 用户登录中控机,执行以下命令: - -{{< copyable "shell-regular" >}} - -```bash -cd /home/tidb/tidb-ansible && \ -ansible-playbook -i hosts.ini deploy_ntp.yml -u tidb -b -``` - -该步骤将在部署目标机器上使用系统自带软件源联网安装并启动 NTP 服务,服务使用安装包默认的 NTP server 列表,见配置文件 `/etc/ntp.conf` 中 server 参数。如果使用默认的 NTP server,你的机器需要连接外网。 - -为了让 NTP 尽快开始同步,启动 NTP 服务前,系统会执行 `ntpdate` 命令,与用户在 `hosts.ini` 文件中指定的 `ntp_server` 同步日期与时间。默认的服务器为 `pool.ntp.org`,也可替换为你的 NTP server。 - -## 第 7 步:在部署目标机器上配置 CPUfreq 调节器模式 - -为了让 CPU 发挥最大性能,请将 CPUfreq 调节器模式设置为 `performance` 模式。如需了解 CPUfreq 的更多信息,可查看[使用 CPUFREQ 调控器](https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/power_management_guide/cpufreq_governors#cpufreq_setup)文档。 - -### 查看系统支持的调节器模式 - -执行以下 `cpupower` 命令,可查看系统支持的调节器模式: - -{{< copyable "shell-root" >}} - -```bash -cpupower frequency-info --governors -``` - -``` -analyzing CPU 0: - available cpufreq governors: performance powersave -``` - -> **注意:** -> -> 本例中系统支持设置 `performance` 和 `powersave` 模式。如果返回 `Not Available`,表示当前系统不支持配置 CPUfreq,跳过该步骤即可。 - -{{< copyable "shell-root" >}} - -```bash -cpupower frequency-info --governors -``` - -``` -analyzing CPU 0: - available cpufreq governors: Not Available -``` - -### 查看系统当前的 CPUfreq 调节器模式 - -执行以下 `cpupower` 命令,可查看系统当前的 CPUfreq 调节器模式: - -{{< copyable "shell-root" >}} - -```bash -cpupower frequency-info --policy -``` - -``` -analyzing CPU 0: - current policy: frequency should be within 1.20 GHz and 3.20 GHz. - The governor "powersave" may decide which speed to use - within this range. -``` - -如上述代码所示,本例中的当前配置是 `powersave` 模式。 - -### 修改调节器模式 - -你可以通过以下两种方法来修改调节器模式。本例中,当前调节器模式为 `powersave`,以下命令会将模式变更为 `performance`。 - -- 使用 `cpupower frequency-set --governor` 命令来修改。 - - {{< copyable "shell-root" >}} - - ```bash - cpupower frequency-set --governor performance - ``` - -- 使用以下命令在部署目标机器上批量设置。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible -i hosts.ini all -m shell -a "cpupower frequency-set --governor performance" -u tidb -b - ``` - -## 第 8 步:在部署目标机器上添加数据盘 ext4 文件系统挂载参数 - -使用 `root` 用户登录目标机器,将部署目标机器数据盘格式化成 ext4 文件系统,挂载时添加 `nodelalloc` 和 `noatime` 挂载参数。`nodelalloc` 是必选参数,否则 Ansible 安装时检测无法通过;`noatime` 是可选建议参数。 - -> **注意:** -> -> 如果你的数据盘已经格式化成 ext4 并挂载了磁盘,可先执行 `umount /dev/nvme0n1p1` 命令卸载,从编辑 `/etc/fstab` 文件步骤开始执行,添加挂载参数重新挂载即可。 - -以 `/dev/nvme0n1` 数据盘为例,具体操作步骤如下: - -1. 查看数据盘。 - - {{< copyable "shell-root" >}} - - ```bash - fdisk -l - ``` - - ``` - Disk /dev/nvme0n1: 1000 GB - ``` - -2. 创建分区表。 - - {{< copyable "shell-root" >}} - - ```bash - parted -s -a optimal /dev/nvme0n1 mklabel gpt -- mkpart primary ext4 1 -1 - ``` - - > **注意:** - > - > 使用 `lsblk` 命令查看分区的设备号:对于 nvme 磁盘,生成的分区设备号一般为 `nvme0n1p1`;对于普通磁盘(例如 `/dev/sdb`),生成的的分区设备号一般为 `sdb1`。 - -3. 格式化文件系统。 - - {{< copyable "shell-root" >}} - - ```bash - mkfs.ext4 /dev/nvme0n1p1 - ``` - -4. 查看数据盘分区 UUID。 - - 本例中 `nvme0n1p1` 的 UUID 为 `c51eb23b-195c-4061-92a9-3fad812cc12f`。 - - {{< copyable "shell-root" >}} - - ```bash - lsblk -f - ``` - - ``` - NAME FSTYPE LABEL UUID MOUNTPOINT - sda - ├─sda1 ext4 237b634b-a565-477b-8371-6dff0c41f5ab /boot - ├─sda2 swap f414c5c0-f823-4bb1-8fdf-e531173a72ed - └─sda3 ext4 547909c1-398d-4696-94c6-03e43e317b60 / - sr0 - nvme0n1 - └─nvme0n1p1 ext4 c51eb23b-195c-4061-92a9-3fad812cc12f - ``` - -5. 编辑 `/etc/fstab` 文件,添加 `nodelalloc` 挂载参数。 - - {{< copyable "shell-root" >}} - - ```bash - vi /etc/fstab - ``` - - ``` - UUID=c51eb23b-195c-4061-92a9-3fad812cc12f /data1 ext4 defaults,nodelalloc,noatime 0 2 - ``` - -6. 挂载数据盘。 - - {{< copyable "shell-root" >}} - - ```bash - mkdir /data1 && \ - mount -a - ``` - -7. 执行以下命令,如果文件系统为 ext4,并且挂载参数中包含 `nodelalloc`,则表示已生效。 - - {{< copyable "shell-root" >}} - - ```bash - mount -t ext4 - ``` - - ``` - /dev/nvme0n1p1 on /data1 type ext4 (rw,noatime,nodelalloc,data=ordered) - ``` - -## 第 9 步:编辑 `inventory.ini` 文件,分配机器资源 - -以 `tidb` 用户登录中控机,编辑 `/home/tidb/tidb-ansible/inventory.ini` 文件为 TiDB 集群分配机器资源。一个标准的 TiDB 集群需要 6 台机器:2 个 TiDB 实例,3 个 PD 实例,3 个 TiKV 实例。 - -- 至少需部署 3 个 TiKV 实例。 -- 不要将 TiKV 实例与 TiDB 或 PD 实例混合部署在同一台机器上。 -- 将第一台 TiDB 机器同时用作监控机。 - -> **注意:** -> -> 请使用内网 IP 来部署集群,如果部署目标机器 SSH 端口非默认的 22 端口,需添加 `ansible_port` 变量,如 `TiDB1 ansible_host=172.16.10.1 ansible_port=5555`。 -> -> 如果是 ARM 架构的机器,需要将 `cpu_architecture` 改为 `arm64`。 - -你可以根据实际场景从以下两种集群拓扑中选择一种: - -- [单机单 TiKV 实例集群拓扑](#单机单-tikv-实例集群拓扑) - - 默认情况下,建议在每个 TiKV 节点上仅部署一个 TiKV 实例,以提高性能。但是,如果你的 TiKV 部署机器的 CPU 和内存配置是[部署建议](/how-to/deploy/hardware-recommendations.md)的两倍或以上,并且一个节点拥有两块 SSD 硬盘或者单块 SSD 硬盘的容量大于 2 TB,则可以考虑部署两实例,但不建议部署两个以上实例。 - -- [单机多 TiKV 实例集群拓扑](#单机多-tikv-实例集群拓扑) - -### 单机单 TiKV 实例集群拓扑 - -| Name | Host IP | Services | -| :---- | :------- | :-------- | -| node1 | 172.16.10.1 | PD1, TiDB1 | -| node2 | 172.16.10.2 | PD2, TiDB2 | -| node3 | 172.16.10.3 | PD3 | -| node4 | 172.16.10.4 | TiKV1 | -| node5 | 172.16.10.5 | TiKV2 | -| node6 | 172.16.10.6 | TiKV3 | - -```ini -[tidb_servers] -172.16.10.1 -172.16.10.2 - -[pd_servers] -172.16.10.1 -172.16.10.2 -172.16.10.3 - -[tikv_servers] -172.16.10.4 -172.16.10.5 -172.16.10.6 - -[monitoring_servers] -172.16.10.1 - -[grafana_servers] -172.16.10.1 - -[monitored_servers] -172.16.10.1 -172.16.10.2 -172.16.10.3 -172.16.10.4 -172.16.10.5 -172.16.10.6 -``` - -### 单机多 TiKV 实例集群拓扑 - -以两实例为例: - -| Name | Host IP | Services | -| :---- | :------- | :-------- | -| node1 | 172.16.10.1 | PD1, TiDB1 | -| node2 | 172.16.10.2 | PD2, TiDB2 | -| node3 | 172.16.10.3 | PD3 | -| node4 | 172.16.10.4 | TiKV1-1, TiKV1-2 | -| node5 | 172.16.10.5 | TiKV2-1, TiKV2-2 | -| node6 | 172.16.10.6 | TiKV3-1, TiKV3-2 | - -```ini -[tidb_servers] -172.16.10.1 -172.16.10.2 - -[pd_servers] -172.16.10.1 -172.16.10.2 -172.16.10.3 - -# 注意:要使用 TiKV 的 labels,必须同时配置 PD 的 location_labels 参数,否则 labels 设置不生效。 -[tikv_servers] -TiKV1-1 ansible_host=172.16.10.4 deploy_dir=/data1/deploy tikv_port=20171 labels="host=tikv1" -TiKV1-2 ansible_host=172.16.10.4 deploy_dir=/data2/deploy tikv_port=20172 labels="host=tikv1" -TiKV2-1 ansible_host=172.16.10.5 deploy_dir=/data1/deploy tikv_port=20171 labels="host=tikv2" -TiKV2-2 ansible_host=172.16.10.5 deploy_dir=/data2/deploy tikv_port=20172 labels="host=tikv2" -TiKV3-1 ansible_host=172.16.10.6 deploy_dir=/data1/deploy tikv_port=20171 labels="host=tikv3" -TiKV3-2 ansible_host=172.16.10.6 deploy_dir=/data2/deploy tikv_port=20172 labels="host=tikv3" - -# 部署 3.0 版本的 TiDB 集群时,多实例场景需要额外配置 status 端口,示例如下: -# TiKV1-1 ansible_host=172.16.10.4 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv1" -# TiKV1-2 ansible_host=172.16.10.4 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv1" -# TiKV2-1 ansible_host=172.16.10.5 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv2" -# TiKV2-2 ansible_host=172.16.10.5 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv2" -# TiKV3-1 ansible_host=172.16.10.6 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv3" -# TiKV3-2 ansible_host=172.16.10.6 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv3" - -[monitoring_servers] -172.16.10.1 - -[grafana_servers] -172.16.10.1 - -[monitored_servers] -172.16.10.1 -172.16.10.2 -172.16.10.3 -172.16.10.4 -172.16.10.5 -172.16.10.6 - -# 注意:为使 TiKV 的 labels 设置生效,部署集群时必须设置 PD 的 location_labels 参数。 -[pd_servers:vars] -location_labels = ["host"] -``` - -- 服务配置文件参数调整 - - 1. 多实例情况下,需要修改 `tidb-ansible/conf/tikv.yml` 中 `block-cache-size` 下面的 `capacity` 参数: - - ```yaml - storage: - block-cache: - capacity: "1GB" - ``` - - > **注意:** - > - > TiKV 实例数量指每个服务器上 TiKV 的进程数量。 - > - > 推荐设置:`capacity` = MEM_TOTAL * 0.5 / TiKV 实例数量 - - 2. 多实例情况下,需要修改 `tidb-ansible/conf/tikv.yml` 中 `high-concurrency`、`normal-concurrency` 和 `low-concurrency` 三个参数: - - ```yaml - readpool: - coprocessor: - # Notice: if CPU_NUM > 8, default thread pool size for coprocessors - # will be set to CPU_NUM * 0.8. - # high-concurrency: 8 - # normal-concurrency: 8 - # low-concurrency: 8 - ``` - - > **注意:** - > - > 推荐设置:TiKV 实例数量 \* 参数值 = CPU 核心数量 \* 0.8 - - 3. 如果多个 TiKV 实例部署在同一块物理磁盘上,需要修改 `conf/tikv.yml` 中的 `capacity` 参数: - - ```yaml - raftstore: - capacity: 0 - ``` - - > **注意:** - > - > 推荐配置:`capacity` = 磁盘总容量 / TiKV 实例数量 - > - > 例如:`capacity: "100GB"` - -## 第 10 步:调整 `inventory.ini` 文件中的变量 - -本小节介绍如何编辑部署目录的变量和 `inventory.ini` 文件中的其它变量。 - -### 调整部署目录 - -部署目录通过 `deploy_dir` 变量控制,默认全局变量已设置为 `/home/tidb/deploy`,对所有服务生效。如数据盘挂载目录为 `/data1`,可设置为 `/data1/deploy`,样例如下: - -```ini -## Global variables -[all:vars] -deploy_dir = /data1/deploy -``` - -如为某一服务单独设置部署目录,可在配置服务主机列表时配置主机变量,以 TiKV 节点为例,其他服务类推,请务必添加第一列别名,以免服务混布时混淆。 - -```ini -TiKV1-1 ansible_host=172.16.10.4 deploy_dir=/data1/deploy -``` - -### 调整其它变量(可选) - -> **注意:** -> -> 以下控制变量开启请使用首字母大写 `True`,关闭请使用首字母大写 `False`。 - -| 变量 | 含义 | -| :--------------- | :-------------------------------------------------------- | -| `cluster_name` | 集群名称,可调整 | -| `cpu_architecture` | CPU 体系架构,默认为 `amd64`,可选 `arm64` | -| `tidb_version` | TiDB 版本,TiDB Ansible 各分支默认已配置 | -| `process_supervision` | 进程监管方式,默认为 `systemd`,可选 `supervise` | -| `timezone` | 新安装 TiDB 集群第一次启动 bootstrap(初始化)时,将 TiDB 全局默认时区设置为该值。TiDB 使用的时区后续可通过 `time_zone` 全局变量和 session 变量来修改,参考[时区支持](/how-to/configure/time-zone.md)。默认为 `Asia/Shanghai`,可选值参考 [timzone 列表](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)。 | -| `enable_firewalld` | 开启防火墙,默认不开启,如需开启,请将[部署建议-网络要求](/how-to/deploy/hardware-recommendations.md#网络要求) 中的端口加入白名单 | -| `enable_ntpd` | 检测部署目标机器 NTP 服务,默认为 `True`,请勿关闭 | -| `set_hostname` | 根据 IP 修改部署目标机器主机名,默认为 `False` | -| `enable_binlog` | 是否部署 Pump 并开启 binlog,默认为 `False`,依赖 Kafka 集群,参见 `zookeeper_addrs` 变量 | -| `zookeeper_addrs` | binlog Kafka 集群的 zookeeper 地址 | -| `deploy_without_tidb` | KV 模式,不部署 TiDB 服务,仅部署 PD、TiKV 及监控服务,请将 `inventory.ini` 文件中 `tidb_servers` 主机组 IP 设置为空。| -| `alertmanager_target` | 可选:如果你已单独部署 alertmanager,可配置该变量,格式:`alertmanager_host:alertmanager_port` | -| `grafana_admin_user` | Grafana 管理员帐号用户名,默认为 admin | -| `grafana_admin_password` | Grafana 管理员帐号密码,默认为 admin,用于 Ansible 导入 Dashboard 和创建 API Key,如后期通过 grafana web 修改了密码,请更新此变量 | -| `collect_log_recent_hours` | 采集日志时,采集最近几个小时的日志,默认为 2 小时 | -| `enable_bandwidth_limit` | 在中控机上从部署目标机器拉取诊断数据时,是否限速,默认为 `True`,与 `collect_bandwidth_limit` 变量结合使用 | -| `collect_bandwidth_limit` | 在中控机上从部署目标机器拉取诊断数据时限速多少,单位: Kbit/s,默认 10000,即 10Mb/s,如果是单机多 TiKV 实例部署方式,需除以单机实例个数 | -| `prometheus_storage_retention` | Prometheus 监控数据的保留时间(默认为 30 天);2.1.7、3.0 以及之后的 tidb-ansible 版本中,`group_vars/monitoring_servers.yml` 文件里新增的配置 | - -## 第 11 步:部署 TiDB 集群 - -`ansible-playbook` 执行 Playbook 时,默认并发为 5。部署目标机器较多时,可添加 `-f` 参数指定并发数,例如 `ansible-playbook deploy.yml -f 10`。以下示例使用 `tidb` 用户作为服务运行用户: - -1. 在 `tidb-ansible/inventory.ini` 文件中,确认 `ansible_user = tidb`。 - - ```ini - ## Connection - # ssh via normal user - ansible_user = tidb - ``` - - > **注意:** - > - > 不要将 `ansible_user` 设置为 `root` 用户,因为 `tidb-ansible` 限制了服务以普通用户运行。 - - 执行以下命令,如果所有 server 均返回 `tidb`,表示 SSH 互信配置成功: - - {{< copyable "shell-regular" >}} - - ```bash - ansible -i inventory.ini all -m shell -a 'whoami' - ``` - - 执行以下命令,如果所有 server 均返回 `root`,表示 `tidb` 用户 sudo 免密码配置成功。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible -i inventory.ini all -m shell -a 'whoami' -b - ``` - -2. 执行 `local_prepare.yml` playbook,联网下载 TiDB binary 至中控机。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook local_prepare.yml - ``` - -3. 初始化系统环境,修改内核参数。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook bootstrap.yml - ``` - -4. 部署 TiDB 集群软件。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook deploy.yml - ``` - - > **注意:** - > - > Grafana Dashboard 上的 **Report** 按钮可用来生成 PDF 文件,此功能依赖 `fontconfig` 包和英文字体。如需使用该功能,登录 **grafana_servers** 机器,用以下命令安装: - > - > {{< copyable "shell-regular" >}} - > - > ```bash - > sudo yum install fontconfig open-sans-fonts - > ``` - -5. 启动 TiDB 集群。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook start.yml - ``` - -## 测试集群 - -TiDB 兼容 MySQL,因此可使用 MySQL 客户端直接连接 TiDB。推荐配置负载均衡以提供统一的 SQL 接口。 - -1. 使用 MySQL 客户端连接 TiDB 集群。TiDB 服务的默认端口为 `4000`。 - - {{< copyable "sql" >}} - - ```sql - mysql -u root -h 172.16.10.1 -P 4000 - ``` - -2. 通过浏览器访问监控平台。 - - - 地址: - - 默认帐号与密码:`admin`;`admin` - -## 常见部署问题 - -本小节介绍使用 TiDB Ansible 部署 TiDB 集群过程中的常见问题与解决方案。 - -### 如何自定义端口 - -修改 `inventory.ini` 文件,在相应服务 IP 后添加以下主机变量即可: - -| 组件 | 端口变量 | 默认端口 | 说明 | -| :-- | :-- | :-- | :-- | -| TiDB | tidb_port | 4000 | 应用及 DBA 工具访问通信端口 | -| TiDB | tidb_status_port | 10080 | TiDB 状态信息上报通信端口 | -| TiKV | tikv_port | 20160 | TiKV 通信端口 | -| TiKV | tikv_status_port | 20180 | 上报 TiKV 状态的通信端口 | -| PD | pd_client_port | 2379 | 提供 TiDB 和 PD 通信端口 | -| PD | pd_peer_port | 2380 | PD 集群节点间通信端口 | -| Pump | pump_port | 8250 | Pump 通信端口 | -| Prometheus | prometheus_port | 9090 | Prometheus 服务通信端口 | -| Pushgateway | pushgateway_port | 9091 | TiDB, TiKV, PD 监控聚合和上报端口 | -| Node_exporter | node_exporter_port | 9100 | TiDB 集群每个节点的系统信息上报通信端口 | -| Blackbox_exporter | blackbox_exporter_port | 9115 | Blackbox_exporter 通信端口,用于 TiDB 集群端口监控 | -| Grafana | grafana_port | 3000 | Web 监控服务对外服务和客户端(浏览器)访问端口 | -| Kafka_exporter | kafka_exporter_port | 9308 | Kafka_exporter 通信端口,用于监控 binlog Kafka 集群 | - -### 如何自定义部署目录 - -修改 `inventory.ini` 文件,在相应服务 IP 后添加以下主机变量即可: - -| 组件 | 目录变量 | 默认目录 | 说明 | -| :-- | :-- | :-- | :-- | -| 全局 | deploy_dir | /home/tidb/deploy | 部署目录 | -| TiDB | tidb_log_dir | {{ deploy_dir }}/log | 日志目录 | -| TiKV | tikv_log_dir | {{ deploy_dir }}/log | 日志目录 | -| TiKV | tikv_data_dir | {{ deploy_dir }}/data | 数据目录 | -| TiKV | wal_dir | "" | rocksdb write-ahead 日志目录,为空时与 TiKV 数据目录一致 | -| TiKV | raftdb_path | "" | raftdb 目录,为空时为 tikv_data_dir/raft | -| PD | pd_log_dir | {{ deploy_dir }}/log | 日志目录 | -| PD | pd_data_dir | {{ deploy_dir }}/data.pd | 数据目录 | -| pump | pump_log_dir | {{ deploy_dir }}/log | 日志目录 | -| pump | pump_data_dir | {{ deploy_dir }}/data.pump | 数据目录 | -| prometheus | prometheus_log_dir | {{ deploy_dir }}/log | 日志目录 | -| prometheus | prometheus_data_dir | {{ deploy_dir }}/data.metrics | 数据目录 | -| pushgateway | pushgateway_log_dir | {{ deploy_dir }}/log | 日志目录 | -| node_exporter | node_exporter_log_dir | {{ deploy_dir }}/log | 日志目录 | -| grafana | grafana_log_dir | {{ deploy_dir }}/log | 日志目录 | -| grafana | grafana_data_dir | {{ deploy_dir }}/data.grafana | 数据目录 | - -### 如何检测 NTP 服务是否正常 - -1. 执行以下命令,如果输出 `running` 表示 NTP 服务正在运行: - - {{< copyable "shell-regular" >}} - - ```bash - sudo systemctl status ntpd.service - ``` - - ``` - ntpd.service - Network Time Service - Loaded: loaded (/usr/lib/systemd/system/ntpd.service; disabled; vendor preset: disabled) - Active: active (running) since 一 2017-12-18 13:13:19 CST; 3s ago - ``` - -2. 执行 `ntpstat` 命令,如果输出 `synchronised to NTP server`(正在与 NTP server 同步),表示在正常同步: - - {{< copyable "shell-regular" >}} - - ```bash - ntpstat - ``` - - ``` - synchronised to NTP server (85.199.214.101) at stratum 2 - time correct to within 91 ms - polling server every 1024 s - ``` - -> **注意:** -> -> Ubuntu 系统需安装 `ntpstat` 软件包。 - -- 以下情况表示 NTP 服务未正常同步: - - {{< copyable "shell-regular" >}} - - ```bash - ntpstat - ``` - - ``` - unsynchronised - ``` - -- 以下情况表示 NTP 服务未正常运行: - - {{< copyable "shell-regular" >}} - - ```bash - ntpstat - ``` - - ``` - Unable to talk to NTP daemon. Is it running? - ``` - -- 如果要使 NTP 服务尽快开始同步,执行以下命令。可以将 `pool.ntp.org` 替换为你的 NTP server: - - {{< copyable "shell-regular" >}} - - ```bash - sudo systemctl stop ntpd.service && \ - sudo ntpdate pool.ntp.org && \ - sudo systemctl start ntpd.service - ``` - -- 如果要在 CentOS 7 系统上手动安装 NTP 服务,可执行以下命令: - - {{< copyable "shell-regular" >}} - - ```bash - sudo yum install ntp ntpdate && \ - sudo systemctl start ntpd.service && \ - sudo systemctl enable ntpd.service - ``` - -### 如何调整进程监管方式从 supervise 到 systemd - -{{< copyable "shell-root" >}} - -```shell -process supervision, [systemd, supervise] -``` - -``` -process_supervision = systemd -``` - -TiDB Anisble 在 TiDB v1.0.4 版本之前进程监管方式默认为 `supervise`。之前安装的集群可保持不变,如需更新为 `systemd`,需关闭集群,按以下方式变更: - -{{< copyable "shell-regular" >}} - -```bash -ansible-playbook stop.yml && \ -ansible-playbook deploy.yml -D && \ -ansible-playbook start.yml -``` - -### 如何手工配置 SSH 互信及 sudo 免密码 - -1. 以 `root` 用户依次登录到部署目标机器创建 `tidb` 用户并设置登录密码。 - - {{< copyable "shell-root" >}} - - ```bash - useradd tidb && \ - passwd tidb - ``` - -2. 执行以下命令,将 `tidb ALL=(ALL) NOPASSWD: ALL` 添加到文件末尾,即配置好 sudo 免密码。 - - {{< copyable "shell-root" >}} - - ```bash - visudo - ``` - - ``` - tidb ALL=(ALL) NOPASSWD: ALL - ``` - -3. 以 `tidb` 用户登录到中控机,执行以下命令。将 `172.16.10.61` 替换成你的部署目标机器 IP,按提示输入部署目标机器 `tidb` 用户密码,执行成功后即创建好 SSH 互信,其他机器同理。 - - {{< copyable "shell-regular" >}} - - ```bash - ssh-copy-id -i ~/.ssh/id_rsa.pub 172.16.10.61 - ``` - -4. 以 `tidb` 用户登录中控机,通过 `ssh` 的方式登录目标机器 IP。如果不需要输入密码并登录成功,即表示 SSH 互信配置成功。 - - {{< copyable "shell-regular" >}} - - ```bash - ssh 172.16.10.61 - ``` - - ``` - [tidb@172.16.10.61 ~]$ - ``` - -5. 以 `tidb` 用户登录到部署目标机器后,执行以下命令,不需要输入密码并切换到 `root` 用户,表示 `tidb` 用户 sudo 免密码配置成功。 - - {{< copyable "shell-regular" >}} - - ```bash - sudo -su root - ``` - - ``` - [root@172.16.10.61 tidb]# - ``` - -### You need to install jmespath prior to running json_query filter 报错 - -1. 请参照[在中控机器上安装 TiDB Ansible 及其依赖](#在中控机器上安装-tidb-ansible-及其依赖) 在中控机上通过 `pip` 安装 TiDB Ansible 及相关依赖的指定版本,默认会安装 `jmespath`。 - -2. 执行以下命令,验证 `jmespath` 是否安装成功: - - {{< copyable "shell-regular" >}} - - ```bash - pip show jmespath - ``` - - ``` - Name: jmespath - Version: 0.9.0 - ``` - -3. 在中控机上 Python 交互窗口里执行 `import jmespath`。 - - - 如果没有报错,表示依赖安装成功。 - - 如果有 `ImportError: No module named jmespath` 报错,表示未成功安装 Python `jmespath` 模块。 - - {{< copyable "shell-regular" >}} - - ```bash - python - ``` - - ``` - Python 2.7.5 (default, Nov 6 2016, 00:28:07) - [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux2 - Type "help", "copyright", "credits" or "license" for more information. - ``` - - {{< copyable "shell-regular" >}} - - ```shell - import jmespath - ``` - -### 启动 Pump/Drainer 报 `zk: node does not exist` 错误 - -请检查 `inventory.ini` 里的 `zookeeper_addrs` 参数配置与 Kafka 集群内的配置是否相同、是否填写了命名空间。关于命名空间的配置说明如下: - -```ini -# ZooKeeper connection string (see ZooKeeper docs for details). -# ZooKeeper address of Kafka cluster, example: -# zookeeper_addrs = "192.168.0.11:2181,192.168.0.12:2181,192.168.0.13:2181" -# You can also append an optional chroot string to the URLs to specify the root directory for all Kafka znodes. Example: -# zookeeper_addrs = "192.168.0.11:2181,192.168.0.12:2181,192.168.0.13:2181/kafka/123" -``` diff --git a/how-to/deploy/orchestrated/docker.md b/how-to/deploy/orchestrated/docker.md deleted file mode 100644 index e53804e3c2a4..000000000000 --- a/how-to/deploy/orchestrated/docker.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -title: TiDB Docker 部署方案 -category: how-to ---- - -# TiDB Docker 部署方案 - -本文介绍如何使用 Docker 部署一个多节点的 TiDB 集群。 - -> **警告:** -> -> 对于生产环境,不要使用 Docker 进行部署,而应[使用 TiDB Ansible 部署 TiDB 集群](/how-to/deploy/orchestrated/ansible.md)。 - -## 环境准备 - -### 安装 Docker - -Docker 可以方便地在 Linux / Mac OS / Windows 平台安装,安装方法请参考 [Docker 官方文档](https://www.docker.com/products/docker)。 - -### 拉取 TiDB 的 Docker 镜像 - -部署 TiDB 集群主要包括 3 个服务组件: - -- TiDB -- TiKV -- PD - -对应的最新 Docker 镜像可以通过 [Docker 官方镜像仓库](https://hub.docker.com/u/pingcap) 获取: - -{{< copyable "shell-regular" >}} - -```bash -docker pull pingcap/tidb:latest -``` - -{{< copyable "shell-regular" >}} - -```bash -docker pull pingcap/tikv:latest -``` - -{{< copyable "shell-regular" >}} - -```bash -docker pull pingcap/pd:latest -``` - -## 部署一个多节点集群 - -假设我们打算在 6 台主机上部署一个 TiDB 集群: - -| 主机名 | IP | 部署服务 | 数据盘挂载 | -| --------- | ------------- | ---------- | ----- | -| host1 | 192.168.1.101 | PD1 & TiDB | /data | -| host2 | 192.168.1.102 | PD2 | /data | -| host3 | 192.168.1.103 | PD3 | /data | -| host4 | 192.168.1.104 | TiKV1 | /data | -| host5 | 192.168.1.105 | TiKV2 | /data | -| host6 | 192.168.1.106 | TiKV3 | /data | - -### 启动 PD - -登录 **host1** 执行: - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name pd1 \ - -p 2379:2379 \ - -p 2380:2380 \ - -v /etc/localtime:/etc/localtime:ro \ - -v /data:/data \ - pingcap/pd:latest \ - --name="pd1" \ - --data-dir="/data/pd1" \ - --client-urls="http://0.0.0.0:2379" \ - --advertise-client-urls="http://192.168.1.101:2379" \ - --peer-urls="http://0.0.0.0:2380" \ - --advertise-peer-urls="http://192.168.1.101:2380" \ - --initial-cluster="pd1=http://192.168.1.101:2380,pd2=http://192.168.1.102:2380,pd3=http://192.168.1.103:2380" -``` - -登录 **host2** 执行: - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name pd2 \ - -p 2379:2379 \ - -p 2380:2380 \ - -v /etc/localtime:/etc/localtime:ro \ - -v /data:/data \ - pingcap/pd:latest \ - --name="pd2" \ - --data-dir="/data/pd2" \ - --client-urls="http://0.0.0.0:2379" \ - --advertise-client-urls="http://192.168.1.102:2379" \ - --peer-urls="http://0.0.0.0:2380" \ - --advertise-peer-urls="http://192.168.1.102:2380" \ - --initial-cluster="pd1=http://192.168.1.101:2380,pd2=http://192.168.1.102:2380,pd3=http://192.168.1.103:2380" -``` - -登录 **host3** 执行: - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name pd3 \ - -p 2379:2379 \ - -p 2380:2380 \ - -v /etc/localtime:/etc/localtime:ro \ - -v /data:/data \ - pingcap/pd:latest \ - --name="pd3" \ - --data-dir="/data/pd3" \ - --client-urls="http://0.0.0.0:2379" \ - --advertise-client-urls="http://192.168.1.103:2379" \ - --peer-urls="http://0.0.0.0:2380" \ - --advertise-peer-urls="http://192.168.1.103:2380" \ - --initial-cluster="pd1=http://192.168.1.101:2380,pd2=http://192.168.1.102:2380,pd3=http://192.168.1.103:2380" -``` - -### 启动 TiKV - -登录 **host4** 执行: - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name tikv1 \ - -p 20160:20160 \ - --ulimit nofile=1000000:1000000 \ - -v /etc/localtime:/etc/localtime:ro \ - -v /data:/data \ - pingcap/tikv:latest \ - --addr="0.0.0.0:20160" \ - --advertise-addr="192.168.1.104:20160" \ - --data-dir="/data/tikv1" \ - --pd="192.168.1.101:2379,192.168.1.102:2379,192.168.1.103:2379" -``` - -登录 **host5** 执行: - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name tikv2 \ - -p 20160:20160 \ - --ulimit nofile=1000000:1000000 \ - -v /etc/localtime:/etc/localtime:ro \ - -v /data:/data \ - pingcap/tikv:latest \ - --addr="0.0.0.0:20160" \ - --advertise-addr="192.168.1.105:20160" \ - --data-dir="/data/tikv2" \ - --pd="192.168.1.101:2379,192.168.1.102:2379,192.168.1.103:2379" -``` - -登录 **host6** 执行: - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name tikv3 \ - -p 20160:20160 \ - --ulimit nofile=1000000:1000000 \ - -v /etc/localtime:/etc/localtime:ro \ - -v /data:/data \ - pingcap/tikv:latest \ - --addr="0.0.0.0:20160" \ - --advertise-addr="192.168.1.106:20160" \ - --data-dir="/data/tikv3" \ - --pd="192.168.1.101:2379,192.168.1.102:2379,192.168.1.103:2379" -``` - -### 启动 TiDB - -登录 **host1** 执行: - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name tidb \ - -p 4000:4000 \ - -p 10080:10080 \ - -v /etc/localtime:/etc/localtime:ro \ - pingcap/tidb:latest \ - --store=tikv \ - --path="192.168.1.101:2379,192.168.1.102:2379,192.168.1.103:2379" -``` - -### 使用 MySQL 标准客户端连接 TiDB 测试 - -登录 **host1** 并确保已安装 [MySQL 命令行客户端](http://dev.mysql.com/downloads/mysql/),执行: - -{{< copyable "shell-regular" >}} - -```bash -mysql -h 127.0.0.1 -P 4000 -u root -D test -``` - -{{< copyable "sql" >}} - -```sql -show databases; -``` - -``` -+--------------------+ -| Database | -+--------------------+ -| INFORMATION_SCHEMA | -| PERFORMANCE_SCHEMA | -| mysql | -| test | -+--------------------+ -4 rows in set (0.00 sec) -``` - -### 如何自定义配置文件 - -TiKV 和 PD 可以通过指定配置文件的方式来加载更加丰富的启动参数,用于性能调优。 - -假定配置文件在宿主机上的存放路径 `/path/to/config/pd.toml` 和 `/path/to/config/tikv.toml`。启动 Docker 时需要调整相应的启动参数,以 tikv1 和 pd1 为例: - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name tikv1 \ - -p 20160:20160 \ - -v /etc/localtime:/etc/localtime:ro \ - -v /data:/data \ - -v /path/to/config/tikv.toml:/tikv.toml:ro \ - pingcap/tikv:latest \ - --addr="0.0.0.0:20160" \ - --advertise-addr="192.168.1.104:20160" \ - --data-dir="/data/tikv1" \ - --pd="192.168.1.101:2379,192.168.1.102:2379,192.168.1.103:2379" \ - --config="/tikv.toml" -``` - -{{< copyable "shell-regular" >}} - -```bash -docker run -d --name pd1 \ - -p 2379:2379 \ - -p 2380:2380 \ - -v /etc/localtime:/etc/localtime:ro \ - -v /data:/data \ - -v /path/to/config/pd.toml:/pd.toml:ro \ - pingcap/pd:latest \ - --name="pd1" \ - --data-dir="/data/pd1" \ - --client-urls="http://0.0.0.0:2379" \ - --advertise-client-urls="http://192.168.1.101:2379" \ - --peer-urls="http://0.0.0.0:2380" \ - --advertise-peer-urls="http://192.168.1.101:2380" \ - --initial-cluster="pd1=http://192.168.1.101:2380,pd2=http://192.168.1.102:2380,pd3=http://192.168.1.103:2380" \ - --config="/pd.toml" -``` diff --git a/how-to/deploy/orchestrated/offline-ansible.md b/how-to/deploy/orchestrated/offline-ansible.md deleted file mode 100644 index a383850dd9f7..000000000000 --- a/how-to/deploy/orchestrated/offline-ansible.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -title: 离线 TiDB Ansible 部署方案 -category: how-to ---- - -# 离线 TiDB Ansible 部署方案 - -## 准备机器 - -1. 下载机一台 - - - 该机器需开放外网访问,用于下载 TiDB Ansible、TiDB 及相关软件安装包。 - - 推荐安装 CentOS 7.3 及以上版本 Linux 操作系统。 - -2. 部署目标机器若干及部署中控机一台 - - - 系统要求及配置参考[准备机器](/how-to/deploy/orchestrated/ansible.md#准备机器)。 - - 可以无法访问外网。 - -## 在中控机上安装系统依赖包 - -1. 在下载机上下载[系统依赖离线安装包](https://download.pingcap.org/ansible-system-rpms.el7.tar.gz),然后上传至中控机。该离线包仅支持 CentOS 7 系统,包含 `pip` 及 `sshpass`。 - -2. 在中控机上安装系统依赖包: - - {{< copyable "shell-root" >}} - - ```bash - tar -xzvf ansible-system-rpms.el7.tar.gz && - cd ansible-system-rpms.el7 && - chmod u+x install_ansible_system_rpms.sh && - ./install_ansible_system_rpms.sh - ``` - -3. 安装完成后,可通过 `pip -V` 验证 pip 是否安装成功: - - {{< copyable "shell-root" >}} - - ```bash - pip -V - ``` - - ``` - pip 8.1.2 from /usr/lib/python2.7/site-packages (python 2.7) - ``` - -> **注意:** -> -> 如果你的系统已安装 pip,请确认版本 >= 8.1.2,否则离线安装 TiDB Ansible 及其依赖时,会有兼容问题。 - -## 在中控机上创建 tidb 用户,并生成 ssh key - -参考[在中控机上创建 tidb 用户,并生成 ssh key](/how-to/deploy/orchestrated/ansible.md#第-2-步在中控机上创建-tidb-用户并生成-ssh-key) 即可。 - -## 在中控机器上离线安装 TiDB Ansible 及其依赖 - -以下是 CentOS 7 系统 Ansible 离线安装方式: - -建议使用 Ansible 2.4 至 2.7.11 版本,Ansible 及相关依赖版本记录在 `tidb-ansible/requirements.txt` 文件中。下面步骤以安装 Ansible 2.5 为例。 - -1. 在下载机上下载 [Ansible 2.5 离线安装包](https://download.pingcap.org/ansible-2.5.0-pip.tar.gz),然后上传至中控机。 - -2. 离线安装 TiDB Ansible 及相关依赖: - - {{< copyable "shell-root" >}} - - ```bash - tar -xzvf ansible-2.5.0-pip.tar.gz && - cd ansible-2.5.0-pip/ && - chmod u+x install_ansible.sh && - ./install_ansible.sh - ``` - -3. 安装完成后,可通过 `ansible --version` 查看版本: - - {{< copyable "shell-root" >}} - - ```bash - ansible --version - ``` - - ``` - ansible 2.5.0 - ``` - -## 在下载机上下载 TiDB Ansible 及 TiDB 安装包 - -1. 在下载机上安装 TiDB Ansible: - - 请按以下方式在 CentOS 7 系统的下载机上在线安装 TiDB Ansible。安装完成后,可通过 `ansible --version` 查看版本,请务必确认是 **Ansible 2.5.0** 版本,否则会有兼容问题。 - - {{< copyable "shell-root" >}} - - ```bash - yum install epel-release && - yum install ansible curl && - ansible --version - ``` - - ``` - ansible 2.5.0 - ``` - -2. 下载 tidb-ansible: - - 使用以下命令从 Github [TiDB Ansible 项目](https://github.com/pingcap/tidb-ansible)上下载 TiDB Ansible 相应版本,默认的文件夹名称为 `tidb-ansible`。 - - {{< copyable "shell-regular" >}} - - ```bash - git clone https://github.com/pingcap/tidb-ansible.git - ``` - - > **注意:** - > - > 部署和升级 TiDB 集群需使用对应的 tidb-ansible 版本,通过改 `inventory.ini` 文件中的版本来混用可能会产生一些错误。 - -3. 执行 `local_prepare.yml` playbook,联网下载 TiDB binary 到下载机: - - {{< copyable "shell-regular" >}} - - ```bash - cd tidb-ansible && - ansible-playbook local_prepare.yml - ``` - -4. 将执行完以上命令之后的 `tidb-ansible` 文件夹拷贝到中控机 `/home/tidb` 目录下,文件属主权限需是 `tidb` 用户。 - -## 在中控机上配置部署机器 SSH 互信及 sudo 规则 - -参考[在中控机上配置部署机器 SSH 互信及 sudo 规则](/how-to/deploy/orchestrated/ansible.md#第-5-步在中控机上配置部署机器-ssh-互信及-sudo-规则)即可。 - -## 在部署目标机器上安装 NTP 服务 - -如果你的部署目标机器时间、时区设置一致,已开启 NTP 服务且在正常同步时间,此步骤可忽略,可参考[如何检测 NTP 服务是否正常](/how-to/deploy/orchestrated/ansible.md#如何检测-ntp-服务是否正常)。 - -参考[在部署目标机器上安装 NTP 服务](/how-to/deploy/orchestrated/ansible.md#第-6-步在部署目标机器上安装-ntp-服务)即可。 - -## 在部署目标机器上配置 CPUfreq 调节器模式 - -参考[在部署目标机器上配置 CPUfreq 调节器模式](/how-to/deploy/orchestrated/ansible.md#第-7-步在部署目标机器上配置-cpufreq-调节器模式)即可。 - -## 在部署目标机器上添加数据盘 ext4 文件系统挂载参数 - -参考[在部署目标机器上添加数据盘 ext4 文件系统挂载参数](/how-to/deploy/orchestrated/ansible.md#第-8-步在部署目标机器上添加数据盘-ext4-文件系统挂载参数)即可。 - -## 分配机器资源,编辑 inventory.ini 文件 - -参考[分配机器资源,编辑 inventory.ini 文件](/how-to/deploy/orchestrated/ansible.md#第-9-步编辑-inventoryini-文件分配机器资源)即可。 - -## 部署任务 - -1. `ansible-playbook local_prepare.yml` 该 playbook 不需要再执行。 - -2. 参考[部署任务](/how-to/deploy/orchestrated/ansible.md#第-11-步部署-tidb-集群)即可。 - -## 测试集群 - -参考[测试集群](/how-to/deploy/orchestrated/ansible.md#测试集群)即可。 diff --git a/how-to/get-started/deploy-tidb-from-docker-compose.md b/how-to/get-started/deploy-tidb-from-docker-compose.md deleted file mode 100644 index e6ec4df5563d..000000000000 --- a/how-to/get-started/deploy-tidb-from-docker-compose.md +++ /dev/null @@ -1,206 +0,0 @@ ---- -title: 使用 Docker Compose 快速构建 TiDB 集群 -category: how-to ---- - -# 使用 Docker Compose 快速构建 TiDB 集群 - -本文档介绍如何在单机上通过 Docker Compose 快速一键部署一套 TiDB 测试集群。[Docker Compose](https://docs.docker.com/compose/overview) 可以通过一个 YAML 文件定义多个容器的应用服务,然后一键启动或停止。 - -> **警告:** -> -> 对于生产环境,不要使用 Docker Compose 进行部署,而应[使用 TiDB Ansible 部署 TiDB 集群](/how-to/deploy/orchestrated/ansible.md)。 - -## 准备环境 - -确保你的机器上已安装: - -- Docker(17.06.0 及以上版本) -- Docker Compose -- Git - -## 快速部署 - -1. 下载 `tidb-docker-compose` - - {{< copyable "shell-regular" >}} - - ```bash - git clone https://github.com/pingcap/tidb-docker-compose.git - ``` - -2. 创建并启动集群 - - 获取最新 Docker 镜像: - - {{< copyable "shell-regular" >}} - - ```bash - cd tidb-docker-compose && docker-compose pull && docker-compose up -d - ``` - -3. 访问集群 - - {{< copyable "shell-regular" >}} - - ```bash - mysql -h 127.0.0.1 -P 4000 -u root - ``` - - 访问集群 Grafana 监控页面: 默认用户名和密码均为 admin。 - - [集群数据可视化](https://github.com/pingcap/tidb-vision): - -## 自定义集群 - -在完成快速部署后,以下组件已默认部署:3 个 PD,3 个 TiKV,1 个 TiDB 和监控组件 Prometheus,Pushgateway,Grafana 以及 tidb-vision。 - -如果想自定义集群,可以直接修改 `docker-compose.yml`,但是手动修改比较繁琐而且容易出错,强烈建议使用 [Helm](https://helm.sh) 模板引擎生成 `docker-compose.yml` 文件。 - -1. 安装 Helm - - [Helm](https://helm.sh) 可以用作模板渲染引擎,只需要下载其 binary 文件即可以使用。确保你的 Helm 版本为 2.9.0 ≤ Helm < 3.0.0。 - - {{< copyable "shell-regular" >}} - - ```bash - curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash - ``` - - 如果是 Mac 系统,也可以通过 Homebrew 安装: - - {{< copyable "shell-regular" >}} - - ```bash - brew install helm@2 - brew link --force helm@2 - ``` - -2. 下载 `tidb-docker-compose` - - {{< copyable "shell-regular" >}} - - ```bash - git clone https://github.com/pingcap/tidb-docker-compose.git - ``` - -3. 自定义集群 - - {{< copyable "shell-regular" >}} - - ```bash - cd tidb-docker-compose && - cp compose/values.yaml values.yaml && - vim values.yaml - ``` - - 修改 `values.yaml` 里面的配置,例如集群规模,TiDB 镜像版本等。 - - [tidb-vision](https://github.com/pingcap/tidb-vision) 是 TiDB 集群可视化页面,可以可视化地显示 PD 对 TiKV 数据的调度。如果不想部署该组件,可以将 `tidbVision` 项留空。 - - PD,TiKV,TiDB 和 tidb-vision 支持从 GitHub 源码或本地文件构建 Docker 镜像,供开发测试使用。 - - - 如果希望从本地已编译好的 binary 文件构建 PD,TiKV 或 TiDB 镜像,需要将其 `image` 字段留空,并将已编译好的 binary 拷贝到对应的 `pd/bin/pd-server`,`tikv/bin/tikv-server`,`tidb/bin/tidb-server`。 - - - 如果希望从本地构建 tidb-vision 镜像,需要将其 `image` 字段留空,并将 tidb-vision 项目拷贝到 `tidb-vision/tidb-vision`。 - -4. 生成 `docker-compose.yml` 文件 - - {{< copyable "shell-regular" >}} - - ```bash - helm template -f values.yaml compose > generated-docker-compose.yml - ``` - -5. 使用生成的 `docker-compose.yml` 创建并启动集群 - - 获取最新 Docker 镜像: - - {{< copyable "shell-regular" >}} - - ```bash - docker-compose -f generated-docker-compose.yml pull - ``` - - {{< copyable "shell-regular" >}} - - ```bash - docker-compose -f generated-docker-compose.yml up -d - ``` - -6. 访问集群 - - {{< copyable "shell-regular" >}} - - ```bash - mysql -h 127.0.0.1 -P 4000 -u root - ``` - - 访问集群 Grafana 监控页面: 默认用户名和密码均为 admin。 - - 如果启用了 tidb-vision,可以通过 查看。 - -## 访问 Spark shell 并加载 TiSpark - -向 TiDB 集群中插入一些样本数据: - -{{< copyable "shell-regular" >}} - -```bash -docker-compose exec tispark-master bash && -cd /opt/spark/data/tispark-sample-data && -mysql -h tidb -P 4000 -u root < dss.ddl -``` - -当样本数据加载到 TiDB 集群之后,可以使用 `docker-compose exec tispark-master /opt/spark/bin/spark-shell` 来访问 Spark shell。 - -{{< copyable "shell-regular" >}} - -```bash -docker-compose exec tispark-master /opt/spark/bin/spark-shell -``` - -``` -... -Spark context available as 'sc' (master = local[*], app id = local-1527045927617). -Spark session available as 'spark'. -Welcome to - ____ __ - / __/__ ___ _____/ /__ - _\ \/ _ \/ _ `/ __/ '_/ - /___/ .__/\_,_/_/ /_/\_\ version 2.1.1 - /_/ - -Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_172) -Type in expressions to have them evaluated. -Type :help for more information. -``` - -```shell -scala> import org.apache.spark.sql.TiContext -... -scala> val ti = new TiContext(spark) -... -scala> ti.tidbMapDatabase("TPCH_001") -... -scala> spark.sql("select count(*) from lineitem").show -``` - -``` -+--------+ -|count(1)| -+--------+ -| 60175| -+--------+ -``` - -你也可以通过 Python 或 R 来访问 Spark: - -{{< copyable "shell-regular" >}} - -```bash -docker-compose exec tispark-master /opt/spark/bin/pyspark && -docker-compose exec tispark-master /opt/spark/bin/sparkR -``` - -更多关于 TiSpark 的信息,参见 [TiSpark 的详细文档](/how-to/get-started/tispark.md)。 diff --git a/how-to/get-started/explore-sql.md b/how-to/get-started/explore-sql.md deleted file mode 100644 index 32599b670888..000000000000 --- a/how-to/get-started/explore-sql.md +++ /dev/null @@ -1,274 +0,0 @@ ---- -title: TiDB 中的基本 SQL 操作 -category: how-to ---- - -# TiDB 中的基本 SQL 操作 - -成功部署 TiDB 集群之后,便可以在 TiDB 中执行 SQL 语句了。因为 TiDB 兼容 MySQL,你可以使用 MySQL 客户端连接 TiDB,并且[大多数情况下](/reference/mysql-compatibility.md)可以直接执行 MySQL 语句。 - -本文介绍 CRUD 操作等基本的 SQL 语句。完整的 SQL 语句列表,参见 [TiDB SQL 语法详解](https://pingcap.github.io/sqlgram/)。 - -## 创建、查看和删除数据库 - -使用 `CREATE DATABASE` 语句创建数据库。语法如下: - -{{< copyable "sql" >}} - -```sql -CREATE DATABASE db_name [options]; -``` - -例如,要创建一个名为 `samp_db` 的数据库,可使用以下语句: - -{{< copyable "sql" >}} - -```sql -CREATE DATABASE IF NOT EXISTS samp_db; -``` - -使用 `SHOW DATABASES` 语句查看数据库: - -{{< copyable "sql" >}} - -```sql -SHOW DATABASES; -``` - -使用 `DROP DATABASE` 语句删除数据库,例如: - -{{< copyable "sql" >}} - -```sql -DROP DATABASE samp_db; -``` - -## 创建、查看和删除表 - -使用 `CREATE TABLE` 语句创建表。语法如下: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE table_name column_name data_type constraint; -``` - -例如: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE person ( - number INT(11), - name VARCHAR(255), - birthday DATE - ); -``` - -如果表已存在,添加 `IF NOT EXISTS` 可防止发生错误: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE IF NOT EXISTS person ( - number INT(11), - name VARCHAR(255), - birthday DATE -); -``` - -使用 `SHOW CREATE` 语句查看建表语句。例如: - -{{< copyable "sql" >}} - -```sql -SHOW CREATE table person; -``` - -使用 `SHOW FULL COLUMNS` 语句查看表的列。 例如: - -{{< copyable "sql" >}} - -```sql -SHOW FULL COLUMNS FROM person; -``` - -使用 `DROP TABLE` 语句删除表。例如: - -{{< copyable "sql" >}} - -```sql -DROP TABLE person; -``` - -或者 - -{{< copyable "sql" >}} - -```sql -DROP TABLE IF EXISTS person; -``` - -使用 `SHOW TABLES` 语句查看数据库中的所有表。例如: - -{{< copyable "sql" >}} - -```sql -SHOW TABLES FROM samp_db; -``` - -## 创建、查看和删除索引 - -对于值不唯一的列,可使用 `CREATE INDEX` 或 `ALTER TABLE` 语句。例如: - -{{< copyable "sql" >}} - -```sql -CREATE INDEX person_num ON person (number); -``` - -或者 - -{{< copyable "sql" >}} - -```sql -ALTER TABLE person ADD INDEX person_num (number); -``` - -对于值唯一的列,可以创建唯一索引。例如: - -{{< copyable "sql" >}} - -```sql -CREATE UNIQUE INDEX person_num ON person (number); -``` - -或者 - -{{< copyable "sql" >}} - -```sql -ALTER TABLE person ADD UNIQUE person_num (number); -``` - -使用 `SHOW INDEX` 语句查看表内所有索引: - -{{< copyable "sql" >}} - -```sql -SHOW INDEX from person; -``` - -使用 `ALTER TABLE` 或 `DROP INDEX` 语句来删除索引。与 `CREATE INDEX` 语句类似,`DROP INDEX` 也可以嵌入 `ALTER TABLE` 语句。例如: - -{{< copyable "sql" >}} - -```sql -DROP INDEX person_num ON person; -``` - -{{< copyable "sql" >}} - -```sql -ALTER TABLE person DROP INDEX person_num; -``` - -## 增删改查数据 - -使用 `INSERT` 语句向表内插入数据。例如: - -{{< copyable "sql" >}} - -```sql -INSERT INTO person VALUES("1","tom","20170912"); -``` - -使用 `SELECT` 语句检索表内数据。例如: - -{{< copyable "sql" >}} - -```sql -SELECT * FROM person; -``` - -``` -+--------+------+------------+ -| number | name | birthday | -+--------+------+------------+ -| 1 | tom | 2017-09-12 | -+--------+------+------------+ -``` - -使用 `UPDATE` 语句修改表内数据。例如: - -{{< copyable "sql" >}} - -```sql -UPDATE person SET birthday='20171010' WHERE name='tom'; -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM person; -``` - -``` -+--------+------+------------+ -| number | name | birthday | -+--------+------+------------+ -| 1 | tom | 2017-10-10 | -+--------+------+------------+ -``` - -使用 `DELETE` 语句删除表内数据: - -{{< copyable "sql" >}} - -```sql -DELETE FROM person WHERE number=1; -``` - -{{< copyable "sql" >}} - -```sql -SELECT * FROM person; -``` - -``` -Empty set (0.00 sec) -``` - -## 创建、授权和删除用户 - -使用 `CREATE USER` 语句创建一个用户 `tiuser`,密码为 `123456`: - -{{< copyable "sql" >}} - -```sql -CREATE USER 'tiuser'@'localhost' IDENTIFIED BY '123456'; -``` - -授权用户 `tiuser` 可检索数据库 `samp_db` 内的表: - -{{< copyable "sql" >}} - -```sql -GRANT SELECT ON samp_db.* TO 'tiuser'@'localhost'; -``` - -查询用户 `tiuser` 的权限: - -{{< copyable "sql" >}} - -```sql -SHOW GRANTS for tiuser@localhost; -``` - -删除用户 `tiuser`: - -{{< copyable "sql" >}} - -```sql -DROP USER 'tiuser'@'localhost'; -``` diff --git a/how-to/get-started/tidb-binlog.md b/how-to/get-started/tidb-binlog.md deleted file mode 100644 index 4635d34c290b..000000000000 --- a/how-to/get-started/tidb-binlog.md +++ /dev/null @@ -1,521 +0,0 @@ ---- -title: TiDB Binlog 教程 -category: how-to ---- - -# TiDB Binlog 教程 - -本文档主要介绍如何使用 TiDB Binlog 将数据从 TiDB 推送到 MariaDB 实例。文中的 TiDB Binlog 集群包含 Pump 和 Drainer 的单个节点,TiDB 集群包含 TiDB、TiKV 和 Placement Driver (PD) 各组件的单个节点。 - -希望上手实践 TiDB Binlog 工具的用户需要对 [TiDB 架构](/architecture.md)有一定的了解,最好有创建过 TiDB 集群的经验。该文档也有助于简单快速了解 TiDB Binlog 架构以及相关概念。 - -> **警告:** -> -> 该文档中部署 TiDB 的操作指导**不适用于**在生产或研发环境中部署 TiDB 的情况。 - -该文档假设用户使用的是现代 Linux 发行版本中的 x86-64。示例中使用的是 VMware 中运行的 CentOS 7 最小化安装。建议在一开始就进行清洁安装,以避免受现有环境中未知情况的影响。如果不想使用本地虚拟环境,也可以使用云服务启动 CentOS 7 VM。 - -## TiDB Binlog 简介 - -TiDB Binlog 用于收集 TiDB 中二进制日志数据、提供实时数据备份和同步以及将 TiDB 集群的数据增量同步到下游。 - -TiDB Binlog 支持以下功能场景: - -- 增量备份,将 TiDB 集群中的数据增量同步到另一个集群,或通过 Kafka 增量同步到选择的下游。 -- 当使用 TiDB DM (Data Migration) 将数据从上游 MySQL 或者 MariaDB 迁移到 TiDB 集群时,可使用 TiDB Binlog 保持 TiDB 集群与其一个独立下游 MySQL 或 MariaDB 实例或集群同步。当 TiDB 集群上游数据迁移过程中出现问题,下游数据同步过程中可使用 TiDB Binlog 恢复数据到原先的状态。 - -更多信息参考 [TiDB Binlog Cluster 版本用户文档](/reference/tidb-binlog/overview.md)。 - -## 架构 - -TiDB Binlog 集群由 **Pump** 和 **Drainer** 两个组件组成。一个 Pump 集群中有若干个 Pump 节点。TiDB 实例连接到各个 Pump 节点并发送 binlog 数据到 Pump 节点。Pump 集群连接到 Drainer 节点,Drainer 将接收到的更新数据转换到某个特定下游(例如 Kafka、另一个 TiDB 集群或 MySQL 或 MariaDB Server)指定的正确格式。 - -![TiDB Binlog architecture](/media/tidb_binlog_cluster_architecture.png) - -Pump 的集群架构能确保 TiDB 或 Pump 集群中有新的实例加入或退出时更新数据不会丢失。 - -## 安装 - -由于 RHEL/CentOS 7 的默认包装库中包括 MariaDB Server,本示例选择的是 MariaDB Server。后续除了安装服务器,也需要安装客户端。安装指令如下: - -{{< copyable "shell-regular" >}} - -```bash -sudo yum install -y mariadb-server -``` - -{{< copyable "shell-regular" >}} - -```bash -curl -LO https://download.pingcap.org/tidb-latest-linux-amd64.tar.gz | tar xzf - && -cd tidb-latest-linux-amd64 -``` - -预期输出: - -``` - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed -100 368M 100 368M 0 0 8394k 0 0:00:44 0:00:44 --:--:-- 11.1M -``` - -## 配置 - -通过执行以下步骤配置一个 TiDB 集群,该集群包括 `pd-server`、`tikv-server` 和 `tidb-server` 各组件的单个实例。 - -1. 填充配置文件: - - {{< copyable "shell-regular" >}} - - ```bash - printf > pd.toml %s\\n 'log-file="pd.log"' 'data-dir="pd.data"' && - printf > tikv.toml %s\\n 'log-file="tikv.log"' '[storage]' 'data-dir="tikv.data"' '[pd]' 'endpoints=["127.0.0.1:2379"]' '[rocksdb]' max-open-files=1024 '[raftdb]' max-open-files=1024 && - printf > pump.toml %s\\n 'log-file="pump.log"' 'data-dir="pump.data"' 'addr="127.0.0.1:8250"' 'advertise-addr="127.0.0.1:8250"' 'pd-urls="http://127.0.0.1:2379"' && - printf > tidb.toml %s\\n 'store="tikv"' 'path="127.0.0.1:2379"' '[log.file]' 'filename="tidb.log"' '[binlog]' 'enable=true' && - printf > drainer.toml %s\\n 'log-file="drainer.log"' '[syncer]' 'db-type="mysql"' '[syncer.to]' 'host="127.0.0.1"' 'user="root"' 'password=""' 'port=3306' - ``` - -2. 查看配置细节: - - {{< copyable "shell-regular" >}} - - ```bash - for f in *.toml; do echo "$f:"; cat "$f"; echo; done - ``` - - 预期输出: - - ``` - drainer.toml: - log-file="drainer.log" - [syncer] - db-type="mysql" - [syncer.to] - host="127.0.0.1" - user="root" - password="" - port=3306 - - pd.toml: - log-file="pd.log" - data-dir="pd.data" - - pump.toml: - log-file="pump.log" - data-dir="pump.data" - addr="127.0.0.1:8250" - advertise-addr="127.0.0.1:8250" - pd-urls="http://127.0.0.1:2379" - - tidb.toml: - store="tikv" - path="127.0.0.1:2379" - [log.file] - filename="tidb.log" - [binlog] - enable=true - - tikv.toml: - log-file="tikv.log" - [storage] - data-dir="tikv.data" - [pd] - endpoints=["127.0.0.1:2379"] - [rocksdb] - max-open-files=1024 - [raftdb] - max-open-files=1024 - ``` - -## 启动程序 - -现在可启动各个组件。推荐启动顺序依次为 Placement Driver (PD)、TiKV、Pump(TiDB 发送 binlog 日志必须连接 Pump 服务)、TiDB。 - -1. 启动所有服务: - - {{< copyable "shell-regular" >}} - - ```bash - ./bin/pd-server --config=pd.toml &>pd.out & - ``` - - ``` - [1] 20935 - ``` - - {{< copyable "shell-regular" >}} - - ```bash - ./bin/tikv-server --config=tikv.toml &>tikv.out & - ``` - - ``` - [2] 20944 - ``` - - {{< copyable "shell-regular" >}} - - ```bash - ./bin/pump --config=pump.toml &>pump.out & - ``` - - ``` - [3] 21050 - ``` - - {{< copyable "shell-regular" >}} - - ```bash - sleep 3 && - ./bin/tidb-server --config=tidb.toml &>tidb.out & - ``` - - ``` - [4] 21058 - ``` - -2. 如果执行 `jobs`,可以看到后台正在运行的程序,列表如下: - - {{< copyable "shell-regular" >}} - - ```bash - jobs - ``` - - ``` - [1] Running ./bin/pd-server --config=pd.toml &>pd.out & - [2] Running ./bin/tikv-server --config=tikv.toml &>tikv.out & - [3]- Running ./bin/pump --config=pump.toml &>pump.out & - [4]+ Running ./bin/tidb-server --config=tidb.toml &>tidb.out & - ``` - - 如果有服务启动失败(例如出现 “`Exit 1`” 而不是 “`Running`”),尝试重启单个组件。 - -## 连接 - -按以上步骤操作后,TiDB 的 4 个组件开始运行。接下来可以使用以下 MariaDB 或 MySQL 命令行客户端,通过 4000 端口连接到 TiDB 服务: - -{{< copyable "shell-regular" >}} - -```bash -mysql -h 127.0.0.1 -P 4000 -u root -e 'select tidb_version();' -``` - -预期输出: - -``` -*************************** 1. row *************************** -tidb_version(): Release Version: v3.0.0-beta.1-154-gd5afff70c -Git Commit Hash: d5afff70cdd825d5fab125c8e52e686cc5fb9a6e -Git Branch: master -UTC Build Time: 2019-04-24 03:10:00 -GoVersion: go version go1.12 linux/amd64 -Race Enabled: false -TiKV Min Version: 2.1.0-alpha.1-ff3dd160846b7d1aed9079c389fc188f7f5ea13e -Check Table Before Drop: false -``` - -连接后TiDB 集群已开始运行,`pump` 读取集群中的 binlog 数据,并在其数据目录中将 binlog 数据存储为 relay log。下一步是启动一个可供 `drainer` 写入的 MariaDB Server。 - -1. 启动 `drainer`: - - {{< copyable "shell-regular" >}} - - ```bash - sudo systemctl start mariadb && - ./bin/drainer --config=drainer.toml &>drainer.out & - ``` - - 如果你的操作系统更易于安装 MySQL,只需保证监听 3306 端口。另外,可使用密码为空的 "root" 用户连接到 MySQL,或调整 `drainer.toml` 连接到 MySQL。 - - {{< copyable "shell-regular" >}} - - ```bash - mysql -h 127.0.0.1 -P 3306 -u root - ``` - - 预期输出: - - ``` - Welcome to the MariaDB monitor. Commands end with ; or \g. - Your MariaDB connection id is 20 - Server version: 5.5.60-MariaDB MariaDB Server - - Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. - - Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. - - MariaDB [(none)]> - ``` - - {{< copyable "sql" >}} - - ```sql - show databases; - ``` - - 预期输出: - - ``` - +--------------------+ - | Database | - +--------------------+ - | information_schema | - | mysql | - | performance_schema | - | test | - | tidb_binlog | - +--------------------+ - 5 rows in set (0.01 sec) - ``` - - 如下表格是包含 `checkpoint` 表格的 `tidb_binlog` 数据库。`drainer` 使用 `checkpoint` 表格,记录 TiDB 集群中的 binlog 已经更新到了哪个位置。 - - {{< copyable "sql" >}} - - ```sql - use tidb_binlog; - ``` - - ``` - Database changed - ``` - - {{< copyable "sql" >}} - - ```sql - select * from checkpoint; - ``` - - ``` - +---------------------+---------------------------------------------+ - | clusterID | checkPoint | - +---------------------+---------------------------------------------+ - | 6678715361817107733 | {"commitTS":407637466476445697,"ts-map":{}} | - +---------------------+---------------------------------------------+ - 1 row in set (0.00 sec) - ``` - - 打开另一个连接到 TiDB 的客户端,创建一个表格并插入几行数据。建议在 GNU Screen 软件中操作,从而同时打开多个客户端。 - - {{< copyable "shell-regular" >}} - - ```bash - mysql -h 127.0.0.1 -P 4000 --prompt='TiDB [\d]> ' -u root - ``` - - {{< copyable "sql" >}} - - ```sql - create database tidbtest; - ``` - - ``` - Query OK, 0 rows affected (0.12 sec) - ``` - - {{< copyable "sql" >}} - - ```sql - use tidbtest; - ``` - - ``` - Database changed - ``` - - {{< copyable "sql" >}} - - ```sql - create table t1 (id int unsigned not null AUTO_INCREMENT primary key); - ``` - - ``` - Query OK, 0 rows affected (0.11 sec) - ``` - - {{< copyable "sql" >}} - - ```sql - insert into t1 () values (),(),(),(),(); - ``` - - ``` - Query OK, 5 rows affected (0.01 sec) - Records: 5 Duplicates: 0 Warnings: 0 - ``` - - {{< copyable "sql" >}} - - ```sql - select * from t1; - ``` - - ``` - +----+ - | id | - +----+ - | 1 | - | 2 | - | 3 | - | 4 | - | 5 | - +----+ - 5 rows in set (0.00 sec) - ``` - - 切换回 MariaDB 客户端可看到新的数据库、新的表格和最近插入的行数据。 - - {{< copyable "sql" >}} - - ```sql - use tidbtest; - ``` - - ``` - Reading table information for completion of table and column names - You can turn off this feature to get a quicker startup with -A - - Database changed - ``` - - {{< copyable "sql" >}} - - ```sql - show tables; - ``` - - ``` - +--------------------+ - | Tables_in_tidbtest | - +--------------------+ - | t1 | - +--------------------+ - 1 row in set (0.00 sec) - ``` - - {{< copyable "sql" >}} - - ```sql - select * from t1; - ``` - - ``` - +----+ - | id | - +----+ - | 1 | - | 2 | - | 3 | - | 4 | - | 5 | - +----+ - 5 rows in set (0.00 sec) - ``` - - 可看到查询 MariaDB 时插入到 TiDB 相同的行数据,表明 TiDB Binlog 安装成功。 - -## binlogctl - -加入到集群的 Pump 和 Drainer 的数据存储在 Placement Driver (PD) 中。binlogctl 可用于查询和修改状态信息。更多信息请参考 [binlogctl guide](/reference/tidb-binlog/maintain.md#binlogctl-工具)。 - -使用 `binlogctl` 查看集群中 Pump 和 Drainer 的当前状态: - -{{< copyable "shell-regular" >}} - -```bash -./bin/binlogctl -cmd drainers -``` - -``` -[2019/04/11 17:44:10.861 -04:00] [INFO] [nodes.go:47] ["query node"] [type=drainer] [node="{NodeID: localhost.localdomain:8249, Addr: 192.168.236.128:8249, State: online, MaxCommitTS: 407638907719778305, UpdateTime: 2019-04-11 17:44:10 -0400 EDT}"] -``` - -{{< copyable "shell-regular" >}} - -```bash -./bin/binlogctl -cmd pumps -``` - -``` -[2019/04/11 17:44:13.904 -04:00] [INFO] [nodes.go:47] ["query node"] [type=pump] [node="{NodeID: localhost.localdomain:8250, Addr: 192.168.236.128:8250, State: online, MaxCommitTS: 407638914024079361, UpdateTime: 2019-04-11 17:44:13 -0400 EDT}"] -``` - -如果结束 Drainer 进程,集群会改进程设置“已暂停(即集群等待 Drainer 重新加入)”的状态。 - -{{< copyable "shell-regular" >}} - -```bash -pkill drainer && -./bin/binlogctl -cmd drainers -``` - -预期输出: - -``` -[2019/04/11 17:44:22.640 -04:00] [INFO] [nodes.go:47] ["query node"] [type=drainer] [node="{NodeID: localhost.localdomain:8249, Addr: 192.168.236.128:8249, State: paused, MaxCommitTS: 407638915597467649, UpdateTime: 2019-04-11 17:44:18 -0400 EDT}"] -``` - -使用 binlogctl 的 "NodeIDs" 可控制单个对应节点。在该情况下,Drainer 的节点 ID 是 "localhost.localdomain:8249",Pump 的节点 ID 是 "localhost.localdomain:8250"。 - -本文档中的 binlogctl 主要用于集群重启。如果在 TiDB 集群中终止并尝试重启所有的进程,由于 Pump 无法连接 Drainer 且认为 Drainer 依旧“在线”,Pump 会拒绝启动。这里的进程并不包括下游的 MySQL 或 MariaDB 或 Drainer。 - -以下有三个方案可解决上述问题: - -- 使用 binlogctl 停止 Drainer,而不是结束进程: - - ```bash - ./bin/binlogctl --pd-urls=http://127.0.0.1:2379 --cmd=drainers && - ./bin/binlogctl --pd-urls=http://127.0.0.1:2379 --cmd=pause-drainer --node-id=localhost.localdomain:8249 - ``` - -- 在启动 Pump **之前**先启动 Drainer。 - -- 在启动 PD 之后但在启动 Drainer 和 Pump 之前,使用 binlogctl 更新已暂定 Drainer 的状态。 - - ```bash - ./bin/binlogctl --pd-urls=http://127.0.0.1:2379 --cmd=update-drainer --node-id=localhost.localdomain:8249 --state=paused - ``` - -## 清理 - -在 shell 终端里可启动创建集群的所有进程(`pd-server` 、`tikv-server`、`pump`、`tidb-server`、`drainer`)。可通过在 shell 终端中执行 `pkill -P $$` 停止 TiDB 集群服务和 TiDB Binlog 进程。按一定的顺序停止这些进程有利于留出足够的时间彻底关闭每个组件。 - -{{< copyable "shell-regular" >}} - -```bash -for p in tidb-server drainer pump tikv-server pd-server; do pkill "$p"; sleep 1; done -``` - -预期输出: - -``` -[4]- Done ./bin/tidb-server --config=tidb.toml &>tidb.out -[5]+ Done ./bin/drainer --config=drainer.toml &>drainer.out -[3]+ Done ./bin/pump --config=pump.toml &>pump.out -[2]+ Done ./bin/tikv-server --config=tikv.toml &>tikv.out -[1]+ Done ./bin/pd-server --config=pd.toml &>pd.out -``` - -如果需要所有服务退出后重启集群,可以使用一开始启动服务的命令。如以上 [`binlogctl`](#binlogctl) 部分所述,需要先启动 Drainer 再启动 Pump,最后启动 `tidb-server`。 - -{{< copyable "shell-regular" >}} - -```bash -./bin/pd-server --config=pd.toml &>pd.out & -./bin/tikv-server --config=tikv.toml &>tikv.out & -./bin/drainer --config=drainer.toml &>drainer.out & -sleep 3 -./bin/pump --config=pump.toml &>pump.out & -sleep 3 -./bin/tidb-server --config=tidb.toml &>tidb.out & -``` - -如果有组件启动失败,请尝试单独重启该组件。 - -## 总结 - -本文档介绍了如何通过设置 TiDB Binlog,使用单个 Pump 和 Drainer 组成的集群同步 TiDB 集群数据到下游的 MariaDB。可以发现,TiDB Binlog 是用于获取处理 TiDB 集群中更新数据的综合性平台工具。 - -在更稳健的开发、测试或生产部署环境中,可以使用多个 TiDB 服务以实现高可用性和扩展性。使用多个 Pump 实例可以避免 Pump 集群中的问题影响发送到 TiDB 实例的应用流量。或者可以使用增加的 Drainer 实例同步数据到不同的下游或实现数据增量备份。 -binlog \ No newline at end of file diff --git a/how-to/get-started/tidb-lightning.md b/how-to/get-started/tidb-lightning.md deleted file mode 100644 index 8836041f54a6..000000000000 --- a/how-to/get-started/tidb-lightning.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: TiDB Lightning 教程 -category: how-to ---- - -# TiDB Lightning 教程 - -TiDB Lightning 是一个将全量数据高速导入到 TiDB 集群的工具,目前支持 Mydumper 或 CSV 输出格式的数据源。你可以在以下两种场景下使用 Lightning: - -- **迅速**导入**大量新**数据。 -- 备份恢复所有数据。 - -TiDB Lightning 主要包含两个部分: - -- **`tidb-lightning`**(“前端”):主要完成适配工作,通过读取数据源,在下游 TiDB 集群建表、将数据转换成键/值对 (KV 对) 发送到 `tikv-importer`、检查数据完整性等。 -- **`tikv-importer`**(“后端”):主要完成将数据导入 TiKV 集群的工作,把 `tidb-lightning` 写入的 KV 对缓存、排序、切分并导入到 TiKV 集群。 - -![TiDB Lightning 整体架构](/media/tidb-lightning-architecture.png) - -本教程假设使用的是若干新的、纯净版 CentOS 7 实例,你可以(使用 VMware、VirtualBox 及其他工具)在本地虚拟化或在供应商提供的平台上部署一台小型的云虚拟主机。因为 TiDB Lightning 对计算机资源消耗较高,建议分配 4 GB 以上的内存。 - -> **警告:** -> -> 本教程中的部署方法只适用于测试及功能体验,并不适用于生产或开发环境。 - -## 准备全量备份数据 - -我们使用 [`mydumper`](/reference/tools/mydumper.md) 从 MySQL 导出数据,如下: - -{{< copyable "shell-regular" >}} - -```sh -./bin/mydumper -h 127.0.0.1 -P 3306 -u root -t 16 -F 256 -B test -T t1,t2 --skip-tz-utc -o /data/my_database/ -``` - -其中: - -- `-B test`:从 `test` 数据库导出。 -- `-T t1,t2`:只导出 `t1` 和 `t2` 这两个表。 -- `-t 16`:使用 16 个线程导出数据。 -- `-F 256`:将每张表切分成多个文件,每个文件大小约为 256 MB。 -- `--skip-tz-utc`:添加这个参数则会忽略掉 TiDB 与导数据的机器之间时区设置不一致的情况,禁止自动转换。 - -这样全量备份数据就导出到了 `/data/my_database` 目录中。 - -## 部署 TiDB Lightning - -### 第 1 步:部署 TiDB 集群 - -在开始数据导入之前,需先部署一套要进行导入的 TiDB 集群(版本要求 2.0.9 以上),本教程使用 TiDB 3.0.4 版本。部署方法可参考 [TiDB 快速入门指南](/overview.md#部署方式)。 - -### 第 2 步:下载 TiDB Lightning 安装包 - -通过以下链接获取 TiDB Lightning 安装包(选择与 TiDB 集群相同的版本): - -- **v3.0.4**: [tidb-toolkit-v3.0.4-linux-amd64.tar.gz](https://download.pingcap.org/tidb-toolkit-v3.0.0-linux-amd64.tar.gz) - -### 第 3 步:启动 `tikv-importer` - -1. 将安装包里的 `bin/tikv-importer` 上传至部署 TiDB Lightning 的服务器。 - -2. 配置 `tikv-importer.toml`。 - - ```toml - # TiKV Importer 配置文件模版 - - # 日志文件。 - log-file = "tikv-importer.log" - # 日志等级:trace、debug、info、warn、error、off。 - log-level = "info" - - [server] - # tikv-importer 监听的地址,tidb-lightning 需要连到这个地址进行数据写入。 - addr = "192.168.20.10:8287" - - [import] - # 存储引擎文档 (engine file) 的文件夹路径。 - import-dir = "/mnt/ssd/data.import/" - ``` - -3. 运行 `tikv-importer`。 - - {{< copyable "shell-regular" >}} - - ```sh - nohup ./tikv-importer -C tikv-importer.toml > nohup.out & - ``` - -### 第 4 步:启动 `tidb-lightning` - -1. 将安装包里的 `bin/tidb-lightning` 及 `bin/tidb-lightning-ctl` 上传至部署 TiDB Lightning 的服务器。 - -2. 将数据源也上传到同样的服务器。 - -3. 配置合适的参数运行 `tidb-lightning`。如果直接在命令行中用 `nohup` 启动程序,可能会因为 SIGHUP 信号而退出,建议把 `nohup` 放到脚本里面,如: - - {{< copyable "shell-regular" >}} - - ```sh - #!/bin/bash - nohup ./tidb-lightning \ - --importer 172.16.31.10:8287 \ - -d /data/my_database/ \ - --tidb-server 172.16.31.2 \ - --tidb-user root \ - --log-file tidb-lightning.log \ - > nohup.out & - ``` - -### 第 5 步:检查数据 - -导入完毕后,TiDB Lightning 会自动退出。若导入成功,日志的最后一行会显示 `tidb lightning exit`。 - -如果出错,请参见 [TiDB Lightning 错误排解](/how-to/troubleshoot/tidb-lightning.md)。 - -## 总结 - -本教程对 TiDB Lightning 进行了简单的介绍,并快速部署了一套简单的 TiDB Lightning 集群,将全量备份数据导入到 TiDB 集群中。 - -关于 TiDB Lightning 的详细功能和使用,参见 [TiDB Lightning 简介](/reference/tools/tidb-lightning/overview.md)。 diff --git a/how-to/get-started/tispark.md b/how-to/get-started/tispark.md deleted file mode 100644 index 32714d0be217..000000000000 --- a/how-to/get-started/tispark.md +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: TiSpark 快速入门指南 -category: how-to ---- - -# TiSpark 快速入门指南 - -为了让大家快速体验 [TiSpark](/reference/tispark.md),通过 TiDB Ansible 安装的 TiDB 集群中默认已集成 Spark、TiSpark jar 包及 TiSpark sample data。 - -## 部署信息 - -- Spark 默认部署在 TiDB 实例部署目录下 spark 目录中 -- TiSpark jar 包默认部署在 Spark 部署目录 jars 文件夹下:`spark/jars/tispark-${name_with_version}.jar` -- TiSpark 示例数据和导入脚本可点击 [TiSpark 示例数据](http://download.pingcap.org/tispark-sample-data.tar.gz)下载。 - - {{< copyable "" >}} - - ``` - tispark-sample-data/ - ``` - -## 环境准备 - -### 在 TiDB 实例上安装 JDK - -在 [Oracle JDK 官方下载页面](http://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html) 下载 JDK 1.8 当前最新版,本示例中下载的版本为 `jdk-8u141-linux-x64.tar.gz`。 - -解压并根据您的 JDK 部署目录设置环境变量,编辑 `~/.bashrc` 文件,比如: - -{{< copyable "shell-regular" >}} - -```bash -export JAVA_HOME=/home/pingcap/jdk1.8.0_144 && -export PATH=$JAVA_HOME/bin:$PATH -``` - -验证 JDK 有效性: - -```bash -java -version -``` - -``` -java version "1.8.0_144" -Java(TM) SE Runtime Environment (build 1.8.0_144-b01) -Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode) -``` - -### 导入样例数据 - -假设 TiDB 集群已启动,其中一台 TiDB 实例服务 IP 为 192.168.0.2,端口为 4000,用户名为 root, 密码为空。 - -{{< copyable "shell-regular" >}} - -```bash -wget http://download.pingcap.org/tispark-sample-data.tar.gz && \ -tar -zxvf tispark-sample-data.tar.gz && \ -cd tispark-sample-data -``` - -修改 `sample_data.sh` 中 TiDB 登录信息,比如: - -{{< copyable "shell-regular" >}} - -```bash -mysql --local-infile=1 -h 192.168.0.2 -P 4000 -u root < dss.ddl -``` - -执行脚本 - -{{< copyable "shell-regular" >}} - -```bash -./sample_data.sh -``` - -> **注意:** -> -> 执行脚本的机器上需要安装 MySQL client,CentOS 用户可通过 `yum -y install mysql`来安装。 - -登录 TiDB 并验证数据包含 `TPCH_001` 库及以下表: - -{{< copyable "shell-regular" >}} - -```bash -mysql -uroot -P4000 -h192.168.0.2 -``` - -{{< copyable "sql" >}} - -```sql -show databases; -``` - -``` -+--------------------+ -| Database | -+--------------------+ -| INFORMATION_SCHEMA | -| PERFORMANCE_SCHEMA | -| TPCH_001 | -| mysql | -| test | -+--------------------+ -5 rows in set (0.00 sec) -``` - -{{< copyable "sql" >}} - -```sql -use TPCH_001; -``` - -``` -Reading table information for completion of table and column names -You can turn off this feature to get a quicker startup with -A - -Database changed -``` - -{{< copyable "sql" >}} - -```sql -show tables; -``` - -``` -+--------------------+ -| Tables_in_TPCH_001 | -+--------------------+ -| CUSTOMER | -| LINEITEM | -| NATION | -| ORDERS | -| PART | -| PARTSUPP | -| REGION | -| SUPPLIER | -+--------------------+ -8 rows in set (0.00 sec) -``` - -## 使用范例 - -进入 spark 部署目录启动 spark-shell: - -{{< copyable "shell-regular" >}} - -```bash -cd spark && -bin/spark-shell -``` - -然后像使用原生 Spark 一样查询 TiDB 表: - -```shell -scala> spark.sql("select count(*) from lineitem").show -``` - -结果为 - -``` -+--------+ -|count(1)| -+--------+ -| 60175| -+--------+ -``` - -下面执行另一个复杂一点的 Spark SQL: - -```shell -scala> spark.sql( - """select - | l_returnflag, - | l_linestatus, - | sum(l_quantity) as sum_qty, - | sum(l_extendedprice) as sum_base_price, - | sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, - | sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, - | avg(l_quantity) as avg_qty, - | avg(l_extendedprice) as avg_price, - | avg(l_discount) as avg_disc, - | count(*) as count_order - |from - | lineitem - |where - | l_shipdate <= date '1998-12-01' - interval '90' day - |group by - | l_returnflag, - | l_linestatus - |order by - | l_returnflag, - | l_linestatus - """.stripMargin).show -``` - -结果为: - -``` -+------------+------------+---------+--------------+--------------+ -|l_returnflag|l_linestatus| sum_qty|sum_base_price|sum_disc_price| -+------------+------------+---------+--------------+--------------+ -| A| F|380456.00| 532348211.65|505822441.4861| -| N| F| 8971.00| 12384801.37| 11798257.2080| -| N| O|742802.00| 1041502841.45|989737518.6346| -| R| F|381449.00| 534594445.35|507996454.4067| -+------------+------------+---------+--------------+--------------+ -(续) ------------------+---------+------------+--------+-----------+ - sum_charge| avg_qty| avg_price|avg_disc|count_order| ------------------+---------+------------+--------+-----------+ - 526165934.000839|25.575155|35785.709307|0.050081| 14876| - 12282485.056933|25.778736|35588.509684|0.047759| 348| -1029418531.523350|25.454988|35691.129209|0.049931| 29181| - 528524219.358903|25.597168|35874.006533|0.049828| 14902| ------------------+---------+------------+--------+-----------+ -``` - -更多样例请参考 [`pingcap/tispark-test`](https://github.com/pingcap/tispark-test/tree/master/tpch/sparksql) diff --git a/how-to/maintain/ansible-operations.md b/how-to/maintain/ansible-operations.md deleted file mode 100644 index 6e79a18ab33c..000000000000 --- a/how-to/maintain/ansible-operations.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: TiDB Ansible 常见运维操作 -category: how-to ---- - -# TiDB Ansible 常见运维操作 - -## 启动集群 - -此操作会按顺序启动整个 TiDB 集群所有组件(包括 PD、TiDB、TiKV 等组件和监控组件)。 - -{{< copyable "shell-regular" >}} - -```bash -ansible-playbook start.yml -``` - -## 关闭集群 - -此操作会按顺序关闭整个 TiDB 集群所有组件(包括 PD、TiDB、TiKV 等组件和监控组件)。 - -{{< copyable "shell-regular" >}} - -```bash -ansible-playbook stop.yml -``` - -## 清除集群数据 - -此操作会关闭 TiDB、Pump、TiKV、PD 服务,并清空 Pump、TiKV、PD 数据目录。 - -{{< copyable "shell-regular" >}} - -```bash -ansible-playbook unsafe_cleanup_data.yml -``` - -## 销毁集群 - -此操作会关闭集群,并清空部署目录,若部署目录为挂载点,会报错,可忽略。 - -{{< copyable "shell-regular" >}} - -```bash -ansible-playbook unsafe_cleanup.yml -``` diff --git a/how-to/maintain/backup-and-restore/mydumper-lightning.md b/how-to/maintain/backup-and-restore/mydumper-lightning.md deleted file mode 100644 index 936641513ec7..000000000000 --- a/how-to/maintain/backup-and-restore/mydumper-lightning.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: 使用 Mydumper/TiDB Lightning 进行备份与恢复 -category: how-to -aliases: ['/docs-cn/dev/how-to/maintain/backup-and-restore/'] ---- - -# 使用 Mydumper/TiDB Lightning 进行备份与恢复 - -本文档将详细介绍如何使用 Mydumper/TiDB Lightning 对 TiDB 进行全量备份与恢复。增量备份与恢复可使用 [TiDB Binlog](/reference/tidb-binlog/overview.md)。 - -这里假定 TiDB 服务信息如下: - -|Name|Address|Port|User|Password| -|----|-------|----|----|--------| -|TiDB|127.0.0.1|4000|root|*| - -在这个备份恢复过程中,会用到下面的工具: - -- [Mydumper](/reference/tools/mydumper.md) 从 TiDB 导出数据 -- [TiDB Lightning](/reference/tools/tidb-lightning/overview.md) 导入数据到 TiDB - -## 使用 Mydumper/TiDB Lightning 全量备份恢复数据 - -`mydumper` 是一个强大的数据备份工具,具体可以参考 [`maxbube/mydumper`](https://github.com/maxbube/mydumper)。 - -可使用 [Mydumper](/reference/tools/mydumper.md) 从 TiDB 导出数据进行备份,然后用 [TiDB Lightning](/reference/tools/tidb-lightning/overview.md) 将其导入到 TiDB 里面进行恢复。 - -> **注意:** -> -> PingCAP 研发团队对 `mydumper` 进行了针对 TiDB 的适配性改造,建议使用 PingCAP 官方提供的 [Mydumper](/reference/tools/mydumper.md)。由于使用 `mysqldump` 进行数据备份和恢复都要耗费许多时间,这里也并不推荐。 - -### Mydumper/TiDB Lightning 全量备份恢复最佳实践 - -为了快速地备份恢复数据 (特别是数据量巨大的库),可以参考以下建议: - -* 导出来的数据文件应当尽可能的小,可以通过设置参数 `-F` 来控制导出来的文件大小。如果后续使用 TiDB Lightning 对备份文件进行恢复,建议把 `mydumper` -F 参数的值设置为 `256`(单位 MB);如果使用 `loader` 恢复,则建议设置为 `64`(单位 MB)。 - -## 从 TiDB 备份数据 - -我们使用 `mydumper` 从 TiDB 备份数据,如下: - -{{< copyable "shell-regular" >}} - -```bash -./bin/mydumper -h 127.0.0.1 -P 4000 -u root -t 32 -F 256 -B test -T t1,t2 --skip-tz-utc -o ./var/test -``` - -上面,我们使用 `-B test` 表明是对 `test` 这个 database 操作,然后用 `-T t1,t2` 表明只导出 `t1`,`t2` 两张表。 - -`-t 32` 表明使用 32 个线程去导出数据。`-F 256` 是将实际的表切分成一定大小的 chunk,这里的 chunk 大小为 256MB。 - -添加 `--skip-tz-utc` 参数后,会忽略掉 TiDB 与导数据的机器之间时区设置不一致的情况,禁止自动转换。 - -如果 `mydumper` 出现以下报错: - -``` -** (mydumper:27528): CRITICAL **: 13:25:09.081: Could not read data from testSchema.testTable: GC life time is shorter than transaction duration, transaction starts at 2019-08-05 21:10:01.451 +0800 CST, GC safe point is 2019-08-05 21:14:53.801 +0800 CST -``` - -就再执行两步命令: - -1. 执行 `mydumper` 命令前,查询 TiDB 集群的 [GC](/reference/garbage-collection/overview.md) 值并使用 MySQL 客户端将其调整为合适的值: - - {{< copyable "sql" >}} - - ```sql - SELECT * FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'; - ``` - - ``` - +-----------------------+------------------------------------------------------------------------------------------------+ - | VARIABLE_NAME | VARIABLE_VALUE | - +-----------------------+------------------------------------------------------------------------------------------------+ - | tikv_gc_life_time | 10m0s | - +-----------------------+------------------------------------------------------------------------------------------------+ - 1 rows in set (0.02 sec) - ``` - - {{< copyable "sql" >}} - - ```sql - update mysql.tidb set VARIABLE_VALUE = '720h' where VARIABLE_NAME = 'tikv_gc_life_time'; - ``` - -2. 执行 `mydumper` 命令后,将 TiDB 集群的 GC 值恢复到第 1 步中的初始值: - - {{< copyable "sql" >}} - - ```sql - update mysql.tidb set VARIABLE_VALUE = '10m' where VARIABLE_NAME = 'tikv_gc_life_time'; - ``` - -## 向 TiDB 恢复数据 - -使用 TiDB Lightning 将之前导出的数据导入到 TiDB,完成恢复操作。具体的使用方法见 [TiDB Lightning 使用文档](/reference/tools/tidb-lightning/tidb-backend.md) diff --git a/how-to/maintain/identify-abnormal-queries/identify-expensive-queries.md b/how-to/maintain/identify-abnormal-queries/identify-expensive-queries.md deleted file mode 100644 index 4cb2df74bc00..000000000000 --- a/how-to/maintain/identify-abnormal-queries/identify-expensive-queries.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: 定位消耗系统资源多的查询 -category: how-to -aliases: ['/docs-cn/how-to/maintain/identify-abnormal-queries/identify-aborted-queries/'] ---- - -# 定位消耗系统资源多的查询 - -TiDB 会将执行时间超过 [`tidb_expensive_query_time_threshold`](/reference/configuration/tidb-server/tidb-specific-variables.md#tidb_expensive_query_time_threshold) 限制(默认值为 60s),或使用内存超过 [`mem-quota-query`](/reference/configuration/tidb-server/configuration-file.md#mem-quota-query) 限制(默认值为 1 GB)的语句输出到 [tidb-server 日志文件](/reference/configuration/tidb-server/configuration-file.md#logfile)(默认文件为 “tidb.log”)中,用于在语句执行结束前定位消耗系统资源多的查询语句(以下简称为 expensive query),帮助用户分析和解决语句执行的性能问题。 - -注意,expensive query 日志和[慢查询日志](/how-to/maintain/identify-abnormal-queries/identify-slow-queries.md)的区别是,慢查询日志是在语句执行完后才打印,expensive query 日志可以将正在执行的语句的相关信息打印出来。当一条语句在执行过程中达到资源使用阈值时(执行时间/使用内存量),TiDB 会即时将这条语句的相关信息写入日志。 - -## Expensive query 日志示例 - -```sql -[2020/02/05 15:32:25.096 +08:00] [WARN] [expensivequery.go:167] [expensive_query] [cost_time=60.008338935s] [wait_time=0s] [request_count=1] [total_keys=70] [process_keys=65] [num_cop_tasks=1] [process_avg_time=0s] [process_p90_time=0s] [process_max_time=0s] [process_max_addr=10.0.1.9:20160] [wait_avg_time=0.002s] [wait_p90_time=0.002s] [wait_max_time=0.002s] [wait_max_addr=10.0.1.9:20160] [stats=t:pseudo] [conn_id=60026] [user=root] [database=test] [table_ids="[122]"] [txn_start_ts=414420273735139329] [mem_max="1035 Bytes (1.0107421875 KB)"] [sql="insert into t select sleep(1) from t"] -``` - -## 字段含义说明 - -基本字段: - -* `cost_time`:日志打印时语句已经花费的执行时间。 -* `stats`:语句涉及到的表或索引使用的统计信息版本。值为 pesudo 时表示无可用统计信息,需要对表或索引进行 analyze。 -* `table_ids`:语句涉及到的表的 ID。 -* `txn_start_ts`:事务的开始时间戳,也是事务的唯一 ID,可以用这个值在 TiDB 日志中查找事务相关的其他日志。 -* `sql`:SQL 语句。 - -和内存使用相关的字段: - -* `mem_max`:日志打印时语句已经使用的内存空间。该项使用两种单位标识内存使用量,分别为 Bytes 以及易于阅读的自适应单位(比如 MB、GB 等)。 - -和 SQL 执行的用户相关的字段: - -* `user`:执行语句的用户名。 -* `conn_id`:用户的连接 ID,可以用类似 `con:60026` 的关键字在 TiDB 日志中查找该连接相关的其他日志。 -* `database`:执行语句时使用的 database。 - -和 TiKV Coprocessor Task 相关的字段: - -* `wait_time`:该语句在 TiKV 的等待时间之和,因为 TiKV 的 Coprocessor 线程数是有限的,当所有的 Coprocessor 线程都在工作的时候,请求会排队;当队列中有某些请求耗时很长的时候,后面的请求的等待时间都会增加。 -* `request_count`:该语句发送的 Coprocessor 请求的数量。 -* `total_keys`:Coprocessor 扫过的 key 的数量。 -* `processed_keys`:Coprocessor 处理的 key 的数量。与 total_keys 相比,processed_keys 不包含 MVCC 的旧版本。如果 processed_keys 和 total_keys 相差很大,说明旧版本比较多。 -* `num_cop_tasks`:该语句发送的 Coprocessor 请求的数量。 -* `process_avg_time`:Coprocessor 执行 task 的平均执行时间。 -* `process_p90_time`:Coprocessor 执行 task 的 P90 分位执行时间。 -* `process_max_time`:Coprocessor 执行 task 的最长执行时间。 -* `process_max_addr`:task 执行时间最长的 Coprocessor 所在地址。 -* `wait_avg_time`:Coprocessor 上 task 的等待时间。 -* `wait_p90_time`:Coprocessor 上 task 的 P90 分位等待时间。 -* `wait_max_time`:Coprocessor 上 task 的最长等待时间。 -* `wait_max_addr`:task 等待时间最长的 Coprocessor 所在地址。 diff --git a/how-to/migrate/from-mysql-aurora.md b/how-to/migrate/from-mysql-aurora.md deleted file mode 100644 index 697cf99eff79..000000000000 --- a/how-to/migrate/from-mysql-aurora.md +++ /dev/null @@ -1,208 +0,0 @@ ---- -title: 从 MySQL 迁移数据 —— 以 Amazon Aurora MySQL 为例 -summary: 使用 DM 从 MySQL/Amazon Aurora MySQL 迁移数据。 -category: how-to -aliases: ['/docs-cn/dev/how-to/migrate/from-aurora/'] ---- - -# 从 MySQL 迁移数据 —— 以 Amazon Aurora MySQL 为例 - -本文以 [Amazon Aurora MySQL](https://aws.amazon.com/cn/rds/aurora/details/mysql-details/) 为例介绍如何使用 DM 从 MySQL 协议数据库迁移数据到 TiDB。 - -## 第 1 步:在 Aurora 集群中启用 binlog - -假设有两个 Aurora 集群需要迁移数据到 TiDB,其集群信息如下,其中 Aurora-1 包含一个独立的读取器节点。 - -| 集群 | 终端节点 | 端口 | 角色 | -|:-------- |:--- | :--- | :--- | -| Aurora-1 | pingcap-1.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | 写入器 | -| Aurora-1 | pingcap-1-us-east-2a.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | 读取器 | -| Aurora-2 | pingcap-2.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | 写入器 | - -DM 在增量同步阶段依赖 `ROW` 格式的 binlog,如果未启用 binlog 及设置正确的 binlog 格式,则不能正常使用 DM 进行数据同步,具体可参见[检查内容](https://pingcap.com/docs-cn/tidb-data-migration/stable/precheck/#检查内容)。 - -> **注意:** -> -> Aurora 读取器不能开启 binlog,因此不能作为 DM 数据迁移时的上游 master server。 - -如果需要基于 GTID 进行数据迁移,还需要为 Aurora 集群启用 GTID 支持。 - -> **注意:** -> -> 基于 GTID 的数据迁移需要 MySQL 5.7 (Aurora 2.04.1) 或更高版本。 - -### 为 Aurora 集群修改 binlog 相关参数 - -在 Aurora 集群中,binlog 相关参数是**集群参数组中的集群级参数**,有关如何为 Aurora 集群启用 binlog 支持,请参考[在复制主实例上启用二进制日志记录](https://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Replication.MySQL.html#AuroraMySQL.Replication.MySQL.EnableBinlog)。在使用 DM 进行数据迁移时,需要将 `binlog_format` 参数设置为 `ROW`。 - -如果需要基于 GTID 进行数据迁移,需要将 `gtid-mode` 与 `enforce_gtid_consistency` 均设置为 `ON`。有关如何为 Aurora 集群启用基于 GTID 的数据迁移支持,请参考 [Configuring GTID-Based Replication for an Aurora MySQL Cluster](https://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/mysql-replication-gtid.html#mysql-replication-gtid.configuring-aurora)。 - -> **注意:** -> -> 在 Aurora 管理后台中,`gtid_mode` 参数表示为 `gtid-mode`。 - -## 第 2 步:部署 DM 集群 - -目前推荐使用 DM-Ansible 部署 DM 集群,具体部署方法参照[使用 DM-Ansible 部署 DM 集群](https://pingcap.com/docs-cn/tidb-data-migration/stable/deploy-a-dm-cluster-using-ansible/)。 - -> **注意:** -> -> - 在 DM 所有的配置文件中,数据库的密码要使用 dmctl 加密后的密文。如果数据库密码为空,则不需要加密。关于如何使用 dmctl 加密明文密码,参考[使用 dmctl 加密上游 MySQL 用户密码](https://pingcap.com/docs-cn/tidb-data-migration/stable/deploy-a-dm-cluster-using-ansible/#使用-dmctl-加密上游-mysql-用户密码)。 -> - 上下游数据库用户必须拥有相应的读写权限。 - -## 第 3 步:检查集群信息 - -使用 DM-Ansible 部署 DM 集群后,相关配置信息如下: - -- DM 集群相关组件配置信息 - - | 组件 | 主机 | 端口 | - |:------|:---- |:---- | - | dm_worker1 | 172.16.10.72 | 8262 | - | dm_worker2 | 172.16.10.73 | 8262 | - | dm_master | 172.16.10.71 | 8261 | - -- 上下游数据库实例相关信息 - - | 数据库实例 | 主机 | 端口 | 用户名 | 加密密码 | - |:-------- |:--- | :--- | :--- | :--- | - | 上游 Aurora-1 | pingcap-1.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | root | VjX8cEeTX+qcvZ3bPaO4h0C80pe/1aU= | - | 上游 Aurora-2 | pingcap-2.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | root | VjX8cEeTX+qcvZ3bPaO4h0C80pe/1aU= | - | 下游 TiDB | 172.16.10.83 | 4000 | root | | - -- dm-master 进程配置文件 `{ansible deploy}/conf/dm-master.toml` 中的配置 - - ```toml - # Master 配置。 - - [[deploy]] - source-id = "mysql-replica-01" - dm-worker = "172.16.10.72:8262" - - [[deploy]] - source-id = "mysql-replica-02" - dm-worker = "172.16.10.73:8262" - ``` - -## 第 4 步:配置任务 - -假设需要将 Aurora-1 和 Aurora-2 实例的 `test_db` 库的 `test_table` 表以**全量+增量**的模式同步到下游 TiDB 的 `test_db` 库的 `test_table` 表。 - -复制并编辑 `{ansible deploy}/conf/task.yaml.example`,生成如下任务配置文件 `task.yaml`: - -```yaml -# 任务名,多个同时运行的任务不能重名。 -name: "test" -# 全量+增量 (all) 同步模式。 -task-mode: "all" -# 下游 TiDB 配置信息。 -target-database: - host: "172.16.10.83" - port: 4000 - user: "root" - password: "" - -# 当前数据同步任务需要的全部上游 MySQL 实例配置。 -mysql-instances: -- - # 上游实例或者复制组 ID,参考 `inventory.ini` 的 `source_id` 或者 `dm-master.toml` 的 `source-id 配置`。 - source-id: "mysql-replica-01" - # 需要同步的库名或表名的黑白名单的配置项名称,用于引用全局的黑白名单配置,全局配置见下面的 `black-white-list` 的配置。 - black-white-list: "global" - # Mydumper 的配置项名称,用于引用全局的 Mydumper 配置。 - mydumper-config-name: "global" - -- - source-id: "mysql-replica-02" - black-white-list: "global" - mydumper-config-name: "global" - -# 黑白名单全局配置,各实例通过配置项名引用。 -black-white-list: - global: - do-tables: # 需要同步的上游表的白名单。 - - db-name: "test_db" # 需要同步的表的库名。 - tbl-name: "test_table" # 需要同步的表的名称。 - -# Mydumper 全局配置,各实例通过配置项名引用。 -mydumpers: - global: - extra-args: "-B test_db -T test_table" # mydumper 的其他参数,从 DM 1.0.2 版本开始,DM 会自动生成 table-list 配置,在其之前的版本仍然需要人工配置。 -``` - -## 第 5 步:启动任务 - -1. 进入 dmctl 目录 `/home/tidb/dm-ansible/resources/bin/` - -2. 执行以下命令启动 dmctl - - {{< copyable "shell-regular" >}} - - ```bash - ./dmctl --master-addr 172.16.10.71:8261 - ``` - -3. 执行以下命令启动数据同步任务(`task.yaml` 是之前编辑的配置文件) - - {{< copyable "shell-regular" >}} - - ```bash - start-task ./task.yaml - ``` - - - 如果执行命令后的返回结果中不包含错误信息,则表明任务已经成功启动 - - 如果包含以下错误信息,则表明上游 Aurora 用户可能拥有 TiDB 不支持的权限类型 - - ```json - { - "id": 4, - "name": "source db dump privilege chcker", - "desc": "check dump privileges of source DB", - "state": "fail", - "errorMsg": "line 1 column 285 near \"LOAD FROM S3, SELECT INTO S3 ON *.* TO 'root'@'%' WITH GRANT OPTION\" ...", - "instruction": "", - "extra": "address of db instance - pingcap-1.h8emfqdptyc4.us-east-2.rds.amazonaws.com" - }, - { - "id": 5, - "name": "source db replication privilege chcker", - "desc": "check replication privileges of source DB", - "state": "fail", - "errorMsg": "line 1 column 285 near \"LOAD FROM S3, SELECT INTO S3 ON *.* TO 'root'@'%' WITH GRANT OPTION\" ...", - "instruction": "", - "extra": "address of db instance - pingcap-1.h8emfqdptyc4.us-east-2.rds.amazonaws.com" - } - ``` - - 此时可以选择以下两种处理方法中的任意一种进行处理后,再使用 `start-task` 尝试重新启动任务: - - 1. 为用于进行数据迁移的 Aurora 用户移除不被 TiDB 支持的不必要的权限 - 2. 如果能确保 Aurora 用户拥有 DM 所需要的权限,可以在 `task.yaml` 配置文件中添加如下顶级配置项以跳过启用任务时的前置权限检查 - - ```yaml - ignore-checking-items: ["dump_privilege", "replication_privilege"] - ``` - -## 第 6 步:查询任务 - -如需了解 DM 集群中是否存在正在运行的同步任务及任务状态等信息,可在 dmctl 内使用以下命令进行查询: - -{{< copyable "shell-regular" >}} - -```bash -query-status -``` - -> **注意:** -> -> 如果查询命令的返回结果中包含以下错误信息,则表明在全量同步的 dump 阶段不能获得相应的 lock: -> -> ``` -> Couldn't acquire global lock, snapshots will not be consistent: Access denied for user 'root'@'%' (using password: YES) -> ``` -> -> 此时如果能接受不使用 FTWL 来确保 dump 文件与 metadata 的一致或上游能暂时停止写入,可以通过为 `mydumpers` 下的 `extra-args` 添加 `--no-locks` 参数来进行绕过,具体方法为: -> -> 1. 使用 `stop-task` 停止当前由于不能正常 dump 而已经转为 paused 的任务 -> 2. 将原 `task.yaml` 中的 `extra-args: "-B test_db -T test_table"` 更新为 `extra-args: "-B test_db -T test_table --no-locks"` -> 3. 使用 `start-task` 重新启动任务 diff --git a/how-to/monitor/monitor-a-cluster.md b/how-to/monitor/monitor-a-cluster.md deleted file mode 100644 index acfa082e4d09..000000000000 --- a/how-to/monitor/monitor-a-cluster.md +++ /dev/null @@ -1,357 +0,0 @@ ---- -title: TiDB 集群监控 -category: how-to ---- - -# TiDB 集群监控 - -TiDB 提供了以下两种接口来监控集群状态: - -- [状态接口](#使用状态接口):通过 HTTP 接口对外汇报组件的信息。 -- [Metrics 接口](#使用-metrics-接口):使用 Prometheus 记录组件中各种操作的详细信息,使用 Grafana 进行可视化展示。 - -## 使用状态接口 - -状态接口用于监控组件的一些基本信息,并且可以作为 keepalive 的监测接口。另外,通过 PD 的状态接口可以看到整个 TiKV 集群的详细信息。 - -### TiDB Server - -- TiDB API 地址:`http://${host}:${port}` -- 默认端口:10080 -- 各类 `api_name` 详细信息:参见 [TiDB API 文档](https://github.com/pingcap/tidb/blob/master/docs/tidb_http_api.md) - -以下示例中,通过访问 `http://${host}:${port}/status` 获取当前 TiDB Server 的状态,并判断该 TiDB Server 是否存活。结果以 **JSON** 格式返回: - -{{< copyable "shell-regular" >}} - -```bash -curl http://127.0.0.1:10080/status -``` - -``` -{ - connections: 0, # 当前 TiDB Server 上的客户端连接数 - version: "5.7.25-TiDB-v3.0.0-beta-250-g778c3f4a5", # TiDB 版本号 - git_hash: "778c3f4a5a716880bcd1d71b257c8165685f0d70" # TiDB 当前代码的 Git Hash -} -``` - -### PD Server - -- PD API 地址:`http://${host}:${port}/pd/api/v1/${api_name}` -- 默认端口:2379 -- 各类 `api_name` 详细信息:参见 [PD API Doc](https://download.pingcap.com/pd-api-doc.html) - -通过该接口可以获取当前所有 TiKV 节点的状态以及负载均衡信息。下面以一个单节点的 TiKV 集群为例,说明用户需要了解的信息: - -{{< copyable "shell-regular" >}} - -```bash -curl http://127.0.0.1:2379/pd/api/v1/stores -``` - -``` -{ - "count": 1, # TiKV 节点数量 - "stores": [ # TiKV 节点的列表 - # 集群中单个 TiKV 节点的信息 - { - "store": { - "id": 1, - "address": "127.0.0.1:20160", - "version": "3.0.0-beta", - "state_name": "Up" - }, - "status": { - "capacity": "20 GiB", # 存储总容量 - "available": "16 GiB", # 存储剩余容量 - "leader_count": 17, - "leader_weight": 1, - "leader_score": 17, - "leader_size": 17, - "region_count": 17, - "region_weight": 1, - "region_score": 17, - "region_size": 17, - "start_ts": "2019-03-21T14:09:32+08:00", # 启动时间 - "last_heartbeat_ts": "2019-03-21T14:14:22.961171958+08:00", # 最后一次心跳的时间 - "uptime": "4m50.961171958s" - } - } - ] -``` - -## 使用 metrics 接口 - -Metrics 接口用于监控整个集群的状态和性能。 - -- 如果使用 TiDB Ansible 部署 TiDB 集群,监控系统(Prometheus 和 Grafana)会同时部署。 -- 如果使用其他方式部署 TiDB 集群,在使用 metrics 接口前,需先[部署 Prometheus 和 Grafana](#部署-prometheus-和-grafana)。 - -成功部署 Prometheus 和 Grafana 之后,[配置 Grafana](#配置-grafana)。 - -### 部署 Prometheus 和 Grafana - -假设 TiDB 的拓扑结构如下: - -| 节点 | 主机 IP | 服务 | -| :-- | :-- | :-------------- | -| Node1 | 192.168.199.113| PD1, TiDB, node_export, Prometheus, Grafana | -| Node2 | 192.168.199.114| PD2, node_export | -| Node3 | 192.168.199.115| PD3, node_export | -| Node4 | 192.168.199.116| TiKV1, node_export | -| Node5 | 192.168.199.117| TiKV2, node_export | -| Node6 | 192.168.199.118| TiKV3, node_export | - -#### 第 1 步:下载二进制包 - -下载二进制包: - -{{< copyable "shell-regular" >}} - -```bash -wget https://download.pingcap.org/prometheus-2.8.1.linux-amd64.tar.gz -wget https://download.pingcap.org/node_exporter-0.17.0.linux-amd64.tar.gz -wget https://download.pingcap.org/grafana-6.1.6.linux-amd64.tar.gz -``` - -解压二进制包: - -{{< copyable "shell-regular" >}} - -```bash -tar -xzf prometheus-2.8.1.linux-amd64.tar.gz -tar -xzf node_exporter-0.17.0.linux-amd64.tar.gz -tar -xzf grafana-6.1.6.linux-amd64.tar.gz -``` - -#### 第 2 步:在 Node1,Node2,Node3,Node4 上启动 `node_exporter` - -{{< copyable "shell-regular" >}} - -```bash -cd node_exporter-0.17.0.linux-amd64 -``` - -启动 node_exporter 服务: - -{{< copyable "shell-regular" >}} - -```bash -./node_exporter --web.listen-address=":9100" \ - --log.level="info" & -``` - -#### 第 3 步:在 Node1 上启动 Prometheus - -编辑 Prometheus 的配置文件: - -{{< copyable "shell-regular" >}} - -```bash -cd prometheus-2.8.1.linux-amd64 && -vi prometheus.yml -``` - -```ini -... - -global: - scrape_interval: 15s - evaluation_interval: 15s - # scrape_timeout 设置为全局默认值 (10s) - external_labels: - cluster: 'test-cluster' - monitor: "prometheus" - -scrape_configs: - - job_name: 'overwritten-nodes' - honor_labels: true # 不要覆盖 job 和实例的 label - static_configs: - - targets: - - '192.168.199.113:9100' - - '192.168.199.114:9100' - - '192.168.199.115:9100' - - '192.168.199.116:9100' - - '192.168.199.117:9100' - - '192.168.199.118:9100' - - - job_name: 'tidb' - honor_labels: true # 不要覆盖 job 和实例的 label - static_configs: - - targets: - - '192.168.199.113:10080' - - - job_name: 'pd' - honor_labels: true # 不要覆盖 job 和实例的 label - static_configs: - - targets: - - '192.168.199.113:2379' - - '192.168.199.114:2379' - - '192.168.199.115:2379' - - - job_name: 'tikv' - honor_labels: true # 不要覆盖 job 和实例的 label - static_configs: - - targets: - - '192.168.199.116:20180' - - '192.168.199.117:20180' - - '192.168.199.118:20180' - -... -``` - -启动 Prometheus 服务: - -{{< copyable "shell-regular" >}} - -```bash -./prometheus \ - --config.file="./prometheus.yml" \ - --web.listen-address=":9090" \ - --web.external-url="http://192.168.199.113:9090/" \ - --web.enable-admin-api \ - --log.level="info" \ - --storage.tsdb.path="./data.metrics" \ - --storage.tsdb.retention="15d" & -``` - -#### 第 4 步:在 Node1 上启动 Grafana - -编辑 Grafana 的配置文件: - -```bash -cd grafana-6.1.6 && -vi conf/grafana.ini -``` - -```ini -... - -[paths] -data = ./data -logs = ./data/log -plugins = ./data/plugins -[server] -http_port = 3000 -domain = 192.168.199.113 -[database] -[session] -[analytics] -check_for_updates = true -[security] -admin_user = admin -admin_password = admin -[snapshots] -[users] -[auth.anonymous] -[auth.basic] -[auth.ldap] -[smtp] -[emails] -[log] -mode = file -[log.console] -[log.file] -level = info -format = text -[log.syslog] -[event_publisher] -[dashboards.json] -enabled = false -path = ./data/dashboards -[metrics] -[grafana_net] -url = https://grafana.net - -... - -``` - -启动 Grafana 服务: - -{{< copyable "shell-regular" >}} - -```bash -./bin/grafana-server \ - --config="./conf/grafana.ini" & -``` - -### 配置 Grafana - -本小节介绍如何配置 Grafana。 - -#### 第 1 步:添加 Prometheus 数据源 - -1. 登录 Grafana 界面。 - - - 默认地址:`http://localhost:3000` - - 默认账户:admin - - 默认密码:admin - - > **注意:** - > - > **Change Password** 步骤可以选择 **Skip**。 - -2. 点击 Grafana 侧边栏菜单 **Configuration** 中的 **Data Source**。 - -3. 点击 **Add data source**。 - -4. 指定数据源的相关信息: - - - 在 **Name** 处,为数据源指定一个名称。 - - 在 **Type** 处,选择 **Prometheus**。 - - 在 **URL** 处,指定 Prometheus 的 IP 地址。 - - 根据需求指定其它字段。 - -5. 点击 **Add** 保存新的数据源。 - -#### 第 2 步:导入 Grafana 面板 - -执行以下步骤,为 PD Server、TiKV Server 和 TiDB Server 分别导入 Grafana 面板: - -1. 点击侧边栏的 Grafana 图标。 - -2. 在侧边栏菜单中,依次点击 **Dashboards** > **Import** 打开 **Import Dashboard** 窗口。 - -3. 点击 **Upload .json File** 上传对应的 JSON 文件(下载 [TiDB Grafana 配置文件](https://github.com/pingcap/tidb-ansible/tree/master/scripts))。 - - > **注意:** - > - > TiKV、PD 和 TiDB 面板对应的 JSON 文件分别为 `tikv_summary.json`,`tikv_details.json`,`tikv_trouble_shooting.json`,`pd.json`,`tidb.json`,`tidb_summary.json`。 - -4. 点击 **Load**。 - -5. 选择一个 Prometheus 数据源。 - -6. 点击 **Import**,Prometheus 面板即导入成功。 - -### 查看组件 metrics - -在顶部菜单中,点击 **New dashboard**,选择要查看的面板。 - -![view dashboard](/media/view-dashboard.png) - -可查看以下集群组件信息: - -+ **TiDB Server:** - + query 处理时间,可以看到延迟和吞吐 - + ddl 过程监控 - + TiKV client 相关的监控 - + PD client 相关的监控 - -+ **PD Server:** - + 命令执行的总次数 - + 某个命令执行失败的总次数 - + 某个命令执行成功的耗时统计 - + 某个命令执行失败的耗时统计 - + 某个命令执行完成并返回结果的耗时统计 - -+ **TiKV Server:** - + GC 监控 - + 执行 KV 命令的总次数 - + Scheduler 执行命令的耗时统计 - + Raft propose 命令的总次数 - + Raft 执行命令的耗时统计 - + Raft 执行命令失败的总次数 - + Raft 处理 ready 状态的总次数 diff --git a/how-to/monitor/overview.md b/how-to/monitor/overview.md deleted file mode 100644 index a23871517f14..000000000000 --- a/how-to/monitor/overview.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: TiDB 监控框架概述 -category: how-to ---- - -# TiDB 监控框架概述 - -TiDB 使用开源时序数据库 [Prometheus](https://prometheus.io) 作为监控和性能指标信息存储方案,使用 [Grafana](https://grafana.com/grafana) 作为可视化组件进行展示。 - -## Prometheus 在 TiDB 中的应用 - -Prometheus 是一个拥有多维度数据模型的、灵活的查询语句的时序数据库。Prometheus 作为热门的开源项目,拥有活跃的社区及众多的成功案例。 - -Prometheus 提供了多个组件供用户使用。目前,TiDB 使用了以下组件: - -- Prometheus Server:用于收集和存储时间序列数据。 -- Client 代码库:用于定制程序中需要的 Metric。 -- Alertmanager:用于实现报警机制。 - -其结构如下图所示: - -![Prometheus in TiDB](/media/prometheus-in-tidb.png) - -## Grafana 在 TiDB 中的应用 - -Grafana 是一个开源的 metric 分析及可视化系统。TiDB 使用 Grafana 来展示 TiDB 的各项性能指标。如下图所示: - -![Grafana in TiDB](/media/grafana-screenshot.png) diff --git a/how-to/scale/horizontally.md b/how-to/scale/horizontally.md deleted file mode 100644 index 60dd3fd6bc16..000000000000 --- a/how-to/scale/horizontally.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: TiDB 集群扩容缩容方案 -category: how-to ---- - -# TiDB 集群扩容缩容方案 - -TiDB 集群可以在不影响线上服务的情况下动态进行扩容和缩容。 - -> **注意:** -> -> 如果使用 TiDB Ansible 部署 TiDB 集群,请参考[使用 TiDB Ansible 扩容缩容](/how-to/scale/with-ansible.md)。 - -下面分别介绍如何增加或者删除 PD,TiKV 以及 TiDB 的节点。 - -下面用到的 pd-ctl 文档可以参考 [pd-control](/reference/tools/pd-control.md)。 - -## PD - -假设现在我们有三个 PD 服务,详细信息如下: - -|Name|ClientUrls|PeerUrls| -|----|----------|--------| -|pd1|`http://host1:2379`|`http://host1:2380`| -|pd2|`http://host2:2379`|`http://host2:2380`| -|pd3|`http://host3:2379`|`http://host3:2380`| - -我们可以通过 pd-ctl 来查看当前所有 PD 节点的信息: - -{{< copyable "shell-regular" >}} - -```bash -./pd-ctl -u http://host1:2379 -i ->> member -``` - -### 动态添加节点 - -我们可以使用 `join` 参数,将一个新的 PD 服务加入到现有的 PD 集群里面。 -如果我们需要添加 `pd4`,只需要在 `--join` 参数里面填入当前 PD 集群任意一个 PD 服务的 client url,比如: - -{{< copyable "shell-regular" >}} - -```bash -./bin/pd-server --name=pd4 \ - --client-urls="http://host4:2379" \ - --peer-urls="http://host4:2380" \ - --join="http://host1:2379" -``` - -### 动态删除节点 - -如果我们需要删除 `pd4`,可以通过 pd-ctl 来完成: - -{{< copyable "shell-regular" >}} - -```bash -./pd-ctl -u http://host1:2379 ->> member delete name pd4 -``` - -### 动态迁移节点 - -如果想把现有的 PD 节点迁移到新的机器上,我们可以先在新的机器上添加节点,然后把旧的机器上的节点删除掉。迁移过程中应该一个节点一个节点逐个迁移,每完成一个步骤可以先查看一下当前的所有节点信息来进行确认。 - -## TiKV - -我们可以通过 pd-ctl 来查看当前所有 TiKV 节点的信息: - -{{< copyable "shell-regular" >}} - -```bash -./pd-ctl -u http://host1:2379 ->> store -``` - -### 动态添加节点 - -动态添加一个新的 TiKV 服务非常容易,只需要在新的机器上启动一个 TiKV 服务,不需要其他特殊操作。 -新启动的 TiKV 服务会自动注册到现有集群的 PD 中,PD 会自动做负载均衡,逐步地把一部分数据迁移到新的TiKV 服务中,从而降低现有 TiKV 服务的压力。 - -### 动态删除节点 - -安全地删除(下线)一个 TiKV 服务需要先告诉 PD,这样 PD 可以先把这个 TiKV 服务上面的数据迁移到其他 TiKV 服务上,保证数据有足够的副本数。 - -假设我们需要删除 store id 为 1 的 TiKV 服务,可以通过 pd-ctl 来完成: - -{{< copyable "shell-regular" >}} - -```bash -./pd-ctl -u http://host1:2379 ->> store delete 1 -``` - -然后可以查看这个 TiKV 服务的状态: - -{{< copyable "shell-regular" >}} - -```bash -./pd-ctl -u http://host1:2379 ->> store 1 -``` - -``` -{ - "store": { - "id": 1, - "address": "127.0.0.1:21060", - "state": 1, - "state_name": "Offline" - }, - "status": { - ... - } -} -``` - -我们可以通过这个 store 的 state_name 来确定这个 store 的状态: - -- Up:这个 store 正常服务 -- Disconnected:当前没有检测到这个 store 的心跳,可能是故障或网络连接中断 -- Down:超过一小时(可通过 `max-down-time` 配置)没有收到 store 心跳,此时 PD 会为这个 store 上的数据添加副本 -- Offline:这个 store 正在将其中的 Region 转移到其他节点,此时这个 store 仍在服务中 -- Tombstone:这个 store 已经完成下线,此时 store 上已经没有数据,可以关闭实例 - -### 动态迁移节点 - -迁移 TiKV 服务也是通过先在新的机器上添加节点,然后把旧的机器上的节点下线来完成。迁移过程中可以先把新集群的机器全部添加到已有的集群中,然后再把旧的节点一个一个地下线。可以通过查看正在下线的节点的状态信息来确定这个节点是否已经完成下线,确认完成以后再下线下一个节点。 - -## TiDB - -TiDB 是一个无状态的服务,这也就意味着我们能直接添加和删除 TiDB。需要注意的是,如果我们在 TiDB 的服务的前面搭建了一个 proxy(譬如 HAProxy),则需要更新 proxy 的配置并重新载入。 diff --git a/how-to/scale/with-ansible.md b/how-to/scale/with-ansible.md deleted file mode 100644 index 8e9a39c92f86..000000000000 --- a/how-to/scale/with-ansible.md +++ /dev/null @@ -1,586 +0,0 @@ ---- -title: 使用 TiDB Ansible 扩容缩容 TiDB 集群 -category: how-to ---- - -# 使用 TiDB Ansible 扩容缩容 TiDB 集群 - -TiDB 集群可以在不影响线上服务的情况下进行扩容和缩容。 - -> **注意:** -> -> 以下缩容示例中,被移除的节点没有混合部署其他服务;如果混合部署了其他服务,不能按如下操作。 - -假设拓扑结构如下所示: - -| Name | Host IP | Services | -| ---- | ------- | -------- | -| node1 | 172.16.10.1 | PD1 | -| node2 | 172.16.10.2 | PD2 | -| node3 | 172.16.10.3 | PD3, Monitor | -| node4 | 172.16.10.4 | TiDB1 | -| node5 | 172.16.10.5 | TiDB2 | -| node6 | 172.16.10.6 | TiKV1 | -| node7 | 172.16.10.7 | TiKV2 | -| node8 | 172.16.10.8 | TiKV3 | -| node9 | 172.16.10.9 | TiKV4 | - -## 扩容 TiDB/TiKV 节点 - -例如,如果要添加两个 TiDB 节点(node101、node102),IP 地址为 172.16.10.101、172.16.10.102,可以进行如下操作: - -1. 编辑 `inventory.ini` 文件和 `hosts.ini` 文件,添加节点信息。 - - - 编辑 `inventory.ini`: - - ```ini - [tidb_servers] - 172.16.10.4 - 172.16.10.5 - 172.16.10.101 - 172.16.10.102 - - [pd_servers] - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - - [tikv_servers] - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - - [monitored_servers] - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - 172.16.10.4 - 172.16.10.5 - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - 172.16.10.101 - 172.16.10.102 - - [monitoring_servers] - 172.16.10.3 - - [grafana_servers] - 172.16.10.3 - ``` - - 现在拓扑结构如下所示: - - | Name | Host IP | Services | - | ---- | ------- | -------- | - | node1 | 172.16.10.1 | PD1 | - | node2 | 172.16.10.2 | PD2 | - | node3 | 172.16.10.3 | PD3, Monitor | - | node4 | 172.16.10.4 | TiDB1 | - | node5 | 172.16.10.5 | TiDB2 | - | **node101** | **172.16.10.101**|**TiDB3** | - | **node102** | **172.16.10.102**|**TiDB4** | - | node6 | 172.16.10.6 | TiKV1 | - | node7 | 172.16.10.7 | TiKV2 | - | node8 | 172.16.10.8 | TiKV3 | - | node9 | 172.16.10.9 | TiKV4 | - - - 编辑 `hosts.ini`: - - ```ini - [servers] - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - 172.16.10.4 - 172.16.10.5 - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - 172.16.10.101 - 172.16.10.102 - - [all:vars] - username = tidb - ntp_server = pool.ntp.org - ``` - -2. 初始化新增节点。 - - 1. 在中控机上配置部署机器 SSH 互信及 sudo 规则: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook -i hosts.ini create_users.yml -l 172.16.10.101,172.16.10.102 -u root -k - ``` - - 2. 在部署目标机器上安装 NTP 服务: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook -i hosts.ini deploy_ntp.yml -u tidb -b - ``` - - 3. 在部署目标机器上初始化节点: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook bootstrap.yml -l 172.16.10.101,172.16.10.102 - ``` - - > **注意:** - > - > 如果 `inventory.ini` 中为节点配置了别名,如 `node101 ansible_host=172.16.10.101`,执行 ansible-playbook 时 -l 请指定别名,以下步骤类似。例如:`ansible-playbook bootstrap.yml -l node101,node102` - -3. 部署新增节点: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook deploy.yml -l 172.16.10.101,172.16.10.102 - ``` - -4. 启动新节点服务: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook start.yml -l 172.16.10.101,172.16.10.102 - ``` - -5. 更新 Prometheus 配置并重启: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook rolling_update_monitor.yml --tags=prometheus - ``` - -6. 打开浏览器访问监控平台:`http://172.16.10.3:3000`,监控整个集群和新增节点的状态。 - - 可使用同样的步骤添加 TiKV 节点。但如果要添加 PD 节点,则需手动更新一些配置文件。 - -## 扩容 PD 节点 - -例如,如果要添加一个 PD 节点(node103),IP 地址为 172.16.10.103,可以进行如下操作: - -1. 编辑 `inventory.ini` 文件,添加节点信息置于 `[pd_servers]` 主机组最后一行: - - ```ini - [tidb_servers] - 172.16.10.4 - 172.16.10.5 - - [pd_servers] - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - 172.16.10.103 - - [tikv_servers] - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - - [monitored_servers] - 172.16.10.4 - 172.16.10.5 - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - 172.16.10.103 - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - - [monitoring_servers] - 172.16.10.3 - - [grafana_servers] - 172.16.10.3 - ``` - - 现在拓扑结构如下所示: - - | Name | Host IP | Services | - | ---- | ------- | -------- | - | node1 | 172.16.10.1 | PD1 | - | node2 | 172.16.10.2 | PD2 | - | node3 | 172.16.10.3 | PD3, Monitor | - | **node103** | **172.16.10.103** | **PD4** | - | node4 | 172.16.10.4 | TiDB1 | - | node5 | 172.16.10.5 | TiDB2 | - | node6 | 172.16.10.6 | TiKV1 | - | node7 | 172.16.10.7 | TiKV2 | - | node8 | 172.16.10.8 | TiKV3 | - | node9 | 172.16.10.9 | TiKV4 | - -2. 初始化新增节点: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook bootstrap.yml -l 172.16.10.103 - ``` - -3. 部署新增节点: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook deploy.yml -l 172.16.10.103 - ``` - -4. 登录新增的 PD 节点,编辑启动脚本:`{deploy_dir}/scripts/run_pd.sh` - - 1. 移除 `--initial-cluster="xxxx" \` 配置,注意这里不能在行开头加注释符 #。 - - 2. 添加 `--join="http://172.16.10.1:2379" \`,IP 地址 (172.16.10.1) 可以是集群内现有 PD IP 地址中的任意一个。 - - 3. 在新增 PD 节点中启动 PD 服务: - - {{< copyable "shell-regular" >}} - - ```bash - {deploy_dir}/scripts/start_pd.sh - ``` - - > **注意:** - > - > 启动前,需要通过 [PD Control](/reference/tools/pd-control.md) 工具确认当前 PD 节点的 `health` 状态均为 "true",否则 PD 服务会启动失败,同时日志中报错 `["join meet error"] [error="etcdserver: unhealthy cluster"]`。 - - 4. 使用 `pd-ctl` 检查新节点是否添加成功: - - {{< copyable "shell-regular" >}} - - ```bash - /home/tidb/tidb-ansible/resources/bin/pd-ctl -u "http://172.16.10.1:2379" -d member - ``` - -5. 启动监控服务: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook start.yml -l 172.16.10.103 - ``` - - > **注意:** - > - > 如果使用了别名(inventory_name),则也需要使用 `-l` 指定别名。 - -6. 更新集群的配置: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook deploy.yml - ``` - -7. 重启 Prometheus,新增扩容的 PD 节点的监控: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook stop.yml --tags=prometheus - ansible-playbook start.yml --tags=prometheus - ``` - -8. 打开浏览器访问监控平台:`http://172.16.10.3:3000`,监控整个集群和新增节点的状态。 - -> **注意:** -> -> TiKV 中的 PD Client 会缓存 PD 节点列表,但目前不会定期自动更新,只有在 PD leader 发生切换或 TiKV 重启加载最新配置后才会更新;为避免 TiKV 缓存的 PD 节点列表过旧的风险,在扩缩容 PD 完成后,PD 集群中至少要包含两个扩缩容操作前就已经存在的 PD 节点成员,如果不满足该条件需要手动执行 PD transfer leader 操作,更新 TiKV 中的 PD 缓存列表。 - -## 缩容 TiDB 节点 - -例如,如果要移除一个 TiDB 节点(node5),IP 地址为 172.16.10.5,可以进行如下操作: - -1. 停止 node5 节点上的服务: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook stop.yml -l 172.16.10.5 - ``` - -2. 编辑 `inventory.ini` 文件,移除节点信息: - - ```ini - [tidb_servers] - 172.16.10.4 - #172.16.10.5 # 注释被移除节点 - - [pd_servers] - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - - [tikv_servers] - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - - [monitored_servers] - 172.16.10.4 - #172.16.10.5 # 注释被移除节点 - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - - [monitoring_servers] - 172.16.10.3 - - [grafana_servers] - 172.16.10.3 - ``` - - 现在拓扑结构如下所示: - - | Name | Host IP | Services | - | ---- | ------- | -------- | - | node1 | 172.16.10.1 | PD1 | - | node2 | 172.16.10.2 | PD2 | - | node3 | 172.16.10.3 | PD3, Monitor | - | node4 | 172.16.10.4 | TiDB1 | - | **node5** | **172.16.10.5** | **TiDB2 已删除** | - | node6 | 172.16.10.6 | TiKV1 | - | node7 | 172.16.10.7 | TiKV2 | - | node8 | 172.16.10.8 | TiKV3 | - | node9 | 172.16.10.9 | TiKV4 | - -3. 更新 Prometheus 配置并重启: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook rolling_update_monitor.yml --tags=prometheus - ``` - -4. 打开浏览器访问监控平台:`http://172.16.10.3:3000`,监控整个集群的状态。 - -## 缩容 TiKV 节点 - -例如,如果要移除一个 TiKV 节点(node9),IP 地址为 172.16.10.9,可以进行如下操作: - -1. 使用 `pd-ctl` 从集群中移除节点: - - 1. 查看 node9 节点的 store id: - - {{< copyable "shell-regular" >}} - - ```bash - /home/tidb/tidb-ansible/resources/bin/pd-ctl -u "http://172.16.10.1:2379" -d store - ``` - - 2. 从集群中移除 node9,假如 store id 为 10: - - {{< copyable "shell-regular" >}} - - ```bash - /home/tidb/tidb-ansible/resources/bin/pd-ctl -u "http://172.16.10.1:2379" -d store delete 10 - ``` - -2. 使用 Grafana 或者 `pd-ctl` 检查节点是否下线成功(下线需要一定时间,下线节点的状态变为 Tombstone 就说明下线成功了): - - {{< copyable "shell-regular" >}} - - ```bash - /home/tidb/tidb-ansible/resources/bin/pd-ctl -u "http://172.16.10.1:2379" -d store 10 - ``` - -3. 下线成功后,停止 node9 上的服务: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook stop.yml -l 172.16.10.9 - ``` - -4. 编辑 `inventory.ini` 文件,移除节点信息: - - ```ini - [tidb_servers] - 172.16.10.4 - 172.16.10.5 - - [pd_servers] - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - - [tikv_servers] - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - #172.16.10.9 # 注释被移除节点 - - [monitored_servers] - 172.16.10.4 - 172.16.10.5 - 172.16.10.1 - 172.16.10.2 - 172.16.10.3 - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - #172.16.10.9 # 注释被移除节点 - - [monitoring_servers] - 172.16.10.3 - - [grafana_servers] - 172.16.10.3 - ``` - - 现在拓扑结构如下所示: - - | Name | Host IP | Services | - | ---- | ------- | -------- | - | node1 | 172.16.10.1 | PD1 | - | node2 | 172.16.10.2 | PD2 | - | node3 | 172.16.10.3 | PD3, Monitor | - | node4 | 172.16.10.4 | TiDB1 | - | node5 | 172.16.10.5 | TiDB2 | - | node6 | 172.16.10.6 | TiKV1 | - | node7 | 172.16.10.7 | TiKV2 | - | node8 | 172.16.10.8 | TiKV3 | - | **node9** | **172.16.10.9** | **TiKV4 已删除** | - -5. 更新 Prometheus 配置并重启: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook rolling_update_monitor.yml --tags=prometheus - ``` - -6. 打开浏览器访问监控平台:`http://172.16.10.3:3000`,监控整个集群的状态。 - -## 缩容 PD 节点 - -例如,如果要移除一个 PD 节点(node2),IP 地址为 172.16.10.2,可以进行如下操作: - -1. 使用 `pd-ctl` 从集群中移除节点: - - 1. 查看 node2 节点的 name: - - {{< copyable "shell-regular" >}} - - ```bash - /home/tidb/tidb-ansible/resources/bin/pd-ctl -u "http://172.16.10.1:2379" -d member - ``` - - 2. 从集群中移除 node2,假如 name 为 pd2: - - {{< copyable "shell-regular" >}} - - ```bash - /home/tidb/tidb-ansible/resources/bin/pd-ctl -u "http://172.16.10.1:2379" -d member delete name pd2 - ``` - -2. 使用 `pd-ctl` 检查节点是否下线成功(PD 下线会很快,结果中没有 node2 节点信息即为下线成功): - - {{< copyable "shell-regular" >}} - - ```bash - /home/tidb/tidb-ansible/resources/bin/pd-ctl -u "http://172.16.10.1:2379" -d member - ``` - -3. 下线成功后,停止 node2 上的服务: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook stop.yml -l 172.16.10.2 - ``` - - > **注意:** - > - > 此示例中 `172.16.10.2` 服务器上只有 PD 节点才可以如上操作,如果该服务器上还有其他服务(例如 `TiDB`),则还需要使用 `-t` 来指定服务(例如 `-t tidb`)。 - -4. 编辑 `inventory.ini` 文件,移除节点信息: - - ```ini - [tidb_servers] - 172.16.10.4 - 172.16.10.5 - - [pd_servers] - 172.16.10.1 - #172.16.10.2 # 注释被移除节点 - 172.16.10.3 - - [tikv_servers] - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - - [monitored_servers] - 172.16.10.4 - 172.16.10.5 - 172.16.10.1 - #172.16.10.2 # 注释被移除节点 - 172.16.10.3 - 172.16.10.6 - 172.16.10.7 - 172.16.10.8 - 172.16.10.9 - - [monitoring_servers] - 172.16.10.3 - - [grafana_servers] - 172.16.10.3 - ``` - - 现在拓扑结构如下所示: - - | Name | Host IP | Services | - | ---- | ------- | -------- | - | node1 | 172.16.10.1 | PD1 | - | **node2** | **172.16.10.2** | **PD2 已删除** | - | node3 | 172.16.10.3 | PD3, Monitor | - | node4 | 172.16.10.4 | TiDB1 | - | node5 | 172.16.10.5 | TiDB2 | - | node6 | 172.16.10.6 | TiKV1 | - | node7 | 172.16.10.7 | TiKV2 | - | node8 | 172.16.10.8 | TiKV3 | - | node9 | 172.16.10.9 | TiKV4 | - -5. 更新集群的配置: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook deploy.yml - ``` - -6. 重启 Prometheus,移除缩容的 PD 节点的监控: - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook stop.yml --tags=prometheus - ansible-playbook start.yml --tags=prometheus - ``` - -7. 打开浏览器访问监控平台:`http://172.16.10.3:3000`,监控整个集群的状态。 - -> **注意:** -> -> TiKV 中的 PD Client 会缓存 PD 节点列表,但目前不会定期自动更新,只有在 PD leader 发生切换或 TiKV 重启加载最新配置后才会更新;为避免 TiKV 缓存的 PD 节点列表过旧的风险,在扩缩容 PD 完成后,PD 集群中至少要包含两个扩缩容操作前就已经存在的 PD 节点成员,如果不满足该条件需要手动执行 PD transfer leader 操作,更新 TiKV 中的 PD 缓存列表。 \ No newline at end of file diff --git a/how-to/secure/enable-tls-between-components.md b/how-to/secure/enable-tls-between-components.md deleted file mode 100644 index 3ef9688e8f3c..000000000000 --- a/how-to/secure/enable-tls-between-components.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: 为 TiDB 组件间开启 TLS 和数据加密存储 -category: how-to ---- - -# 为 TiDB 组件间开启 TLS 和数据加密存储 - -本文档介绍 TiDB 集群如何开启 TLS 验证和数据加密存储。 - -## 开启 TLS 验证 - -本部分介绍 TiDB 集群如何开启 TLS 验证,TLS 验证支持: - -- TiDB 组件之间的双向验证,包括 TiDB、TiKV、PD 相互之间,TiKV Control 与 TiKV、PD Control 与 PD 的双向认证,以及 TiKV peer 之间、PD peer 之间。一旦开启,所有组件之间均使用验证,不支持只开启某一部分的验证。 -- MySQL Client 与 TiDB 之间的客户端对服务器身份的单向验证以及双向验证。 - -MySQL Client 与 TiDB 之间使用一套证书,TiDB 集群组件之间使用另外一套证书。 - -### TiDB 集群组件间开启 TLS(双向认证) - -1. 准备证书。 - - 推荐为 TiDB、TiKV、PD 分别准备一个 server 证书,并保证可以相互验证,而它们的各种客户端共用 client 证书。 - - 有多种工具可以生成自签名证书,如 `openssl`,`easy-rsa`,`cfssl`。 - - 这里提供一个使用 `cfssl` 生成证书的示例:[生成自签名证书](/how-to/secure/generate-self-signed-certificates.md)。 - -2. 配置证书。 - - - TiDB - - 在 `config` 文件或命令行参数中设置: - - ```toml - [security] - # Path of file that contains list of trusted SSL CAs for connection with cluster components. - cluster-ssl-ca = "/path/to/ca.pem" - # Path of file that contains X509 certificate in PEM format for connection with cluster components. - cluster-ssl-cert = "/path/to/tidb-server.pem" - # Path of file that contains X509 key in PEM format for connection with cluster components. - cluster-ssl-key = "/path/to/tidb-server-key.pem" - ``` - - - TiKV - - 在 `config` 文件或命令行参数中设置,并设置相应的 URL 为 https: - - ```toml - [security] - # set the path for certificates. Empty string means disabling secure connectoins. - ca-path = "/path/to/ca.pem" - cert-path = "/path/to/tikv-server.pem" - key-path = "/path/to/tikv-server-key.pem" - ``` - - - PD - - 在 `config` 文件或命令行参数中设置,并设置相应的 URL 为 https: - - ```toml - [security] - # Path of file that contains list of trusted SSL CAs. if set, following four settings shouldn't be empty - cacert-path = "/path/to/ca.pem" - # Path of file that contains X509 certificate in PEM format. - cert-path = "/path/to/pd-server.pem" - # Path of file that contains X509 key in PEM format. - key-path = "/path/to/pd-server-key.pem" - ``` - - 此时 TiDB 集群各个组件间已开启双向验证。 - - > **注意:** - > - > 若 TiDB 集群各个组件间已开启 TLS,在使用 tikv-ctl 或 pd-ctl 工具连接集群时,需要指定 client 证书,示例: - - {{< copyable "shell-regular" >}} - - ```bash - ./pd-ctl -u https://127.0.0.1:2379 --cacert /path/to/ca.pem --cert /path/to/client.pem --key /path/to/client-key.pem - ``` - - {{< copyable "shell-regular" >}} - - ```bash - ./tikv-ctl --host="127.0.0.1:20160" --ca-path="/path/to/ca.pem" --cert-path="/path/to/client.pem" --key-path="/path/to/clinet-key.pem" - ``` - -### MySQL 与 TiDB 间开启 TLS - -请参考 [使用加密连接](/how-to/secure/enable-tls-clients.md)。 - -## 开启数据加密存储 - -在 TiDB 集群中,用户的数据都存储在 TiKV 中,配置了 TiKV 数据加密存储功能,就代表 TiDB 集群已经加密存储了用户的数据。本部分主要介绍如何配置 TiKV 的加密存储功能。 - -### 操作流程 - -1. 生成 token 文件。 - - token 文件存储的是密钥,用于对用户数据进行加密,以及对已加密的数据进行解密。 - - {{< copyable "shell-regular" >}} - - ```bash - ./tikv-ctl random-hex --len 256 > cipher-file-256 - ``` - - > **注意:** - > - > TiKV 只接受 hex 格式的 token 文件,文件的长度必须是 2^n,并且小于等于 1024。 - -2. 配置 TiKV。 - - ```toml - [security] - # Cipher file 的存储路径 - cipher-file = "/path/to/cipher-file-256" - ``` - -> **注意:** -> -> 若使用 [Lightning](/reference/tools/tidb-lightning/overview.md) 向集群导入数据,如果目标集群开启了加密功能,Lightning 生成的 sst 文件也必须是加密的格式。 - -### 使用限制 - -目前 TiKV 数据加密存储存在以下限制: - -- 对之前没有开启加密存储的集群,不支持开启该功能。 -- 已经开启加密功能的集群,不允许关闭加密存储功能。 -- 同一集群内部,不允许部分 TiKV 实例开启该功能,部分 TiKV 实例不开启该功能。对于加密存储功能,所有 TiKV 实例要么都开启该功能,要么都不开启该功能。这是由于 TiKV 实例之间会有数据迁移,如果开启了加密存储功能,迁移过程中数据也是加密的。 diff --git a/how-to/secure/enable-tls-clients.md b/how-to/secure/enable-tls-clients.md deleted file mode 100644 index 1368d558be5e..000000000000 --- a/how-to/secure/enable-tls-clients.md +++ /dev/null @@ -1,158 +0,0 @@ ---- -title: 使用加密连接 -category: how-to ---- - -# 使用加密连接 - -TiDB 服务端默认采用非加密连接,因而具备监视信道流量能力的第三方可以知悉 TiDB 服务端与客户端之间发送和接受的数据,包括但不限于查询语句内容、查询结果等。若信道是不可信的,例如客户端是通过公网连接到 TiDB 服务端的,则非加密连接容易造成信息泄露,建议使用加密连接确保安全性。 - -TiDB 服务端支持启用基于 TLS(传输层安全)协议的加密连接,协议与 MySQL 加密连接一致,现有 MySQL 客户端如 MySQL 运维工具和 MySQL 驱动等能直接支持。TLS 的前身是 SSL,因而 TLS 有时也被称为 SSL,但由于 SSL 协议有已知安全漏洞,TiDB 实际上并未支持。TiDB 支持的 TLS/SSL 协议版本为 TLS 1.0、TLS 1.1、TLS 1.2。 - -使用加密连接后,连接将具有以下安全性质: - -- 保密性:流量明文无法被窃听; -- 完整性:流量明文无法被篡改; -- 身份验证(可选):客户端和服务端能验证双方身份,避免中间人攻击。 - -TiDB 的加密连接支持默认是关闭的,必须在 TiDB 服务端通过配置开启加密连接的支持后,才能在客户端中使用加密连接。另外,与 MySQL 一致,TiDB 加密连接是以单个连接为单位的,并且是可选的,因而对于开启了加密连接支持的 TiDB 服务端,客户端既可以选择通过加密连接安全地连接到该 TiDB 服务端,也可以选择使用普通的非加密连接。大部分 MySQL 客户端默认不采用加密连接,因此一般还要显式地要求客户端使用加密连接。 - -简单来说,要使用加密连接必须同时满足以下两个条件: - -1. TiDB 服务端配置开启加密连接的支持 -2. 客户端指定使用加密连接 - -## 配置 TiDB 启用加密连接支持 - -在启动 TiDB 时,至少需要在配置文件中同时指定 `ssl-cert` 和 `ssl-key` 参数,才能使 TiDB 服务端接受加密连接。还可以指定 `ssl-ca` 参数进行客户端身份验证(请参见[配置启用身份验证](#配置启用身份验证)章节)。 - -- [`ssl-cert`](/reference/configuration/tidb-server/configuration-file.md#ssl-cert):指定 SSL 证书文件路径 -- [`ssl-key`](/reference/configuration/tidb-server/configuration-file.md#ssl-key):指定证书文件对应的私钥 -- [`ssl-ca`](/reference/configuration/tidb-server/configuration-file.md#ssl-ca):可选,指定受信任的 CA 证书文件路径 - -参数指定的文件都为 PEM 格式。另外目前 TiDB 尚不支持加载有密码保护的私钥,因此必须提供一个没有密码的私钥文件。若提供的证书或私钥无效,则 TiDB 服务端将照常启动,但并不支持客户端加密连接到 TiDB 服务端。 - -上述证书及密钥可以使用 OpenSSL 签发和生成,也可以使用 MySQL 自带的工具 `mysql_ssl_rsa_setup` 快捷生成: - -{{< copyable "shell-regular" >}} - -```bash -mysql_ssl_rsa_setup --datadir=./certs -``` - -以上命令将在 `certs` 目录下生成以下文件: - -``` -certs -├── ca-key.pem -├── ca.pem -├── client-cert.pem -├── client-key.pem -├── private_key.pem -├── public_key.pem -├── server-cert.pem -└── server-key.pem -``` - -对应的 TiDB 配置文件参数为: - -```toml -[security] -ssl-cert = "certs/server-cert.pem" -ssl-key = "certs/server-key.pem" -``` - -若证书参数无误,则 TiDB 在启动时将会输出 `secure connection is enabled`,否则 TiDB 会输出 `secure connection is NOT ENABLED`。 - -## 配置 MySQL 客户端使用加密连接 - -MySQL 5.7 及以上版本自带的客户端默认尝试使用安全连接,若服务端不支持安全连接则自动退回到使用非安全连接;MySQL 5.7 以下版本自带的客户端默认采用非安全连接。 - -可以通过命令行参数修改客户端的连接行为,包括: - -- 强制使用安全连接,若服务端不支持安全连接则连接失败 (`--ssl-mode=REQUIRED`) -- 尝试使用安全连接,若服务端不支持安全连接则退回使用不安全连接 -- 使用不安全连接 (`--ssl-mode=DISABLED`) - -详细信息请参阅 MySQL 文档中关于[客户端配置安全连接](https://dev.mysql.com/doc/refman/5.7/en/using-encrypted-connections.html#using-encrypted-connections-client-side-configuration)的部分。 - -## 配置启用身份验证 - -若在 TiDB 服务端或 MySQL 客户端中未指定 `ssl-ca` 参数,则默认不会进行客户端或服务端身份验证,无法抵御中间人攻击,例如客户端可能会“安全地”连接到了一个伪装的服务端。可以在服务端和客户端中配置 `ssl-ca` 参数进行身份验证。一般情况下只需验证服务端身份,但也可以验证客户端身份进一步增强安全性。 - -- 若要使 MySQL 客户端验证 TiDB 服务端身份,TiDB 服务端需至少配置 `ssl-cert` 和 `ssl-key` 参数,客户端需至少指定 `--ssl-ca` 参数,且 `--ssl-mode` 至少为 `VERIFY_CA`。必须确保 TiDB 服务端配置的证书(`ssl-cert`)是由客户端 `--ssl-ca` 参数所指定的 CA 所签发的,否则身份验证失败。 -- 若要使 TiDB 服务端验证 MySQL 客户端身份,TiDB 服务端需配置 `ssl-cert`、`ssl-key`、`ssl-ca` 参数,客户端需至少指定 `--ssl-cert`、`--ssl-key` 参数。必须确保服务端配置的证书和客户端配置的证书都是由服务端配置指定的 `ssl-ca` 签发的。 -- 若要进行双向身份验证,请同时满足上述要求。 - -> **注意:** -> -> 目前 TiDB 尚不支持强制验证客户端身份,即服务端对客户端的身份验证是可选的。若客户端在 TLS 握手时未出示自己的身份证书,也能正常建立 TLS 连接。 - -## 检查当前连接是否是加密连接 - -可以通过 `SHOW STATUS LIKE "%Ssl%";` 了解当前连接的详细情况,包括是否使用了安全连接、安全连接采用的加密协议、TLS 版本号等。 - -以下是一个安全连接中执行该语句的结果。由于客户端支持的 TLS 版本号和加密协议会有所不同,执行结果相应地也会有所变化。 - -{{< copyable "sql" >}} - -```sql -SHOW STATUS LIKE "%Ssl%"; -``` - -``` -...... -| Ssl_verify_mode | 5 | -| Ssl_version | TLSv1.2 | -| Ssl_cipher | ECDHE-RSA-AES128-GCM-SHA256 | -...... -``` - -除此以外,对于 MySQL 自带客户端,还可以使用 `STATUS` 或 `\s` 语句查看连接情况: - -{{< copyable "sql" >}} - -```sql -\s -``` - -``` -... -SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256 -... -``` - -## 支持的 TLS 版本及密钥交换协议和加密算法 - -TiDB 支持的 TLS 版本及密钥交换协议和加密算法由 Golang 官方库决定。 - -### 支持的 TLS 版本 - -- TLS 1.0 -- TLS 1.1 -- TLS 1.2 - -### 支持的密钥交换协议及加密算法 - -- TLS\_RSA\_WITH\_RC4\_128\_SHA -- TLS\_RSA\_WITH\_3DES\_EDE\_CBC\_SHA -- TLS\_RSA\_WITH\_AES\_128\_CBC\_SHA -- TLS\_RSA\_WITH\_AES\_256\_CBC\_SHA -- TLS\_RSA\_WITH\_AES\_128\_CBC\_SHA256 -- TLS\_RSA\_WITH\_AES\_128\_GCM\_SHA256 -- TLS\_RSA\_WITH\_AES\_256\_GCM\_SHA384 -- TLS\_ECDHE\_ECDSA\_WITH\_RC4\_128\_SHA -- TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_CBC\_SHA -- TLS\_ECDHE\_ECDSA\_WITH\_AES\_256\_CBC\_SHA -- TLS\_ECDHE\_RSA\_WITH\_RC4\_128\_SHA -- TLS\_ECDHE\_RSA\_WITH\_3DES\_EDE\_CBC\_SHA -- TLS\_ECDHE\_RSA\_WITH\_AES\_128\_CBC\_SHA -- TLS\_ECDHE\_RSA\_WITH\_AES\_256\_CBC\_SHA -- TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_CBC\_SHA256 -- TLS\_ECDHE\_RSA\_WITH\_AES\_128\_CBC\_SHA256 -- TLS\_ECDHE\_RSA\_WITH\_AES\_128\_GCM\_SHA256 -- TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_GCM\_SHA256 -- TLS\_ECDHE\_RSA\_WITH\_AES\_256\_GCM\_SHA384 -- TLS\_ECDHE\_ECDSA\_WITH\_AES\_256\_GCM\_SHA384 -- TLS\_ECDHE\_RSA\_WITH\_CHACHA20\_POLY1305 -- TLS\_ECDHE\_ECDSA\_WITH\_CHACHA20\_POLY1305 diff --git a/how-to/secure/generate-self-signed-certificates.md b/how-to/secure/generate-self-signed-certificates.md deleted file mode 100644 index 4280b63d2d2f..000000000000 --- a/how-to/secure/generate-self-signed-certificates.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: 生成自签名证书 -category: how-to ---- - -# 生成自签名证书 - -## 概述 - -本文档提供使用 `cfssl` 生成自签名证书的示例。 - -假设实例集群拓扑如下: - -| Name | Host IP | Services | -| ----- | ----------- | ---------- | -| node1 | 172.16.10.1 | PD1, TiDB1 | -| node2 | 172.16.10.2 | PD2, TiDB2 | -| node3 | 172.16.10.3 | PD3 | -| node4 | 172.16.10.4 | TiKV1 | -| node5 | 172.16.10.5 | TiKV2 | -| node6 | 172.16.10.6 | TiKV3 | - -## 下载 cfssl - -假设使用 x86_64 Linux 主机: - -{{< copyable "shell-regular" >}} - -```bash -mkdir ~/bin && -curl -s -L -o ~/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 && -curl -s -L -o ~/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 && -chmod +x ~/bin/{cfssl,cfssljson} && -export PATH=$PATH:~/bin -``` - -## 初始化证书颁发机构 - -生成 cfssl 的默认配置,以便于之后修改: - -```bash -mkdir ~/cfssl && -cd ~/cfssl && -cfssl print-defaults config > ca-config.json && -cfssl print-defaults csr > ca-csr.json -``` - -## 生成证书 - -### 证书介绍 - -- tidb-server certificate 由 TiDB 使用,为其他组件和客户端验证 TiDB 身份。 -- tikv-server certificate 由 TiKV 使用,为其他组件和客户端验证 TiKV 身份。 -- pd-server certificate 由 PD 使用,为其他组件和客户端验证 PD 身份。 -- client certificate 用于通过 PD、TiKV、TiDB 验证客户端。例如 `pd-ctl`,`tikv-ctl`,`pd-recover`。 - -### 配置 CA 选项 - -根据实际需求修改 `ca-config.json`: - -```json -{ - "signing": { - "default": { - "expiry": "43800h" - }, - "profiles": { - "server": { - "expiry": "43800h", - "usages": [ - "signing", - "key encipherment", - "server auth", - "client auth" - ] - }, - "client": { - "expiry": "43800h", - "usages": [ - "signing", - "key encipherment", - "client auth" - ] - } - } - } -} -``` - -根据实际需求修改 `ca-csr.json` : - -```json -{ - "CN": "My own CA", - "key": { - "algo": "rsa", - "size": 2048 - }, - "names": [ - { - "C": "CN", - "L": "Beijing", - "O": "PingCAP", - "ST": "Beijing" - } - ] -} -``` - -### 生成 CA 证书 - -{{< copyable "shell-regular" >}} - -```bash -cfssl gencert -initca ca-csr.json | cfssljson -bare ca - -``` - -将会生成以下几个文件: - -``` -ca-key.pem -ca.csr -ca.pem -``` - -### 生成服务器端证书 - -`hostname` 中为各组件的 IP 地址,以及 `127.0.0.1` - -{{< copyable "shell-regular" >}} - -```bash -echo '{"CN":"tidb-server","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server -hostname="172.16.10.1,172.16.10.2,127.0.0.1" - | cfssljson -bare tidb-server && - -echo '{"CN":"tikv-server","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server -hostname="172.16.10.4,172.16.10.5,172.16.10.6,127.0.0.1" - | cfssljson -bare tikv-server && - -echo '{"CN":"pd-server","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server -hostname="172.16.10.1,172.16.10.2,172.16.10.3,127.0.0.1" - | cfssljson -bare pd-server -``` - -将会生成以下几个文件: - -``` -tidb-server-key.pem tikv-server-key.pem pd-server-key.pem -tidb-server.csr tikv-server.csr pd-server.csr -tidb-server.pem tikv-server.pem pd-server.pem -``` - -### 生成客户端证书 - -{{< copyable "shell-regular" >}} - -```bash -echo '{"CN":"client","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client -hostname="" - | cfssljson -bare client -``` - -将会生成以下几个文件: - -``` -client-key.pem -client.csr -client.pem -``` diff --git a/how-to/troubleshoot/cluster-setup.md b/how-to/troubleshoot/cluster-setup.md deleted file mode 100644 index 168eadedcdbd..000000000000 --- a/how-to/troubleshoot/cluster-setup.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: TiDB 集群故障诊断 -category: how-to ---- - -# TiDB 集群故障诊断 - -当试用 TiDB 遇到问题时,请先参考本篇文档。如果问题未解决,请按文档要求收集必要的信息通过 Github [提供给 TiDB 开发者](https://github.com/pingcap/tidb/issues/new/choose)。 - -## 如何给 TiDB 开发者报告错误 - -当使用 TiDB 遇到问题并且通过后面所列信息无法解决时,请收集以下信息并[创建新 Issue](https://github.com/pingcap/tidb/issues/new/choose): - -+ 具体的出错信息以及正在执行的操作 -+ 当前所有组件的状态 -+ 出问题组件 log 中的 error/fatal/panic 信息 -+ 机器配置以及部署拓扑 -+ dmesg 中 TiDB 组件相关的问题 - -## 数据库连接不上 - -首先请确认集群的各项服务是否已经启动,包括 tidb-server、pd-server、tikv-server。请用 ps 命令查看所有进程是否在。如果某个组件的进程已经不在了,请参考对应的章节排查错误。 - -如果所有的进程都在,请查看 tidb-server 的日志,看是否有报错?常见的错误包括: - -+ InformationSchema is out of date - - 无法连接 tikv-server,请检查 pd-server 以及 tikv-server 的状态和日志。 - -+ panic - - 程序有错误,请将具体的 panic log [提供给 TiDB 开发者](https://github.com/pingcap/tidb/issues/new/choose)。 - - 如果是清空数据并重新部署服务,请确认以下信息: - -+ pd-server、tikv-server 数据都已清空 - - tikv-server 存储具体的数据,pd-server 存储 tikv-server 中数据的的元信息。如果只清空 pd-server 或只清空 tikv-server 的数据,会导致两边数据不匹配。 - -+ 清空 pd-server 和 tikv-server 的数据并重启后,也需要重启 tidb-server - - 集群 ID 是由 pd-server 在集群初始化时随机分配,所以重新部署集群后,集群 ID 会发生变化。tidb-server 业务需要重启以获取新的集群 ID。 - -## tidb-server 启动报错 - -tidb-server 无法启动的常见情况包括: - -+ 启动参数错误 - - 请参考 [TiDB 命令行参数](/reference/configuration/tidb-server/configuration.md)。 - -+ 端口被占用:`lsof -i:port` - - 请确保 tidb-server 启动所需要的端口未被占用。 - -+ 无法连接 pd-server - - 首先检查 pd-server 的进程状态和日志,确保 pd-server 成功启动,对应端口已打开:`lsof -i:port`。 - - 若 pd-server 正常,则需要检查 tidb-server 机器和 pd-server 对应端口之间的连通性, - 确保网段连通且对应服务端口已添加到防火墙白名单中,可通过 nc 或 curl 工具检查。 - - 例如,假设 tidb 服务位于 `192.168.1.100`,无法连接的 pd 位于 `192.168.1.101`,且 2379 为其 client port, - 则可以在 tidb 机器上执行 `nc -v -z 192.168.1.101 2379`,测试是否可以访问端口。 - 或使用 `curl -v 192.168.1.101:2379/pd/api/v1/leader` 直接检查 pd 是否正常服务。 - -## tikv-server 启动报错 - -+ 启动参数错误 - - 请参考 [TiKV 启动参数](/reference/configuration/tikv-server/configuration.md)文档。 - -+ 端口被占用:`lsof -i:port` - - 请确保 tikv-server 启动所需要的端口未被占用:`lsof -i:port`。 -+ 无法连接 pd-server - - 首先检查 pd-server 的进程状态和日志。确保 pd-server 成功启动,对应端口已打开:`lsof -i:port`。 - - 若 pd-server 正常,则需要检查 tikv-server 机器和 pd-server 对应端口之间的连通性, - 确保网段连通且对应服务端口已添加到防火墙白名单中,可通过 nc 或 curl 工具检查。具体命令参考上一节。 - -+ 文件被占用 - - 不要在一个数据库文件目录上打开两个 tikv。 - -## pd-server 启动报错 - -+ 启动参数错误 - - 请参考 [PD 命令行参数](/reference/configuration/pd-server/configuration.md)文档。 - -+ 端口被占用:`lsof -i:port` - - 请确保 pd-server 启动所需要的端口未被占用:`lsof -i:port`。 - -## TiDB/TiKV/PD 进程异常退出 - -+ 进程是否是启动在前台 - - 当前终端退出给其所有子进程发送 HUP 信号,从而导致进程退出。 - -+ 是否是在命令行用过 `nohup+&` 方式直接运行 - - 这样依然可能导致进程因终端连接突然中断,作为终端 SHELL 的子进程被杀掉。 - - 推荐将启动命令写在脚本中,通过脚本运行(相当于二次 fork 启动)。 - -## TiKV 进程异常重启 - -+ 检查 dmesg 或者 syslog 里面是否有 OOM 信息 - - 如果有 OOM 信息并且杀掉的进程为 TiKV,请减少 TiKV 的 RocksDB 的各个 CF 的 `block-cache-size` 值。 - -+ 检查 TiKV 日志是否有 panic 的 log - - 提交 Issue 并附上 panic 的 log。 - -## TiDB panic - -请提供 panic 的 log。 - -## 连接被拒绝 - -+ 请确保操作系统的网络参数正确,包括但不限于 - - 连接字符串中的端口和 tidb-server 启动的端口需要一致 - - 请保证防火墙的配置正确 - -## Too many open files - -在启动进程之前,请确保 `ulimit -n` 的结果足够大,推荐设为 unlimited 或者是大于 1000000。 - -## 数据库访问超时,系统负载高 - -首先检查 [SLOW-QUERY](/how-to/maintain/identify-abnormal-queries/identify-slow-queries.md) 日志,判断是否是因为某条 SQL 语句导致。如果未能解决,请提供如下信息: - -+ 部署的拓扑结构 - - tidb-server/pd-server/tikv-server 部署了几个实例 - - 这些实例在机器上是如何分布的 -+ 机器的硬件配置 - - CPU 核数 - - 内存大小 - - 硬盘类型(SSD 还是机械硬盘) - - 是实体机还是虚拟机 -+ 机器上除了 TiDB 集群之外是否还有其他服务 -+ pd-server 和 tikv-server 是否分开部署 -+ 目前正在进行什么操作 -+ 用 `top -H` 命令查看当前占用 CPU 的线程名 -+ 最近一段时间的网络/IO 监控数据是否有异常 diff --git a/how-to/troubleshoot/tidb-lightning.md b/how-to/troubleshoot/tidb-lightning.md deleted file mode 100644 index f9ceac89079f..000000000000 --- a/how-to/troubleshoot/tidb-lightning.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -title: TiDB Lightning 故障诊断 -category: reference ---- - -# TiDB Lightning 故障诊断 - -当 Lightning 遇到不可恢复的错误时便会异常退出,并在日志中记下错误原因。一般可在日志底部找到,也可以搜索 `[error]` 字符串找出中间发生的错误。本文主要描述一些常见的错误及其解决方法。 - -## 导入速度太慢 - -TiDB Lightning 的正常速度为每条线程每 2 分钟导入一个 256 MB 的数据文件,如果速度远慢于这个数值就是有问题。导入的速度可以检查日志提及 `restore chunk … takes` 的记录,或者观察 Grafana 的监控信息。 - -导入速度太慢一般有几个原因: - -**原因 1**:`region-concurrency` 设定太高,线程间争用资源反而减低了效率。 - -1. 从日志的开头搜寻 `region-concurrency` 能知道 Lightning 读到的参数是多少。 -2. 如果 Lightning 与其他服务(如 Importer)共用一台服务器,必需**手动**将 `region-concurrency` 设为该服务器 CPU 数量的 75%。 -3. 如果 CPU 设有限额(例如从 Kubernetes 指定的上限),Lightning 可能无法自动判断出来,此时亦需要**手动**调整 `region-concurrency`。 - -**原因 2**:表结构太复杂。 - -每条索引都会额外增加键值对。如果有 N 条索引,实际导入的大小就差不多是 Mydumper 文件的 N+1 倍。如果索引不太重要,可以考虑先从 schema 去掉,待导入完成后再使用 `CREATE INDEX` 加回去。 - -**原因 3**:Lightning 版本太旧。 - -试试最新的版本吧!可能会有改善。 - -## checksum failed: checksum mismatched remote vs local - -**原因**:本地数据源跟目标数据库某个表的校验和不一致。这通常有更深层的原因: - -1. 这张表可能本身已有数据,影响最终结果。 -2. 如果目标数据库的校验和全是 0,表示没有发生任何导入,有可能是集群太忙无法接收任何数据。 -3. 如果数据源是由机器生成而不是从 Mydumper 备份的,需确保数据符合表的限制,例如: - - * 自增 (AUTO_INCREMENT) 的列需要为正数,不能为 0。 - * 唯一键和主键 (UNIQUE and PRIMARY KEYs) 不能有重复的值。 -4. 如果 TiDB Lightning 之前失败停机过,但没有正确重启,可能会因为数据不同步而出现校验和不一致。 - -**解决办法**: - -1. 使用 `tidb-lightning-ctl` 把出错的表删除,然后重启 Lightning 重新导入那些表。 - - {{< copyable "shell-regular" >}} - - ```sh - tidb-lightning-ctl --config conf/tidb-lightning.toml --checkpoint-error-destroy=all - ``` - -2. 把断点存放在外部数据库(修改 `[checkpoint] dsn`),减轻目标集群压力。 - -3. 参考[如何正确重启 TiDB Lightning](/faq/tidb-lightning.md#如何正确重启-tidb-lightning)中的解决办法。 - -## Checkpoint for … has invalid status:(错误码) - -**原因**:[断点续传](/reference/tools/tidb-lightning/checkpoints.md)已启用。Lightning 或 Importer 之前发生了异常退出。为了防止数据意外损坏,Lightning 在错误解决以前不会启动。 - -错误码是小于 25 的整数,可能的取值是 0、3、6、9、12、14、15、17、18、20、21。整数越大,表示异常退出所发生的步骤在导入流程中越晚。 - -**解决办法**: - -如果错误原因是非法数据源,使用 `tidb-lightning-ctl` 删除已导入数据,并重启 Lightning。 - -{{< copyable "shell-regular" >}} - -```sh -tidb-lightning-ctl --config conf/tidb-lightning.toml --checkpoint-error-destroy=all -``` - -其他解决方法请参考[断点续传的控制](/reference/tools/tidb-lightning/checkpoints.md#断点续传的控制)。 - -## ResourceTemporarilyUnavailable("Too many open engines …: …") - -**原因**:并行打开的引擎文件 (engine files) 超出 `tikv-importer` 里的限制。这可能由配置错误引起。即使配置没问题,如果 `tidb-lightning` 曾经异常退出,也有可能令引擎文件残留在打开的状态,占据可用的数量。 - -**解决办法**: - -1. 提高 `tikv-importer.toml` 内 `max-open-engines` 的值。这个设置主要由内存决定,计算公式为: - - 最大内存使用量 ≈ `max-open-engines` × `write-buffer-size` × `max-write-buffer-number` - -2. 降低 `table-concurrency` + `index-concurrency`,使之低于 `max-open-engines`。 - -3. 重启 `tikv-importer` 来强制移除所有引擎文件 (默认值为 `./data.import/`)。这样也会丢弃导入了一半的表,所以启动 Lightning 前必须清除过期的断点记录: - - {{< copyable "shell-regular" >}} - - ```sh - tidb-lightning-ctl --config conf/tidb-lightning.toml --checkpoint-error-destroy=all - ``` - -## cannot guess encoding for input file, please convert to UTF-8 manually - -**原因**:Lightning 只支持 UTF-8 和 GB-18030 编码的表架构。此错误代表数据源不是这里任一个编码。也有可能是文件中混合了不同的编码,例如,因为在不同的环境运行过 `ALTER TABLE`,使表架构同时出现 UTF-8 和 GB-18030 的字符。 - -**解决办法**: - -1. 编辑数据源,保存为纯 UTF-8 或 GB-18030 的文件。 -2. 手动在目标数量库创建所有的表,然后设置 `[mydumper] no-schema = true` 跳过创建表的步骤。 -3. 设置 `[mydumper] character-set = "binary"` 跳过这个检查。但是这样可能使数据库出现乱码。 - -## [sql2kv] sql encode error = [types:1292]invalid time format: '{1970 1 1 …}' - -**原因**: 一个 `timestamp` 类型的时间戳记录了不存在的时间值。时间值不存在是由于夏时制切换或超出支持的范围(1970 年 1 月 1 日至 2038 年 1 月 19 日)。 - -**解决办法**: - -1. 确保 Lightning 与数据源时区一致。 - - * 使用 TiDB Ansible 部署的话,修正 [`inventory.ini`] 下的 `timezone` 变量。 - - ```ini - # inventory.ini - [all:vars] - timezone = Asia/Shanghai - ``` - - * 手动部署的话,通过设定 `$TZ` 环境变量强制时区设定。 - - 强制使用 Asia/Shanghai 时区: - - {{< copyable "shell-regular" >}} - - ```sh - TZ='Asia/Shanghai' bin/tidb-lightning -config tidb-lightning.toml - ``` - -2. 导出数据时,必须加上 `--skip-tz-utc` 选项。 - -3. 确保整个集群使用的是同一最新版本的 `tzdata` (2018i 或更高版本)。 - - 如果你使用的是 CentOS 机器,你可以运行 `yum info tzdata` 命令查看 `tzdata` 的版本及是否有更新。然后运行 `yum upgrade tzdata` 命令升级 `tzdata`。 diff --git a/how-to/upgrade/from-previous-version.md b/how-to/upgrade/from-previous-version.md deleted file mode 100644 index e9302a3c45af..000000000000 --- a/how-to/upgrade/from-previous-version.md +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: TiDB 最新开发版升级操作指南 -category: how-to -aliases: ['/docs-cn/dev/how-to/upgrade/to-tidb-3.0/','/docs-cn/dev/how-to/upgrade/rolling-updates-with-ansible/'] ---- - -# TiDB 最新开发版升级操作指南 - -本文档适用于从 TiDB 2.0、2.1、3.0、3.1 版本升级至 TiDB 最新开发版 (latest) 以及从开发版的较低版本升级至最新版本。目前,TiDB 最新开发版兼容 [TiDB Binlog Cluster 版本](/reference/tidb-binlog/overview.md)。 - -> **警告:** -> -> TiDB 最新开发版为非稳定版本,不建议用于生产环境。 - -## 升级兼容性说明 - -- 不支持在升级后回退至 2.1.x 或更旧版本 -- 从 2.0.6 之前的版本升级到 latest 之前,需要确认集群中是否存在正在运行中的 DDL 操作,特别是耗时的 `Add Index` 操作,等 DDL 操作完成后再执行升级操作 -- 2.1 及之后版本启用了并行 DDL,早于 2.0.1 版本的集群,无法滚动升级到 latest 版本,可以选择下面两种方案: - - 停机升级,直接从早于 2.0.1 的 TiDB 版本升级到 latest 版本 - - 先滚动升级到 2.0.1 或者之后的 2.0.x 版本,再滚动升级到 latest 版本 - -> **注意:** -> -> 在升级的过程中不要执行 DDL 请求,否则可能会出现行为未定义的问题。 - -## 在中控机器上安装 TiDB Ansible 及其依赖 - -> **注意:** -> -> 如果已经安装了 TiDB Ansible 及其依赖,可跳过该步骤。 - -TiDB Ansible 最新开发版依赖 2.4.2 及以上但不高于 2.7.11 的 Ansible 版本(`2.4.2 ≦ ansible ≦ 2.7.11`,建议 2.7.11 版本),另依赖 Python 模块:`jinja2 ≧ 2.9.6` 和 `jmespath ≧ 0.9.0`。为方便管理依赖,建议使用 `pip` 安装 TiDB Ansible 及其依赖,可参照[在中控机器上安装 TiDB Ansible 及其依赖](/how-to/deploy/orchestrated/ansible.md#在中控机器上安装-tidb-ansible-及其依赖) 进行安装。离线环境参照[在中控机器上离线安装 TiDB Ansible 及其依赖](/how-to/deploy/orchestrated/offline-ansible.md#在中控机器上离线安装-tidb-ansible-及其依赖)。 - -安装完成后,可通过以下命令查看版本: - -{{< copyable "shell-regular" >}} - -```bash -ansible --version -``` - -``` -ansible 2.7.11 -``` - -{{< copyable "shell-regular" >}} - -```bash -pip show jinja2 -``` - -``` -Name: Jinja2 -Version: 2.10 -``` - -{{< copyable "shell-regular" >}} - -```bash -pip show jmespath -``` - -``` -Name: jmespath -Version: 0.9.0 -``` - -> **注意:** -> -> 请务必按以上文档安装 TiDB Ansible 及其依赖。确认 Jinja2 版本是否正确,否则启动 Grafana 时会报错。确认 jmespath 版本是否正确,否则滚动升级 TiKV 时会报错。 - -## 在中控机器上下载 TiDB Ansible - -以 `tidb` 用户登录中控机并进入 `/home/tidb` 目录,备份 TiDB 2.0、2.1、3.0 或其他低版本的 tidb-ansible 文件夹: - -{{< copyable "shell-regular" >}} - -```bash -mv tidb-ansible tidb-ansible-bak -``` - -下载 TiDB latest 版本对应的 tidb-ansible [**下载 TiDB Ansible**](/how-to/deploy/orchestrated/ansible.md#在中控机器上下载-tidb-ansible),默认的文件夹名称为 `tidb-ansible`。 - -{{< copyable "shell-regular" >}} - -```bash -git clone https://github.com/pingcap/tidb-ansible.git -``` - -## 编辑 inventory.ini 文件和配置文件 - -以 `tidb` 用户登录中控机并进入 `/home/tidb/tidb-ansible` 目录。 - -### 编辑 `inventory.ini` 文件 - -编辑 `inventory.ini` 文件,IP 信息参照备份文件 `/home/tidb/tidb-ansible-bak/inventory.ini`。 - -以下变量配置,需要重点确认,变量含义可参考 [inventory.ini 变量调整](/how-to/deploy/orchestrated/ansible.md#调整其它变量可选)。 - -1. 请确认 `ansible_user` 配置的是普通用户。为统一权限管理,不再支持使用 root 用户远程安装。默认配置中使用 `tidb` 用户作为 SSH 远程用户及程序运行用户。 - - ``` - ## Connection - # ssh via normal user - ansible_user = tidb - ``` - - 可参考[如何配置 SSH 互信及 sudo 规则](/how-to/deploy/orchestrated/ansible.md#第-5-步在中控机上配置部署机器-ssh-互信及-sudo-规则)自动配置主机间互信。 - -2. `process_supervision` 变量请与之前版本保持一致,默认推荐使用 `systemd`。 - - ``` - # process supervision, [systemd, supervise] - process_supervision = systemd - ``` - - 如需变更,可参考[如何调整进程监管方式从 supervise 到 systemd](/how-to/deploy/orchestrated/ansible.md#如何调整进程监管方式从-supervise-到-systemd),先使用备份 `/home/tidb/tidb-ansible-bak/` 分支变更进程监管方式再升级。 - -### 编辑 TiDB 集群组件配置文件 - -如之前自定义过 TiDB 集群组件配置文件,请参照备份文件修改 `/home/tidb/tidb-ansible/conf` 下对应配置文件。 - -**注意以下参数变更:** - -- TiKV 配置中 `end-point-concurrency` 变更为 `high-concurrency`、`normal-concurrency` 和 `low-concurrency` 三个参数: - - ``` - readpool: - coprocessor: - # Notice: if CPU_NUM > 8, default thread pool size for coprocessors - # will be set to CPU_NUM * 0.8. - # high-concurrency: 8 - # normal-concurrency: 8 - # low-concurrency: 8 - ``` - - > **注意:** - > - > 2.0 版本升级且单机多 TiKV 实例(进程)情况下,需要修改这三个参数。 - > - > 推荐设置:TiKV 实例数量 \* 参数值 = CPU 核心数量 \* 0.8 - -- TiKV 配置中不同 CF 中的 `block-cache-size` 参数变更为 `block-cache`: - - ``` - storage: - block-cache: - capacity: "1GB" - ``` - - > **注意:** - > - > 单机多 TiKV 实例(进程)情况下,需要修改 `capacity` 参数。 - > - > 推荐设置:`capacity` = (MEM_TOTAL * 0.5 / TiKV 实例数量) - -- TiKV 配置中单机多实例场景需要额外配置 `tikv_status_port` 端口: - - ``` - [tikv_servers] - TiKV1-1 ansible_host=172.16.10.4 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv1" - TiKV1-2 ansible_host=172.16.10.4 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv1" - TiKV2-1 ansible_host=172.16.10.5 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv2" - TiKV2-2 ansible_host=172.16.10.5 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv2" - TiKV3-1 ansible_host=172.16.10.6 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv3" - TiKV3-2 ansible_host=172.16.10.6 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv3" - ``` - - > **注意:** - > - > 最新开发版单机多 TiKV 实例(进程)情况下,需要添加 `tikv_status_port` 参数。 - > - > 配置前,注意检查端口是否有冲突。 - -## 下载 TiDB latest binary 到中控机 - -确认 `tidb-ansible/inventory.ini` 文件中 `tidb_version = latest`,然后执行以下命令下载 TiDB latest binary 到中控机。 - -{{< copyable "shell-regular" >}} - -```bash -ansible-playbook local_prepare.yml -``` - -## 滚动升级 TiDB 集群组件 - -- 如果 `process_supervision` 变量使用默认的 `systemd` 参数: - - - 当前集群版本 < 3.0,则通过 `excessive_rolling_update.yml` 滚动升级 TiDB 集群。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook excessive_rolling_update.yml - ``` - - - 当前集群版本 ≥ 3.0.0,滚动升级及日常滚动重启 TiDB 集群,使用 `rolling_update.yml`。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook rolling_update.yml - ``` - -- 如果 `process_supervision` 变量使用的是 `supervise` 参数,无论当前集群为哪个版本,均通过 `rolling_update.yml` 来滚动升级 TiDB 集群。 - - {{< copyable "shell-regular" >}} - - ```bash - ansible-playbook rolling_update.yml - ``` - -## 滚动升级 TiDB 监控组件 - -{{< copyable "shell-regular" >}} - -```bash -ansible-playbook rolling_update_monitor.yml -``` diff --git a/hybrid-deployment-topology.md b/hybrid-deployment-topology.md new file mode 100644 index 000000000000..ab3f8da4e591 --- /dev/null +++ b/hybrid-deployment-topology.md @@ -0,0 +1,103 @@ +--- +title: 混合部署拓扑 +summary: 介绍混合部署 TiDB 集群的拓扑结构。 +category: how-to +--- + +# 混合部署拓扑 + +本文介绍 TiDB 集群的 TiKV 和 TiDB 混合部署拓扑以及主要参数。常见的场景为,部署机为多路 CPU 处理器,内存也充足,为提高物理机资源利用率,可单机多实例部署,即 TiDB、TiKV 通过 numa 绑核,隔离 CPU 资源。PD 和 Prometheus 混合部署,但两者的数据目录需要使用独立的文件系统。 + +## 拓扑信息 + +| 实例 | 个数 | 物理机配置 | IP | 配置 | +| :-- | :-- | :-- | :-- | :-- | +| TiDB | 6 | 32 VCore 64GB | 10.0.1.1
10.0.1.2
10.0.1.3 | 配置 numa 绑核操作 | +| PD | 3 | 16 VCore 32 GB | 10.0.1.4
10.0.1.5
10.0.1.6 | 配置 location_lables 参数 | +| TiKV | 6 | 32 VCore 64GB | 10.0.1.7
10.0.1.8
10.0.1.9 | 1. 区分实例级别的 port、status_port;
2. 配置全局参数 readpool、storage 以及 raftstore;
3. 配置实例级别 host 维度的 labels;
4. 配置 numa 绑核操作| +| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.10 | 默认配置 | + +### 拓扑模版 + +[简单混部配置模板](https://github.com/pingcap/docs-cn/blob/release-4.0/config-templates/simple-multi-instance.yaml) + +[详细混部配置模板](https://github.com/pingcap/docs-cn/blob/release-4.0/config-templates/complex-multi-instance.yaml) + +### 混合部署的关键参数介绍 + +本节介绍单机多实例的关键参数,主要用于 TiDB、TiKV 的单机多实例部署场景。你需要按照提供的计算公式,将结果填写至上一步的配置模板中。 + +- TiKV 进行配置优化 + + - readpool 线程池自适应,配置 `readpool.unified.max-thread-count` 参数可以使 `readpool.storage` 和 `readpool.coprocessor` 共用统一线程池,同时要分别设置自适应开关。 + + - 开启 `readpool.storage` 和 `readpool.coprocessor`: + + ```yaml + readpool.storage.use-unified-pool: false + readpool.coprocessor.use-unified-pool: true + ``` + + - 计算公式如下: + + ``` + readpool.unified.max-thread-count = cores * 0.8 / TiKV 数量 + ``` + + - storage CF (all RocksDB column families) 内存自适应,配置 `storage.block-cache.capacity` 参数即可实现 CF 之间自动平衡内存使用。 + + - `storage.block-cache` 默认开启 CF 自适应,无需修改。 + + ```yaml + storage.block-cache.shared: true + ``` + + - 计算公式如下: + + ``` + storage.block-cache.capacity = (MEM_TOTAL * 0.5 / TiKV 实例数量) + ``` + + - 如果多个 TiKV 实例部署在同一块物理磁盘上,需要在 tikv 配置中添加 capacity 参数: + + ``` + raftstore.capacity = 磁盘总容量 / TiKV 实例数量 + ``` + +- label 调度配置 + + 由于采用单机多实例部署 TiKV,为了避免物理机宕机导致 Region Group 默认 3 副本的 2 副本丢失,导致集群不可用的问题,可以通过 label 来实现 PD 智能调度,保证同台机器的多 TiKV 实例不会出现 Region Group 只有 2 副本的情况。 + + - TiKV 配置 + + 相同物理机配置相同的 host 级别 label 信息: + + ```yml + config: + server.labels: + host: tikv1 + ``` + + - PD 配置 + + PD 需要配置 labels 类型来识别并调度 Region: + + ```yml + pd: + replication.location-labels: ["host"] + ``` + +- `numa_node` 绑核 + + - 在实例参数模块配置对应的 `numa_node` 参数,并添加对应的物理 CPU 的核数; + + - numa 绑核使用前,确认已经安装 numactl 工具,以及物理机对应的物理机 CPU 的信息后,再进行参数配置; + + - `numa_node` 这个配置参数与 `numactl --membind` 配置对应。 + +> **注意:** +> +> - 编辑配置文件模版时,注意修改必要参数、IP、端口及目录。 +> - 各个组件的 deploy_dir,默认会使用 global 中的 `/-`。例如 tidb 端口指定 4001,则 deploy_dir 默认为 /tidb-deploy/tidb-4001。因此,在多实例场景下指定非默认端口时,无需再次指定目录。 +> - 无需手动创建配置文件中的 `tidb` 用户,TiUP cluster 组件会在部署主机上自动创建该用户。可以自定义用户,也可以和中控机的用户保持一致。 +> - 如果部署目录配置为相对路径,会部署在用户家目录下。 diff --git a/identify-expensive-queries.md b/identify-expensive-queries.md new file mode 100644 index 000000000000..4d1a4604f3a6 --- /dev/null +++ b/identify-expensive-queries.md @@ -0,0 +1,53 @@ +--- +title: 定位消耗系统资源多的查询 +category: how-to +aliases: ['/docs-cn/stable/how-to/maintain/identify-abnormal-queries/identify-expensive-queries/'] +--- + +# 定位消耗系统资源多的查询 + +TiDB 会将执行时间超过 [`tidb_expensive_query_time_threshold`](/tidb-specific-system-variables.md#tidb_expensive_query_time_threshold) 限制(默认值为 60s),或使用内存超过 [`mem-quota-query`](/tidb-configuration-file.md#mem-quota-query) 限制(默认值为 1 GB)的语句输出到 [tidb-server 日志文件](/tidb-configuration-file.md#logfile)(默认文件为 “tidb.log”)中,用于在语句执行结束前定位消耗系统资源多的查询语句(以下简称为 expensive query),帮助用户分析和解决语句执行的性能问题。 + +注意,expensive query 日志和[慢查询日志](/identify-slow-queries.md)的区别是,慢查询日志是在语句执行完后才打印,expensive query 日志可以将正在执行的语句的相关信息打印出来。当一条语句在执行过程中达到资源使用阈值时(执行时间/使用内存量),TiDB 会即时将这条语句的相关信息写入日志。 + +## Expensive query 日志示例 + +```sql +[2020/02/05 15:32:25.096 +08:00] [WARN] [expensivequery.go:167] [expensive_query] [cost_time=60.008338935s] [wait_time=0s] [request_count=1] [total_keys=70] [process_keys=65] [num_cop_tasks=1] [process_avg_time=0s] [process_p90_time=0s] [process_max_time=0s] [process_max_addr=10.0.1.9:20160] [wait_avg_time=0.002s] [wait_p90_time=0.002s] [wait_max_time=0.002s] [wait_max_addr=10.0.1.9:20160] [stats=t:pseudo] [conn_id=60026] [user=root] [database=test] [table_ids="[122]"] [txn_start_ts=414420273735139329] [mem_max="1035 Bytes (1.0107421875 KB)"] [sql="insert into t select sleep(1) from t"] +``` + +## 字段含义说明 + +基本字段: + +* `cost_time`:日志打印时语句已经花费的执行时间。 +* `stats`:语句涉及到的表或索引使用的统计信息版本。值为 pesudo 时表示无可用统计信息,需要对表或索引进行 analyze。 +* `table_ids`:语句涉及到的表的 ID。 +* `txn_start_ts`:事务的开始时间戳,也是事务的唯一 ID,可以用这个值在 TiDB 日志中查找事务相关的其他日志。 +* `sql`:SQL 语句。 + +和内存使用相关的字段: + +* `mem_max`:日志打印时语句已经使用的内存空间。该项使用两种单位标识内存使用量,分别为 Bytes 以及易于阅读的自适应单位(比如 MB、GB 等)。 + +和 SQL 执行的用户相关的字段: + +* `user`:执行语句的用户名。 +* `conn_id`:用户的连接 ID,可以用类似 `con:60026` 的关键字在 TiDB 日志中查找该连接相关的其他日志。 +* `database`:执行语句时使用的 database。 + +和 TiKV Coprocessor Task 相关的字段: + +* `wait_time`:该语句在 TiKV 的等待时间之和,因为 TiKV 的 Coprocessor 线程数是有限的,当所有的 Coprocessor 线程都在工作的时候,请求会排队;当队列中有某些请求耗时很长的时候,后面的请求的等待时间都会增加。 +* `request_count`:该语句发送的 Coprocessor 请求的数量。 +* `total_keys`:Coprocessor 扫过的 key 的数量。 +* `processed_keys`:Coprocessor 处理的 key 的数量。与 total_keys 相比,processed_keys 不包含 MVCC 的旧版本。如果 processed_keys 和 total_keys 相差很大,说明旧版本比较多。 +* `num_cop_tasks`:该语句发送的 Coprocessor 请求的数量。 +* `process_avg_time`:Coprocessor 执行 task 的平均执行时间。 +* `process_p90_time`:Coprocessor 执行 task 的 P90 分位执行时间。 +* `process_max_time`:Coprocessor 执行 task 的最长执行时间。 +* `process_max_addr`:task 执行时间最长的 Coprocessor 所在地址。 +* `wait_avg_time`:Coprocessor 上 task 的等待时间。 +* `wait_p90_time`:Coprocessor 上 task 的 P90 分位等待时间。 +* `wait_max_time`:Coprocessor 上 task 的最长等待时间。 +* `wait_max_addr`:task 等待时间最长的 Coprocessor 所在地址。 diff --git a/how-to/maintain/identify-abnormal-queries/identify-slow-queries.md b/identify-slow-queries.md similarity index 95% rename from how-to/maintain/identify-abnormal-queries/identify-slow-queries.md rename to identify-slow-queries.md index b32cfc4037d9..e234ca0084e2 100644 --- a/how-to/maintain/identify-abnormal-queries/identify-slow-queries.md +++ b/identify-slow-queries.md @@ -1,14 +1,14 @@ --- title: 慢查询日志 category: how-to -aliases: ['/docs-cn/sql/slow-query/','/docs-cn/dev/how-to/maintain/identify-slow-queries/'] +aliases: ['/docs-cn/stable/how-to/maintain/identify-abnormal-queries/identify-slow-queries/'] --- # 慢查询日志 -TiDB 会将执行时间超过 [slow-threshold](/reference/configuration/tidb-server/configuration-file.md#slow-threshold)(默认值为 300 毫秒)的语句输出到 [slow-query-file](/reference/configuration/tidb-server/configuration-file.md#slow-query-file)(默认值:"tidb-slow.log")日志文件中,用于帮助用户定位慢查询语句,分析和解决 SQL 执行的性能问题。 +TiDB 会将执行时间超过 [slow-threshold](/tidb-configuration-file.md#slow-threshold)(默认值为 300 毫秒)的语句输出到 [slow-query-file](/tidb-configuration-file.md#slow-query-file)(默认值:"tidb-slow.log")日志文件中,用于帮助用户定位慢查询语句,分析和解决 SQL 执行的性能问题。 -TiDB 默认启用慢查询日志,可以修改配置 [`enable-slow-log`](/reference/configuration/tidb-server/configuration-file.md#enable-slow-log) 来启用或禁用它。 +TiDB 默认启用慢查询日志,可以修改配置 [`enable-slow-log`](/tidb-configuration-file.md#enable-slow-log) 来启用或禁用它。 ## 日志示例 @@ -32,6 +32,8 @@ TiDB 默认启用慢查询日志,可以修改配置 [`enable-slow-log`](/refer # Cop_backoff_rpcPD_total_times: 200 Cop_backoff_rpcPD_total_time: 0.2 Cop_backoff_rpcPD_max_time: 0.2 Cop_backoff_rpcPD_max_addr: 127.0.0.1 Cop_backoff_rpcPD_avg_time: 0.2 Cop_backoff_rpcPD_p90_time: 0.2 # Cop_backoff_rpcTiKV_total_times: 200 Cop_backoff_rpcTiKV_total_time: 0.2 Cop_backoff_rpcTiKV_max_time: 0.2 Cop_backoff_rpcTiKV_max_addr: 127.0.0.1 Cop_backoff_rpcTiKV_avg_time: 0.2 Cop_backoff_rpcTiKV_p90_time: 0.2 # Mem_max: 525211 +# Prepared: false +# Plan_from_cache: false # Succ: true # Plan: tidb_decode_plan('ZJAwCTMyXzcJMAkyMAlkYXRhOlRhYmxlU2Nhbl82CjEJMTBfNgkxAR0AdAEY1Dp0LCByYW5nZTpbLWluZiwraW5mXSwga2VlcCBvcmRlcjpmYWxzZSwgc3RhdHM6cHNldWRvCg==') insert into t select * from t; @@ -57,6 +59,8 @@ Slow Query 基础信息: * `Succ`:表示语句是否执行成功。 * `Backoff_time`:表示语句遇到需要重试的错误时在重试前等待的时间,常见的需要重试的错误有以下几种:遇到了 lock、Region 分裂、`tikv server is busy`。 * `Plan`:表示语句的执行计划,用 `select tidb_decode_plan('xxx...')` SQL 语句可以解析出具体的执行计划。 +* `Prepared`:表示这个语句是否是 `Prepare` 或 `Execute` 的请求。 +* `Plan_from_cache`:表示这个语句是否命中了执行计划缓存。 和事务执行相关的字段: @@ -70,7 +74,7 @@ Slow Query 基础信息: 和内存使用相关的字段: -* `Memory_max`:表示执行期间 TiDB 使用的最大内存空间,单位为 byte。 +* `Mem_max`:表示执行期间 TiDB 使用的最大内存空间,单位为 byte。 和 SQL 执行的用户相关的字段: @@ -102,7 +106,7 @@ Slow Query 基础信息: ## 慢日志内存映射表 -用户可通过查询 `INFORMATION_SCHEMA.SLOW_QUERY` 表来查询慢查询日志中的内容,表中列名和慢日志中字段名一一对应,表结构可查看 [Information Schema](/reference/system-databases/information-schema.md#information-schema) 中关于 `SLOW_QUERY` 表的介绍。 +用户可通过查询 `INFORMATION_SCHEMA.SLOW_QUERY` 表来查询慢查询日志中的内容,表中列名和慢日志中字段名一一对应,表结构可查看 [Information Schema](/system-tables/system-table-information-schema.md#information-schema) 中关于 `SLOW_QUERY` 表的介绍。 > **注意:** > @@ -154,7 +158,7 @@ where time > '2020-03-10 00:00:00' > > 如果指定时间范围内的慢日志文件被删除,或者并没有慢查询,则查询结果会返回空。 -TiDB 4.0 中新增了 [`CLUSTER_SLOW_QUERY`](/reference/system-databases/information-schema.md#cluster_slow_query-表) 系统表,用来查询所有 TiDB 节点的慢查询信息,表结构在 `SLOW_QUERY` 的基础上多增加了 `INSTANCE` 列,表示该行慢查询信息来自的 TiDB 节点地址。使用方式和 [`SLOW_QUERY`](/reference/system-databases/information-schema.md#slow_query-表) 系统表一样。 +TiDB 4.0 中新增了 [`CLUSTER_SLOW_QUERY`](/system-tables/system-table-information-schema.md#cluster_slow_query-表) 系统表,用来查询所有 TiDB 节点的慢查询信息,表结构在 `SLOW_QUERY` 的基础上多增加了 `INSTANCE` 列,表示该行慢查询信息来自的 TiDB 节点地址。使用方式和 [`SLOW_QUERY`](/system-tables/system-table-information-schema.md#slow_query-表) 系统表一样。 关于查询 `CLUSTER_SLOW_QUERY` 表,TiDB 会把相关的计算和判断下推到其他节点执行,而不是把其他节点的慢查询数据都取回来在一台 TiDB 上执行。 diff --git a/reference/performance/join-reorder.md b/join-reorder.md similarity index 90% rename from reference/performance/join-reorder.md rename to join-reorder.md index ffee60f5d63c..9531b38fd46a 100644 --- a/reference/performance/join-reorder.md +++ b/join-reorder.md @@ -1,6 +1,7 @@ --- title: Join Reorder 算法简介 category: reference +aliases: ['/docs-cn/stable/reference/performance/join-reorder/'] --- # Join Reorder 算法简介 @@ -32,4 +33,4 @@ category: reference - 目前并不支持 Outer Join 的 Join Reorder - 受结果集的计算算法所限并不会保证一定会选到合适的 Join order -目前 TiDB 中支持使用 `STRAIGHT_JOIN` 语法来强制指定一种 Join 顺序,参见[语法元素说明](/reference/sql/statements/select.md#语法元素说明)。 +目前 TiDB 中支持使用 `STRAIGHT_JOIN` 语法来强制指定一种 Join 顺序,参见[语法元素说明](/sql-statements/sql-statement-select.md#语法元素说明)。 diff --git a/key-features.md b/key-features.md deleted file mode 100644 index 4d739c036396..000000000000 --- a/key-features.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: TiDB 核心特性 -category: introduction ---- - -# TiDB 核心特性 - -本文详细介绍 TiDB 的两大核心特性:水平扩展与高可用。 - -## 水平扩展 - -无限水平扩展是 TiDB 的一大特点,这里说的水平扩展包括两方面:计算能力和存储能力。TiDB Server 负责处理 SQL 请求,随着业务的增长,可以简单的添加 TiDB Server 节点,提高整体的处理能力,提供更高的吞吐。TiKV 负责存储数据,随着数据量的增长,可以部署更多的 TiKV Server 节点解决数据 Scale 的问题。PD 会在 TiKV 节点之间以 Region 为单位做调度,将部分数据迁移到新加的节点上。所以在业务的早期,可以只部署少量的服务实例(推荐至少部署 3 个 TiKV, 3 个 PD,2 个 TiDB),随着业务量的增长,按照需求添加 TiKV 或者 TiDB 实例。 - -## 高可用 - -高可用是 TiDB 的另一大特点,TiDB/TiKV/PD 这三个组件都能容忍部分实例失效,不影响整个集群的可用性。下面分别说明这三个组件的可用性、单个实例失效后的后果以及如何恢复。 - -- TiDB - - TiDB 是无状态的,推荐至少部署两个实例,前端通过负载均衡组件对外提供服务。当单个实例失效时,会影响正在这个实例上进行的 Session,从应用的角度看,会出现单次请求失败的情况,重新连接后即可继续获得服务。单个实例失效后,可以重启这个实例或者部署一个新的实例。 - -- PD - - PD 是一个集群,通过 Raft 协议保持数据的一致性,单个实例失效时,如果这个实例不是 Raft 的 leader,那么服务完全不受影响;如果这个实例是 Raft 的 leader,会重新选出新的 Raft leader,自动恢复服务。PD 在选举的过程中无法对外提供服务,这个时间大约是3秒钟。推荐至少部署三个 PD 实例,单个实例失效后,重启这个实例或者添加新的实例。 - -- TiKV - - TiKV 是一个集群,通过 Raft 协议保持数据的一致性(副本数量可配置,默认保存三副本),并通过 PD 做负载均衡调度。单个节点失效时,会影响这个节点上存储的所有 Region。对于 Region 中的 Leader 节点,会中断服务,等待重新选举;对于 Region 中的 Follower 节点,不会影响服务。当某个 TiKV 节点失效,并且在一段时间内(默认 30 分钟)无法恢复,PD 会将其上的数据迁移到其他的 TiKV 节点上。 diff --git a/keywords.md b/keywords.md new file mode 100644 index 000000000000..0fc49e1141e3 --- /dev/null +++ b/keywords.md @@ -0,0 +1,680 @@ +--- +title: 关键字 +category: reference +summary: 本文介绍 TiDB 的关键字。 +aliases: ['/docs-cn/stable/keywords-and-reserved-words/','/docs-cn/stable/reference/sql/language-structure/keywords-and-reserved-words/'] +--- + +# 关键字 + +本文介绍 TiDB 的关键字,对保留字和非保留字作出区分,并汇总所有的关键字以供查询使用。 + +关键字是 SQL 语句中具有特殊含义的单词,例如 `SELECT`,`UPDATE`,`DELETE` 等等。它们之中有的能够直接作为标识符,被称为**非保留关键字**(简称**非保留字**),但有需要经过特殊处理才能作为标识符的字,被称为**保留关键字**(简称**保留字**)。 + +对于保留字,必须使用反引号包裹,才能作为标识符被使用。例如: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE select (a INT); +``` + +``` +ERROR 1105 (HY000): line 0 column 19 near " (a INT)" (total length 27) +``` + +{{< copyable "sql" >}} + +```sql +CREATE TABLE `select` (a INT); +``` + +``` +Query OK, 0 rows affected (0.09 sec) +``` + +而非保留字则不需要反引号也能直接作为标识符。例如 `BEGIN` 和 `END` 是非保留字,以下语句能够正常执行: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE `select` (BEGIN int, END int); +``` + +``` +Query OK, 0 rows affected (0.09 sec) +``` + +有一种特殊情况,如果使用了限定符 `.`,那么也不需要用反引号: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE test.select (BEGIN int, END int); +``` + +``` +Query OK, 0 rows affected (0.08 sec) +``` + +下表列出了 TiDB 中所有的关键字。其中保留字用 `(R)` 来标识。[窗口函数](/functions-and-operators/window-functions.md)的保留字用 `(R-Window)` 来标识: + +{{< tabs-panel "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" >}} + +A + +- ACCOUNT +- ACTION +- ADD (R) +- ADMIN (R) +- ADVISE +- AFTER +- AGAINST +- AGO +- ALGORITHM +- ALL (R) +- ALTER (R) +- ALWAYS +- ANALYZE (R) +- AND (R) +- ANY +- AS (R) +- ASC (R) +- ASCII +- AUTO_ID_CACHE +- AUTO_INCREMENT +- AUTO_RANDOM +- AUTO_RANDOM_BASE +- AVG +- AVG_ROW_LENGTH + +B + +- BACKEND +- BACKUP +- BACKUPS +- BEGIN +- BETWEEN (R) +- BIGINT (R) +- BINARY (R) +- BINDING +- BINDINGS +- BINLOG +- BIT +- BLOB (R) +- BLOCK +- BOOL +- BOOLEAN +- BOTH (R) +- BTREE +- BUCKETS (R) +- BUILTINS (R) +- BY (R) +- BYTE + +C + +- CACHE +- CANCEL (R) +- CAPTURE +- CASCADE (R) +- CASCADED +- CASE (R) +- CHAIN +- CHANGE (R) +- CHAR (R) +- CHARACTER (R) +- CHARSET +- CHECK (R) +- CHECKPOINT +- CHECKSUM +- CIPHER +- CLEANUP +- CLIENT +- CMSKETCH (R) +- COALESCE +- COLLATE (R) +- COLLATION +- COLUMN (R) +- COLUMNS +- COLUMN_FORMAT +- COMMENT +- COMMIT +- COMMITTED +- COMPACT +- COMPRESSED +- COMPRESSION +- CONCURRENCY +- CONFIG +- CONNECTION +- CONSISTENT +- CONSTRAINT (R) +- CONTEXT +- CONVERT (R) +- CPU +- CREATE (R) +- CROSS (R) +- CSV_BACKSLASH_ESCAPE +- CSV_DELIMITER +- CSV_HEADER +- CSV_NOT_NULL +- CSV_NULL +- CSV_SEPARATOR +- CSV_TRIM_LAST_SEPARATORS +- CUME_DIST (R-Window) +- CURRENT +- CURRENT_DATE (R) +- CURRENT_ROLE (R) +- CURRENT_TIME (R) +- CURRENT_TIMESTAMP (R) +- CURRENT_USER (R) +- CYCLE + +D + +- DATA +- DATABASE (R) +- DATABASES (R) +- DATE +- DATETIME +- DAY +- DAY_HOUR (R) +- DAY_MICROSECOND (R) +- DAY_MINUTE (R) +- DAY_SECOND (R) +- DDL (R) +- DEALLOCATE +- DECIMAL (R) +- DEFAULT (R) +- DEFINER +- DELAYED (R) +- DELAY_KEY_WRITE +- DELETE (R) +- DENSE_RANK (R-Window) +- DEPTH (R) +- DESC (R) +- DESCRIBE (R) +- DIRECTORY +- DISABLE +- DISCARD +- DISK +- DISTINCT (R) +- DISTINCTROW (R) +- DIV (R) +- DO +- DOUBLE (R) +- DRAINER (R) +- DROP (R) +- DUAL (R) +- DUPLICATE +- DYNAMIC + +E + +- ELSE (R) +- ENABLE +- ENCLOSED (R) +- ENCRYPTION +- END +- ENFORCED +- ENGINE +- ENGINES +- ENUM +- ERROR +- ERRORS +- ESCAPE +- ESCAPED (R) +- EVENT +- EVENTS +- EVOLVE +- EXCEPT (R) +- EXCHANGE +- EXCLUSIVE +- EXECUTE +- EXISTS (R) +- EXPANSION +- EXPIRE +- EXPLAIN (R) +- EXTENDED + +F + +- FALSE (R) +- FAULTS +- FIELDS +- FILE +- FIRST +- FIRST_VALUE (R-Window) +- FIXED +- FLOAT (R) +- FLUSH +- FOLLOWING +- FOR (R) +- FORCE (R) +- FOREIGN (R) +- FORMAT +- FROM (R) +- FULL +- FULLTEXT (R) +- FUNCTION + +G + +- GENERAL +- GENERATED (R) +- GLOBAL +- GRANT (R) +- GRANTS +- GROUP (R) +- GROUPS (R-Window) + +H + +- HASH +- HAVING (R) +- HIGH_PRIORITY (R) +- HISTORY +- HOSTS +- HOUR +- HOUR_MICROSECOND (R) +- HOUR_MINUTE (R) +- HOUR_SECOND (R) + +I + +- IDENTIFIED +- IF (R) +- IGNORE (R) +- IMPORT +- IMPORTS +- IN (R) +- INCREMENT +- INCREMENTAL +- INDEX (R) +- INDEXES +- INFILE (R) +- INNER (R) +- INSERT (R) +- INSERT_METHOD +- INSTANCE +- INT (R) +- INT1 (R) +- INT2 (R) +- INT3 (R) +- INT4 (R) +- INT8 (R) +- INTEGER (R) +- INTERVAL (R) +- INTO (R) +- INVISIBLE +- INVOKER +- IO +- IPC +- IS (R) +- ISOLATION +- ISSUER + +J + +- JOB (R) +- JOBS (R) +- JOIN (R) +- JSON + +K + +- KEY (R) +- KEYS (R) +- KEY_BLOCK_SIZE +- KILL (R) + +L + +- LABELS +- LAG (R-Window) +- LANGUAGE +- LAST +- LASTVAL +- LAST_BACKUP +- LAST_VALUE (R-Window) +- LEAD (R-Window) +- LEADING (R) +- LEFT (R) +- LESS +- LEVEL +- LIKE (R) +- LIMIT (R) +- LINEAR (R) +- LINES (R) +- LIST +- LOAD (R) +- LOCAL +- LOCALTIME (R) +- LOCALTIMESTAMP (R) +- LOCATION +- LOCK (R) +- LOGS +- LONG (R) +- LONGBLOB (R) +- LONGTEXT (R) +- LOW_PRIORITY (R) + +M + +- MASTER +- MATCH (R) +- MAXVALUE (R) +- MAX_CONNECTIONS_PER_HOUR +- MAX_IDXNUM +- MAX_MINUTES +- MAX_QUERIES_PER_HOUR +- MAX_ROWS +- MAX_UPDATES_PER_HOUR +- MAX_USER_CONNECTIONS +- MB +- MEDIUMBLOB (R) +- MEDIUMINT (R) +- MEDIUMTEXT (R) +- MEMORY +- MERGE +- MICROSECOND +- MINUTE +- MINUTE_MICROSECOND (R) +- MINUTE_SECOND (R) +- MINVALUE +- MIN_ROWS +- MOD (R) +- MODE +- MODIFY +- MONTH + +N + +- NAMES +- NATIONAL +- NATURAL (R) +- NCHAR +- NEVER +- NEXT +- NEXTVAL +- NO +- NOCACHE +- NOCYCLE +- NODEGROUP +- NODE_ID (R) +- NODE_STATE (R) +- NOMAXVALUE +- NOMINVALUE +- NONE +- NOT (R) +- NOWAIT +- NO_WRITE_TO_BINLOG (R) +- NTH_VALUE (R-Window) +- NTILE (R-Window) +- NULL (R) +- NULLS +- NUMERIC (R) +- NVARCHAR + +O + +- OFFSET +- ON (R) +- ONLINE +- ONLY +- ON_DUPLICATE +- OPEN +- OPTIMISTIC (R) +- OPTIMIZE (R) +- OPTION (R) +- OPTIONALLY (R) +- OR (R) +- ORDER (R) +- OUTER (R) +- OUTFILE (R) +- OVER (R-Window) + +P + +- PACK_KEYS +- PAGE +- PARSER +- PARTIAL +- PARTITION (R) +- PARTITIONING +- PARTITIONS +- PASSWORD +- PERCENT_RANK (R-Window) +- PER_DB +- PER_TABLE +- PESSIMISTIC (R) +- PLUGINS +- PRECEDING +- PRECISION (R) +- PREPARE +- PRE_SPLIT_REGIONS +- PRIMARY (R) +- PRIVILEGES +- PROCEDURE (R) +- PROCESS +- PROCESSLIST +- PROFILE +- PROFILES +- PUMP (R) + +Q + +- QUARTER +- QUERIES +- QUERY +- QUICK + +R + +- RANGE (R) +- RANK (R-Window) +- RATE_LIMIT +- READ (R) +- REAL (R) +- REBUILD +- RECOVER +- REDUNDANT +- REFERENCES (R) +- REGEXP (R) +- REGION (R) +- REGIONS (R) +- RELEASE (R) +- RELOAD +- REMOVE +- RENAME (R) +- REORGANIZE +- REPAIR +- REPEAT (R) +- REPEATABLE +- REPLACE (R) +- REPLICA +- REPLICATION +- REQUIRE (R) +- RESPECT +- RESTORE +- RESTORES +- RESTRICT (R) +- REVERSE +- REVOKE (R) +- RIGHT (R) +- RLIKE (R) +- ROLE +- ROLLBACK +- ROUTINE +- ROW (R) +- ROWS (R-Window) +- ROW_COUNT +- ROW_FORMAT +- ROW_NUMBER (R-Window) +- RTREE + +S + +- SAMPLES (R) +- SECOND +- SECONDARY_ENGINE +- SECONDARY_LOAD +- SECONDARY_UNLOAD +- SECOND_MICROSECOND (R) +- SECURITY +- SELECT (R) +- SEND_CREDENTIALS_TO_TIKV +- SEPARATOR +- SEQUENCE +- SERIAL +- SERIALIZABLE +- SESSION +- SET (R) +- SETVAL +- SHARD_ROW_ID_BITS +- SHARE +- SHARED +- SHOW (R) +- SHUTDOWN +- SIGNED +- SIMPLE +- SKIP_SCHEMA_FILES +- SLAVE +- SLOW +- SMALLINT (R) +- SNAPSHOT +- SOME +- SOURCE +- SPATIAL (R) +- SPLIT (R) +- SQL (R) +- SQL_BIG_RESULT (R) +- SQL_BUFFER_RESULT +- SQL_CACHE +- SQL_CALC_FOUND_ROWS (R) +- SQL_NO_CACHE +- SQL_SMALL_RESULT (R) +- SQL_TSI_DAY +- SQL_TSI_HOUR +- SQL_TSI_MINUTE +- SQL_TSI_MONTH +- SQL_TSI_QUARTER +- SQL_TSI_SECOND +- SQL_TSI_WEEK +- SQL_TSI_YEAR +- SSL (R) +- START +- STARTING (R) +- STATS (R) +- STATS_AUTO_RECALC +- STATS_BUCKETS (R) +- STATS_HEALTHY (R) +- STATS_HISTOGRAMS (R) +- STATS_META (R) +- STATS_PERSISTENT +- STATS_SAMPLE_PAGES +- STATUS +- STORAGE +- STORED (R) +- STRAIGHT_JOIN (R) +- STRICT_FORMAT +- SUBJECT +- SUBPARTITION +- SUBPARTITIONS +- SUPER +- SWAPS +- SWITCHES +- SYSTEM_TIME + +T + +- TABLE (R) +- TABLES +- TABLESPACE +- TABLE_CHECKSUM +- TEMPORARY +- TEMPTABLE +- TERMINATED (R) +- TEXT +- THAN +- THEN (R) +- TIDB (R) +- TIFLASH (R) +- TIKV_IMPORTER +- TIME +- TIMESTAMP +- TINYBLOB (R) +- TINYINT (R) +- TINYTEXT (R) +- TO (R) +- TOPN (R) +- TRACE +- TRADITIONAL +- TRAILING (R) +- TRANSACTION +- TRIGGER (R) +- TRIGGERS +- TRUE (R) +- TRUNCATE +- TYPE + +U + +- UNBOUNDED +- UNCOMMITTED +- UNDEFINED +- UNICODE +- UNION (R) +- UNIQUE (R) +- UNKNOWN +- UNLOCK (R) +- UNSIGNED (R) +- UPDATE (R) +- USAGE (R) +- USE (R) +- USER +- USING (R) +- UTC_DATE (R) +- UTC_TIME (R) +- UTC_TIMESTAMP (R) + +V + +- VALIDATION +- VALUE +- VALUES (R) +- VARBINARY (R) +- VARCHAR (R) +- VARCHARACTER (R) +- VARIABLES +- VARYING (R) +- VIEW +- VIRTUAL (R) +- VISIBLE + +W + +- WARNINGS +- WEEK +- WEIGHT_STRING +- WHEN (R) +- WHERE (R) +- WIDTH (R) +- WINDOW (R-Window) +- WITH (R) +- WITHOUT +- WRITE (R) + +X + +- X509 +- XOR (R) + +Y + +- YEAR +- YEAR_MONTH (R) + +Z + +- ZEROFILL (R) diff --git a/licensing.md b/licensing.md new file mode 100644 index 000000000000..4140a0571267 --- /dev/null +++ b/licensing.md @@ -0,0 +1,3 @@ +--- +draft: true +--- \ No newline at end of file diff --git a/reference/sql/language-structure/literal-values.md b/literal-values.md similarity index 82% rename from reference/sql/language-structure/literal-values.md rename to literal-values.md index c4d5c89bd5ab..5074a8745a49 100644 --- a/reference/sql/language-structure/literal-values.md +++ b/literal-values.md @@ -1,8 +1,11 @@ --- title: 字面值 category: reference +aliases: ['/docs-cn/stable/reference/sql/language-structure/literal-values/'] --- +TiDB 字面值包括字符字面值、数值字面值、时间日期字面值、十六进制、二进制字面值和 NULL 字面值。以下分别对这些字面值进行一一介绍。 + # 字面值 ## String Literals @@ -24,11 +27,12 @@ String Literals 是一个 bytes 或者 characters 的序列,两端被单引号 如果 `ANSI_QUOTES` SQL MODE 开启了,那么只有单引号内的会被认为是 String Literals,对于双引号内的字符串,会被认为是一个 identifier。 -binary string 是一串 bytes 组成的字符串,每一个 binary string 有一个叫做 `binary` 的 character set 和 collation。一个非二进制的字符串是一个由字符组成的字符串,它有除 `binary` 外的 character set和与之兼容的 collation。 +字符串分为以下两种: -对于两种字符串类型,比较都是基于每个字符的数值。对于 binary string 而言,比较单元就是字节,对于非二进制的字符串,那么单元就是字符,而有的字符集支持多字节字符。 ++ 二进制字符串 (binary string):由字节序列构成,它的 charset 和 collation 都是 `binary`,在互相比较时利用**字节**作为单位。 ++ 非二进制字符串:由字符序列构成,有除 `binary` 以外的多种 charset 和 collation,在相互比较时用**字符**(一个字符可能包含多个字节,取决于 charset 的选择)作为单位。 -一个 String Literal 可以拥有一个可选的 `character set introducer` 和 `COLLATE clause`,可以用来指派特定的字符集跟 collation(TiDB 对此只是做了语法上的兼容,并不实质做处理)。 +一个 String Literal 可以拥有一个可选的 `character set introducer` 和 `COLLATE clause`,可以用来指定特定的 charset 和 collation。 ``` [_charset_name]'string' [COLLATE collation_name] @@ -54,26 +58,23 @@ SELECT n'some text'; SELECT _utf8'some text'; ``` -转义字符: - -- \\0: ASCII NUL (X'00') 字符 -- \\': 单引号 -- \\": 双引号 -- \\b: 退格符号 -- \\n: 换行符 -- \\r: 回车符 -- \\t: tab 符(制表符) -- \\z: ASCII 26 (Ctrl + Z) -- \\\\: 反斜杠 \\ -- \\%: \% -- \\_: \_ +要在字符串中表示某些特殊字符,可以利用转义字符进行转义: -如果要在 string literal 中使用 `'` 或者 `"`,有以下几种办法: +| 转义字符 | 含义 | +| :------ | :---- | +| \\0 | ASCII NUL (X'00') 字符 | +| \\' | 单引号 | +| \\" | 双引号 | +| \\b | 退格符号 | +| \\n | 换行符 | +| \\r | 回车符 | +| \\t | tab 符(制表符) | +| \\z | ASCII 26 (Ctrl + Z) | +| \\\\ | 反斜杠 \\ | +| \\% | \% | +| \\_ | \_ | -* 在 `'` 引用的字符串中,可以用 `''` 来表示单引号。 -* 在 `"` 引用的字符串中,可以用 `""` 来表示双引号。 -* 前面接转义符`\`。 -* 在 `'` 中表示 `"` 或者在 `"` 中表示 `'` 都不需要特别的处理。 +如果要在 `'` 包围的字符串中表示 `"`,或者在 `"` 包围的字符串中表示 `'`,可以不使用转义字符。 更多[细节](https://dev.mysql.com/doc/refman/5.7/en/string-literals.html)。 @@ -89,13 +90,61 @@ integer 可以包括 `.` 作为小数点分隔,数字前可以有 `-` 或者 ` 更多[细节](https://dev.mysql.com/doc/refman/5.7/en/number-literals.html)。 -## NULL Values +## Date and Time Literals -`NULL` 代表数据为空,它是大小写不敏感的,与 `\N`(大小写敏感) 同义。 +Date 跟 Time 字面值有几种格式,例如用字符串表示,或者直接用数字表示。在 TiDB 里面,当 TiDB 期望一个 Date 的时候,它会把 `'2017-08-24'`, `'20170824'`,`20170824` 当做是 Date。 -> **注意:** -> -> `NULL` 跟 `0` 并不一样,跟空字符串 `''` 也不一样。 +TiDB 的 Date 值有以下几种格式: + +* `'YYYY-MM-DD'` 或者 `'YY-MM-DD'`,这里的 `-` 分隔符并不是严格的,可以是任意的标点符号。比如 `'2017-08-24'`,`'2017&08&24'`, `'2012@12^31'` 都是一样的。唯一需要特别对待的是 '.' 号,它被当做是小数点,用于分隔整数和小数部分。 + Date 和 Time 部分可以被 'T' 分隔,它的作用跟空格符是一样的,例如 `2017-8-24 10:42:00` 跟 `2017-8-24T10:42:00` 是一样的。 +* `'YYYYMMDDHHMMSS'` 或者 `'YYMMDDHHMMSS'`,例如 `'20170824104520'` 和 `'170824104520'` 被当做是 `'2017-08-24 10:45:20'`,但是如果你提供了一个超过范围的值,例如`'170824304520'`,那这就不是一个有效的 Date 字面值。 +* `YYYYMMDDHHMMSS` 或者 `YYMMDDHHMMSS` 注意这里没有单引号或者双引号,是一个数字。例如 `20170824104520`表示为 `'2017-08-24 10:45:20'`。 + +DATETIME 或者 TIMESTAMP 值可以接一个小数部分,用来表示微秒(精度最多到小数点后 6 位),用小数点 `.` 分隔。 + +如果 Date 的 year 部分只有两个数字,这是有歧义的(推荐使用四个数字的格式),TiDB 会尝试用以下的规则来解释: + +* year 值如果在 `70-99` 范围,那么被转换成 `1970-1999`。 +* year 值如果在 `00-69` 范围,那么被转换成 `2000-2069`。 + +对于小于 10 的 month 或者 day 值,`'2017-8-4'` 跟 `'2017-08-04'` 是一样的。对于 Time 也是一样,比如 `'2017-08-24 1:2:3'` 跟 `'2017-08-24 01:02:03'`是一样的。 + +在需要 Date 或者 Time 的语境下, 对于数值,TiDB 会根据数值的长度来选定指定的格式: + +* 6 个数字,会被解释为 `YYMMDD`。 +* 12 个数字,会被解释为 `YYMMDDHHMMSS`。 +* 8 个数字,会解释为 `YYYYMMDD`。 +* 14 个数字,会被解释为 `YYYYMMDDHHMMSS`。 + +对于 Time 类型,TiDB 用以下格式来表示: + +* `'D HH:MM:SS'`,或者 `'HH:MM:SS'`,`'HH:MM'`,`'D HH:MM'`,`'D HH'`,`'SS'`,这里的 D 表示 days,合法的范围是 `0-34`。 +* 数值 `HHMMSS`,例如 `231010` 被解释为`'23:10:10'`。 +* 数值 `SS`,`MMSS`,`HHMMSS` 都是可以被当做 Time。 + +Time 类型的小数点也是 `.`,精度最多小数点后 6 位。 + +更多[细节](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html)。 + +## Boolean Literals + +常量 `TRUE` 和 `FALSE` 等于 1 和 0,它是大小写不敏感的。 + +{{< copyable "sql" >}} + +```sql +SELECT TRUE, true, tRuE, FALSE, FaLsE, false; +``` + +``` ++------+------+------+-------+-------+-------+ +| TRUE | true | tRuE | FALSE | FaLsE | false | ++------+------+------+-------+-------+-------+ +| 1 | 1 | 1 | 0 | 0 | 0 | ++------+------+------+-------+-------+-------+ +1 row in set (0.00 sec) +``` ## Hexadecimal Literals @@ -141,8 +190,7 @@ select X'0aff'; +---------+ | X'0aff' | +---------+ -| - | +| 0x0aff | +---------+ 1 row in set (0.00 sec) ``` @@ -181,65 +229,9 @@ SELECT X'54694442'; 1 row in set (0.00 sec) ``` -## Date and Time Literals - -Date 跟 Time 字面值有几种格式,例如用字符串表示,或者直接用数字表示。在 TiDB 里面,当 TiDB 期望一个 Date 的时候,它会把 `'2017-08-24'`, `'20170824'`,`20170824` 当做是 Date。 - -TiDB 的 Date 值有以下几种格式: - -* `'YYYY-MM-DD'` 或者 `'YY-MM-DD'`,这里的 `-` 分隔符并不是严格的,可以是任意的标点符号。比如 `'2017-08-24'`,`'2017&08&24'`, `'2012@12^31'` 都是一样的。唯一需要特别对待的是 '.' 号,它被当做是小数点,用于分隔整数和小数部分。 - Date 和 Time 部分可以被 'T' 分隔,它的作用跟空格符是一样的,例如 `2017-8-24 10:42:00` 跟 `2017-8-24T10:42:00` 是一样的。 -* `'YYYYMMDDHHMMSS'` 或者 `'YYMMDDHHMMSS'`,例如 `'20170824104520'` 和 `'170824104520'` 被当做是 `'2017-08-24 10:45:20'`,但是如果你提供了一个超过范围的值,例如`'170824304520'`,那这就不是一个有效的 Date 字面值。 -* `YYYYMMDDHHMMSS` 或者 `YYMMDDHHMMSS` 注意这里没有单引号或者双引号,是一个数字。例如 `20170824104520`表示为 `'2017-08-24 10:45:20'`。 - -DATETIME 或者 TIMESTAMP 值可以接一个小数部分,用来表示微秒(精度最多到小数点后 6 位),用小数点 `.` 分隔。 - -Dates 如果 year 部分只有两个数字,这是有歧义的(推荐使用四个数字的格式),TiDB 会尝试用以下的规则来解释: - -* year 值如果在 `70-99` 范围,那么被转换成 `1970-1999`。 -* year 值如果在 `00-69` 范围,那么被转换成 `2000-2069`。 - -对于小于 10 的 month 或者 day 值,`'2017-8-4'` 跟 `'2017-08-04'` 是一样的。对于 Time 也是一样,比如 `'2017-08-24 1:2:3'` 跟 `'2017-08-24 01:02:03'`是一样的。 - -在需要 Date 或者 Time 的语境下, 对于数值,TiDB 会根据数值的长度来选定指定的格式: - -* 6 个数字,会被解释为 `YYMMDD`。 -* 12 个数字,会被解释为 `YYMMDDHHMMSS`。 -* 8 个数字,会解释为 `YYYYMMDD`。 -* 14 个数字,会被解释为 `YYYYMMDDHHMMSS`。 - -对于 Time 类型,TiDB 用以下格式来表示: - -* `'D HH:MM:SS'`,或者 `'HH:MM:SS'`,`'HH:MM'`,`'D HH:MM'`,`'D HH'`,`'SS'`,这里的 D 表示 days,合法的范围是 `0-34`。 -* 数值 `HHMMSS`,例如 `231010` 被解释为`'23:10:10'`。 -* 数值 `SS`,`MMSS`,`HHMMSS` 都是可以被当做 Time。 - -Time 类型的小数点也是 `.`,精度最多小数点后 6 位。 - -更多[细节](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html)。 - -## Boolean Literals - -常量 `TRUE` 和 `FALSE` 等于 1 和 0,它是大小写不敏感的。 - -{{< copyable "sql" >}} - -```sql -SELECT TRUE, true, tRuE, FALSE, FaLsE, false; -``` - -``` -+------+------+------+-------+-------+-------+ -| TRUE | true | tRuE | FALSE | FaLsE | false | -+------+------+------+-------+-------+-------+ -| 1 | 1 | 1 | 0 | 0 | 0 | -+------+------+------+-------+-------+-------+ -1 row in set (0.00 sec) -``` - ## Bit-Value Literals -位值字面值用 `b` 或者 `0b` 做前缀,后接以 0 跟 1 组成的二进制数字。其中 `0b` 是区分大小写的,`0B` 是会报错的。 +位值字面值用 `b` 或者 `0b` 做前缀,后接以 0 跟 1 组成的二进制数字。其中 `0b` 是区分大小写的,`0B` 则会报错。 合法的 Bit-value: @@ -281,3 +273,11 @@ SELECT b+0, BIN(b), HEX(b) FROM t; +------+--------+--------+ 3 rows in set (0.00 sec) ``` + +## NULL Values + +`NULL` 代表数据为空,它是大小写不敏感的,与 `\N`(大小写敏感) 同义。 + +> **注意:** +> +> `NULL` 跟 `0` 并不一样,跟空字符串 `''` 也不一样。 diff --git a/reference/tools/error-case-handling/load-misuse-handling.md b/load-misuse-handling.md similarity index 84% rename from reference/tools/error-case-handling/load-misuse-handling.md rename to load-misuse-handling.md index 9806fb53e8c0..2f4f0484f327 100644 --- a/reference/tools/error-case-handling/load-misuse-handling.md +++ b/load-misuse-handling.md @@ -1,11 +1,12 @@ --- title: 全量数据导入过程常见报错处理 category: reference +aliases: ['/docs-cn/stable/reference/tools/error-case-handling/load-misuse-handling/'] --- # 全量数据导入过程常见报错处理 -本文介绍了使用 [Loader](/reference/tools/loader.md) 或者 [TiDB Data Migration](https://pingcap.com/docs-cn/tidb-data-migration/stable/overview/)(以下简称为 DM)进行全量数据导入过程中常见的因为使用造成的出错场景,以及这些错误发生的原因和处理方式。 +本文介绍了使用 [Loader](/loader-overview.md) 或者 [TiDB Data Migration](https://pingcap.com/docs-cn/tidb-data-migration/stable/overview/)(以下简称为 DM)进行全量数据导入过程中常见的因为使用造成的出错场景,以及这些错误发生的原因和处理方式。 ## 报错:```Try adjusting the `max_allowed_packet` variable``` @@ -18,7 +19,7 @@ packet for query is too large. Try adjusting the 'max_allowed_packet' variable ### 原因 * MySQL client 和 MySQL/TiDB Server 都有 `max_allowed_packet` 配额的限制,如果在使用过程中违反其中任何一个 `max_allowed_packet` 配额,客户端程序就会收到对应的报错。目前最新版本的 Syncer、Loader、DM 和 TiDB Server 的默认 `max_allowed_packet` 配额都为 `64M`。 - * 请使用最新版本,或者最新稳定版本的工具。[下载页面](/reference/tools/download.md)。 + * 请使用最新版本,或者最新稳定版本的工具。[下载页面](/download-ecosystem-tools.md)。 * Loader 或 DM 的全量数据导入处理模块不支持对 dump sqls 文件进行切分,原因是 Mydumper 采用了最简单的编码实现,正如 Mydumper 代码注释 `/* Poor man's data dump code */` 所言。如果在 Loader 或 DM 实现文件切分,那么需要在 `TiDB parser` 基础上实现一个完备的解析器才能正确的处理数据切分,但是随之会带来以下的问题: * 工作量大 * 复杂度高,不容易保证正确性 diff --git a/loader-overview.md b/loader-overview.md new file mode 100644 index 000000000000..889b48b836dc --- /dev/null +++ b/loader-overview.md @@ -0,0 +1,193 @@ +--- +title: Loader 使用文档 +category: reference +aliases: ['/docs-cn/stable/reference/tools/loader/'] +--- + +# Loader 使用文档 + +> **警告:** +> +> Loader 目前已经不再维护,其功能已经完全被 [TiDB Lightning 的 TiDB backend 功能](/tidb-lightning/tidb-lightning-tidb-backend.md)取代,强烈建议切换到 TiDB Lightning。 + +## Loader 简介 + +Loader 是由 PingCAP 开发的数据导入工具,用于向 TiDB 中导入数据。 + +Loader 包含在 tidb-enterprise-tools 安装包中,可[在此下载](/download-ecosystem-tools.md)。 + +## 为什么我们要做这个工具 + +当数据量比较大的时候,如果用 mysqldump 这样的工具迁移数据会比较慢。我们尝试了 [Mydumper/myloader 套件](https://github.com/maxbube/mydumper),能够多线程导出和导入数据。在使用过程中,Mydumper 问题不大,但是 myloader 由于缺乏出错重试、断点续传这样的功能,使用起来很不方便。所以我们开发了 loader,能够读取 Mydumper 的输出数据文件,通过 MySQL protocol 向 TiDB/MySQL 中导入数据。 + +## Loader 有哪些优点 + +* 多线程导入 +* 支持表级别的并发导入,分散写入热点 +* 支持对单个大表并发导入,分散写入热点 +* 支持 Mydumper 数据格式 +* 出错重试 +* 断点续导 +* 通过 system variable 优化 TiDB 导入数据速度 + +## 使用方法 + +### 注意事项 + +请勿使用 loader 导入 MySQL 实例中 `mysql` 系统数据库到下游 TiDB。 + +如果 Mydumper 使用 -m 参数,会导出不带表结构的数据,这时 loader 无法导入数据。 + +如果使用默认的 `checkpoint-schema` 参数,在导完一个 database 数据库后,请 `drop database tidb_loader` 后再开始导入下一个 database。 + +推荐数据库开始导入的时候,明确指定 `checkpoint-schema = "tidb_loader"` 参数。 + +### 参数说明 + +``` + -L string + log 级别设置,可以设置为 debug, info, warn, error, fatal (默认为 "info") + -P int + TiDB/MySQL 的端口 (默认为 4000) + -V + 打印 loader 版本 + -c string + 指定配置文件启动 loader + -checkpoint-schema string + checkpoint 数据库名,loader 在运行过程中会不断的更新这个数据库,在中断并恢复后,会通过这个库获取上次运行的进度 (默认为 "tidb_loader") + -d string + 需要导入的数据存放路径 (default "./") + -h string + TiDB 服务 host IP (default "127.0.0.1") + -p string + TiDB 账户密码 + -status-addr string + Prometheus 可以通过该地址拉取 Loader metrics, 也是 Loader 的 pprof 调试地址 (默认为 ":8272")。 + -t int + 线程数 (默认为 16). 每个线程同一时刻只能操作一个数据文件。 + -u string + TiDB 的用户名 (默认为 "root") +``` + +### 配置文件 + +除了使用命令行参数外,还可以使用配置文件来配置,配置文件的格式如下: + +```toml +# 日志输出等级;可以设置为 debug, info, warn, error, fatal (默认为 "info") +log-level = "info" + +# 指定 loader 日志目录 +log-file = "loader.log" + +# 需要导入的数据存放路径 (default "./") +dir = "./" + +## Prometheus 可以通过该地址拉取 Loader metrics, 也是 Loader 的 pprof 调试地址 (默认为 ":8272")。 +status-addr = ":8272" + +# checkpoint 数据库名,loader 在运行过程中会不断的更新这个数据库,在中断并恢复后, +# 会通过这个库获取上次运行的进度 (默认为 "tidb_loader") +checkpoint-schema = "tidb_loader" + +# 线程数 (默认为 16). 每个线程同一时刻只能操作一个数据文件。 +pool-size = 16 + +# 目标数据库信息 +[db] +host = "127.0.0.1" +user = "root" +password = "" +port = 4000 + +# 导入数据时数据库连接所使用的 session 级别的 `sql_mode`。如果 `sql-mode` 的值没有提供或者设置为 "@DownstreamDefault",会使用下游 global 级别的 `sql_mode`。 +# sql-mode = "" +# `max-allowed-packet` 设置数据库连接允许的最大数据包大小,对应于系统参数中的 `max_allowed_packet`。 如果设置为 0,会使用下游数据库 global 级别的 `max_allowed_packet`。 +max-allowed-packet = 67108864 + +# sharding 同步规则,采用 wildcharacter +# 1\. 星号字符 (*) 可以匹配零个或者多个字符, +# 例子, doc* 匹配 doc 和 document, 但是和 dodo 不匹配; +# 星号只能放在 pattern 结尾,并且一个 pattern 中只能有一个 +# 2\. 问号字符 (?) 匹配任一一个字符 + +# [[route-rules]] +# pattern-schema = "shard_db_*" +# pattern-table = "shard_table_*" +# target-schema = "shard_db" +# target-table = "shard_table" +``` + +### 使用示例 + +通过命令行参数: + +{{< copyable "shell-regular" >}} + +```bash +./bin/loader -d ./test -h 127.0.0.1 -u root -P 4000 +``` + +或者使用配置文件 "config.toml": + +{{< copyable "shell-regular" >}} + +```bash +./bin/loader -c=config.toml +``` + +## FAQ + +### 合库合表场景案例说明 + +根据配置文件的 route-rules 可以支持将分库分表的数据导入到同一个库同一个表中,但是在开始前需要检查分库分表规则: + ++ 是否可以利用 route-rules 的语义规则表示 ++ 分表中是否包含唯一递增主键,或者合并后是否包含数据上有冲突的唯一索引或者主键 + +Loader 需要配置文件中开启 route-rules 参数以提供合库合表功能 + ++ 如果使用该功能,必须填写 `pattern-schema` 与 `target-schema` ++ 如果 `pattern-table` 与 `target-table` 为空,将不进行表名称合并或转换 + +```toml +[[route-rules]] +pattern-schema = "example_db" +pattern-table = "table_*" +target-schema = "example_db" +target-table = "table" +``` + +### 全量导入过程中遇到报错 `packet for query is too large. Try adjusting the 'max_allowed_packet' variable` + +#### 原因 + +* MySQL client 和 MySQL/TiDB Server 都有 `max_allowed_packet` 配额的限制,如果在使用过程中违反其中任何一个 `max_allowed_packet` 配额,客户端程序就会收到对应的报错。目前最新版本的 Loader 和 TiDB Server 的默认 `max_allowed_packet` 配额都为 `64M`。 + + * 请使用最新版本,或者最新稳定版本的工具。[下载页面](/download-ecosystem-tools.md)。 + +* Loader 的全量数据导入处理模块不支持对 dump sqls 文件进行切分,原因是 Mydumper 采用了最简单的编码实现,正如 Mydumper 代码注释 `/* Poor man's data dump code */` 所言。如果在 Loader 实现文件切分,那么需要在 `TiDB parser` 基础上实现一个完备的解析器才能正确的处理数据切分,但是随之会带来以下的问题: + + * 工作量大 + + * 复杂度高,不容易保证正确性 + + * 性能的极大降低 + +#### 解决方案 + +* 依据上面的原因,在代码层面不能简单的解决这个困扰,我们推荐的方式是:利用 Mydumper 提供的控制 `Insert Statement` 大小的功能 `-s, --statement-size`: `Attempted size of INSERT statement in bytes, default 1000000`。 + + 依据默认的 `--statement-size` 设置,Mydumper 默认生成的 `Insert Statement` 大小会尽量接近在 `1M` 左右,使用默认值就可以确保绝大部分情况不会出现该问题。 + + 有时候在 dump 过程中会出现下面的 `WARN` log,但是这个报错不影响 dump 的过程,只是表达了 dump 的表可能是宽表。 + + ``` + Row bigger than statement_size for xxx + ``` + +* 如果宽表的单行超过了 `64M`,那么需要修改以下两个配置,并且使之生效。 + + * 在 TiDB Server 执行 `set @@global.max_allowed_packet=134217728` (`134217728 = 128M`) + + * 根据实际情况为 Loader 的配置文件中的 db 配置增加 `max-allowed-packet=128M`,然后重启进程或者任务 diff --git a/maintain-tidb-using-ansible.md b/maintain-tidb-using-ansible.md new file mode 100644 index 000000000000..bcfce56fa969 --- /dev/null +++ b/maintain-tidb-using-ansible.md @@ -0,0 +1,47 @@ +--- +title: TiDB Ansible 常见运维操作 +category: how-to +aliases: ['/docs-cn/stable/how-to/maintain/ansible-operations/'] +--- + +# TiDB Ansible 常见运维操作 + +## 启动集群 + +此操作会按顺序启动整个 TiDB 集群所有组件(包括 PD、TiDB、TiKV 等组件和监控组件)。 + +{{< copyable "shell-regular" >}} + +```bash +ansible-playbook start.yml +``` + +## 关闭集群 + +此操作会按顺序关闭整个 TiDB 集群所有组件(包括 PD、TiDB、TiKV 等组件和监控组件)。 + +{{< copyable "shell-regular" >}} + +```bash +ansible-playbook stop.yml +``` + +## 清除集群数据 + +此操作会关闭 TiDB、Pump、TiKV、PD 服务,并清空 Pump、TiKV、PD 数据目录。 + +{{< copyable "shell-regular" >}} + +```bash +ansible-playbook unsafe_cleanup_data.yml +``` + +## 销毁集群 + +此操作会关闭集群,并清空部署目录,若部署目录为挂载点,会报错,可忽略。 + +{{< copyable "shell-regular" >}} + +```bash +ansible-playbook unsafe_cleanup.yml +``` diff --git a/maintain-tidb-using-tiup.md b/maintain-tidb-using-tiup.md new file mode 100644 index 000000000000..f149a3cc517d --- /dev/null +++ b/maintain-tidb-using-tiup.md @@ -0,0 +1,207 @@ +--- +title: TiUP 常见运维操作 +category: how-to +aliases: ['/docs-cn/stable/how-to/maintain/tiup-operations/'] +--- + +# TiUP 常见运维操作 + +本文介绍了使用 TiUP 运维 TiDB 集群的常见操作,包括查看集群列表、启动集群、查看集群状态、修改配置参数、关闭集群、销毁集群等。 + +## 查看集群列表 + +TiUP cluster 组件可以用来管理多个 TiDB 集群,在每个 TiDB 集群部署完毕后,该集群会出现在 TiUP 的集群列表里,可以使用 list 命令来查看。 + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster list +``` + +## 启动集群 + +启动集群操作会按 PD -> TiKV -> Pump -> TiDB -> TiFlash -> Drainer 的顺序启动整个 TiDB 集群所有组件(同时也会启动监控组件): + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster start ${cluster-name} +``` + +> **注意:** +> +> 你需要将 `${cluster-name}` 替换成实际的集群名字,若忘记集群名字,可通过 `tiup cluster list` 查看。 + +该命令支持通过 `-R` 和 `-N` 参数来只启动部分组件。 + +例如,下列命令只启动 PD 组件: + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster start ${cluster-name} -R pd +``` + +下列命令只启动 `1.2.3.4` 和 `1.2.3.5` 这两台机器上的 PD 组件: + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster start ${cluster-name} -N 1.2.3.4:2379,1.2.3.5:2379 +``` + +> **注意:** +> +> 若通过 `-R` 和 `-N` 启动指定组件,需要保证启动顺序正确(例如需要先启动 PD 才能启动 TiKV),否则可能导致启动失败。 + +## 查看集群状态 + +集群启动之后需要检查每个组件的运行状态,以确保每个组件工作正常。TiUP 提供了 display 命令,节省了登陆到每台机器上去查看进程的时间。 + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster display ${cluster-name} +``` + +## 修改配置参数 + +集群运行过程中,如果需要调整某个组件的参数,可以使用 `edit-config` 命令来编辑参数。具体的操作步骤如下: + +1. 以编辑模式打开该集群的配置文件: + + {{< copyable "shell-regular" >}} + + ```bash + tiup cluster edit-config ${cluster-name} + ``` + +2. 设置参数: + + 首先确定配置的生效范围,有以下两种生效范围: + + - 如果配置的生效范围为该组件全局,则配置到 `server_configs`。例如: + + ``` + server_configs: + tidb: + log.slow-threshold: 300 + ``` + + - 如果配置的生效范围为某个节点,则配置到具体节点的 `config` 中。例如: + + ``` + tidb_servers: + - host: 10.0.1.11 + port: 4000 + config: + log.slow-threshold: 300 + ``` + + 参数的格式参考 [TiUP 配置参数模版](https://github.com/pingcap/tiup/blob/master/examples/topology.example.yaml)。 + + **配置项层次结构使用 `.` 表示**。 + + 关于组件的更多配置参数说明,可参考 [tidb `config.toml.example`](https://github.com/pingcap/tidb/blob/v4.0.0-rc/config/config.toml.example)、[tikv `config.toml.example`](https://github.com/tikv/tikv/blob/v4.0.0-rc/etc/config-template.toml) 和 [pd `config.toml.example`](https://github.com/pingcap/pd/blob/v4.0.0-rc/conf/config.toml)。 + +3. 执行 `reload` 命令滚动分发配置、重启相应组件: + + {{< copyable "shell-regular" >}} + + ```bash + tiup cluster reload ${cluster-name} [-N ] [-R ] + ``` + +### 示例 + +如果要调整 tidb-server 中事务大小限制参数 `txn-total-size-limit` 为 `1G`,该参数位于 [performance](https://github.com/pingcap/tidb/blob/v4.0.0-rc/config/config.toml.example) 模块下,调整后的配置如下: + +``` +server_configs: + tidb: + performance.txn-total-size-limit: 1073741824 +``` + +然后执行 `tiup cluster reload ${cluster-name} -R tidb` 命令滚动重启。 + +## Hotfix 版本替换 + +常规的升级集群请参考[升级文档](/upgrade-tidb-using-tiup.md),但是在某些场景下(例如 Debug),可能需要用一个临时的包替换正在运行的组件,此时可以用 `patch` 命令: + +{{< copyable "shell-root" >}} + +```bash +tiup cluster patch --help +``` + +``` +Replace the remote package with a specified package and restart the service + +Usage: + tiup cluster patch [flags] + +Flags: + -h, --help 帮助信息 + -N, --node strings 指定被替换的节点 + --overwrite 在未来的 scale-out 操作中使用当前指定的临时包 + -R, --role strings 指定被替换的服务类型 + --transfer-timeout int transfer leader 的超时时间 + +Global Flags: + --ssh-timeout int SSH 连接的超时时间 + -y, --yes 跳过所有的确认步骤 +``` + +例如,有一个 TiDB 实例的 hotfix 包放在 `/tmp/tidb-hotfix.tar.gz` 目录下。如果此时想要替换集群上的所有 TiDB 实例,则可以执行以下命令: + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster patch test-cluster /tmp/tidb-hotfix.tar.gz -R tidb +``` + +或者只替换其中一个 TiDB 实例: + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster patch test-cluster /tmp/tidb-hotfix.tar.gz -N 172.16.4.5:4000 +``` + +## 关闭集群 + +关闭集群操作会按 Drainer -> TiFlash -> TiDB -> Pump -> TiKV -> PD 的顺序关闭整个 TiDB 集群所有组件(同时也会关闭监控组件): + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster stop ${cluster-name} +``` + +和 `start` 命令类似,`stop` 命令也支持通过 `-R` 和 `-N` 参数来只停止部分组件。 + +例如,下列命令只停止 TiDB 组件: + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster stop ${cluster-name} -R tidb +``` + +下列命令只停止 `1.2.3.4` 和 `1.2.3.5` 这两台机器上的 TiDB 组件: + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster stop ${cluster-name} -N 1.2.3.4:4000,1.2.3.5:4000 +``` + +## 销毁集群 + +销毁集群操作会关闭服务,清空数据目录和部署目录,并且无法恢复,需要**谨慎操作**。 + +{{< copyable "shell-regular" >}} + +```bash +tiup cluster destroy ${cluster-name} +``` diff --git a/max-min-eliminate.md b/max-min-eliminate.md new file mode 100644 index 000000000000..a7c7d0d9e310 --- /dev/null +++ b/max-min-eliminate.md @@ -0,0 +1,118 @@ +--- +title: Max/Min 函数消除规则 +category: reference +aliases: ['/docs-cn/stable/reference/performance/max-min-eliminate/'] +--- + +# Max/Min 函数消除规则 + +在 SQL 中包含了 `max`/`min` 函数时,查询优化器会尝试使用 `max`/`min` 消除优化规则来将 `max`/`min` 聚合函数转换为 TopN 算子,从而能够有效地利用索引进行查询。 + +根据 `select` 语句中 `max`/`min` 函数的个数,这一优化规则有以下两种表现形式: + ++ [存在多个 max/min 函数时的优化规则](#存在多个-maxmin-函数时的优化规则) ++ [存在多个 max/min 函数时的优化规则](#存在多个-maxmin-函数时的优化规则) + +## 只有一个 max/min 函数时的优化规则 + +当一个 SQL 满足以下条件时,就会应用这个规则: + ++ 只有一个聚合函数,且为 `max` 或者 `min` 函数。 ++ 聚合函数没有相应的 `group by` 语句。 + +例如: + +{{< copyable "sql" >}} + +```sql +select max(a) from t +``` + +这时 `max`/`min` 消除优化规则会将其重写为: + +{{< copyable "sql" >}} + +```sql +select max(a) from (select a from t where a is not null order by a desc limit 1) t +``` + +这个新的 SQL 语句在 `a` 列存在索引(或 `a` 列是某个联合索引的前缀)时,能够利用索引只扫描一行数据来得到最大或者最小值,从而避免对整个表的扫描。 + +上述例子最终得到的执行计划如下: + +``` +mysql> explain select max(a) from t; ++------------------------------+---------+-----------+-------------------------+-------------------------------------+ +| id | estRows | task | access object | operator info | ++------------------------------+---------+-----------+-------------------------+-------------------------------------+ +| StreamAgg_13 | 1.00 | root | | funcs:max(test.t.a)->Column#4 | +| └─Limit_17 | 1.00 | root | | offset:0, count:1 | +| └─IndexReader_27 | 1.00 | root | | index:Limit_26 | +| └─Limit_26 | 1.00 | cop[tikv] | | offset:0, count:1 | +| └─IndexFullScan_25 | 1.00 | cop[tikv] | table:t, index:idx_a(a) | keep order:true, desc, stats:pseudo | ++------------------------------+---------+-----------+-------------------------+-------------------------------------+ +5 rows in set (0.00 sec) +``` + +## 存在多个 max/min 函数时的优化规则 + +当一个 SQL 满足以下条件时,就会应用这个规则: + ++ 有多个聚合函数,且所有的聚合函数都是 max/min ++ 聚合函数没有相应的 `group by` 语句。 ++ 每个 `max`/`min` 聚合函数参数中的列都有索引能够保序。 + +下面是一个简单的例子: + +{{< copyable "sql" >}} + +```sql +select max(a) - min(a) from t +``` + +优化规则会先检查 `a` 列是否存在索引能够为其保序,如果存在,这个 SQL 会先被重写为两个子查询的笛卡尔积: + +{{< copyable "sql" >}} + +```sql +select max_a - min_a +from + (select max(a) as max_a from t) t1, + (select min(a) as min_a from t) t2 +``` + +这样,两个子句中的 `max`/`min` 函数就可以使用上述“只有一个 `max`/`min` 函数时的优化规则”分别进行优化,最终重写为: + +{{< copyable "sql" >}} + +```sql +select max_a - min_a +from + (select max(a) as max_a from (select a from t where a is not null order by a desc limit 1) t) t1, + (select min(a) as min_a from (select a from t where a is not null order by a asc limit 1) t) t2 +``` + +同样的,如果 `a` 列能够使用索引保序,那这个优化只会扫描两行数据,避免了对整个表的扫描。但如果 `a` 列没有可以保序的索引,这个变换会使原本只需一次的全表扫描变成两次,因此这个规则就不会被应用。 + +最后得到的执行计划: + +``` +mysql> explain select max(a)-min(a) from t; ++------------------------------------+---------+-----------+-------------------------+-------------------------------------+ +| id | estRows | task | access object | operator info | ++------------------------------------+---------+-----------+-------------------------+-------------------------------------+ +| Projection_17 | 1.00 | root | | minus(Column#4, Column#5)->Column#6 | +| └─HashJoin_18 | 1.00 | root | | CARTESIAN inner join | +| ├─StreamAgg_45(Build) | 1.00 | root | | funcs:min(test.t.a)->Column#5 | +| │ └─Limit_49 | 1.00 | root | | offset:0, count:1 | +| │ └─IndexReader_59 | 1.00 | root | | index:Limit_58 | +| │ └─Limit_58 | 1.00 | cop[tikv] | | offset:0, count:1 | +| │ └─IndexFullScan_57 | 1.00 | cop[tikv] | table:t, index:idx_a(a) | keep order:true, stats:pseudo | +| └─StreamAgg_24(Probe) | 1.00 | root | | funcs:max(test.t.a)->Column#4 | +| └─Limit_28 | 1.00 | root | | offset:0, count:1 | +| └─IndexReader_38 | 1.00 | root | | index:Limit_37 | +| └─Limit_37 | 1.00 | cop[tikv] | | offset:0, count:1 | +| └─IndexFullScan_36 | 1.00 | cop[tikv] | table:t, index:idx_a(a) | keep order:true, desc, stats:pseudo | ++------------------------------------+---------+-----------+-------------------------+-------------------------------------+ +12 rows in set (0.01 sec) +``` diff --git a/media/binlog/bi-repl2.png b/media/binlog/bi-repl2.png index 39fef6f948b9..abf4e6602283 100644 Binary files a/media/binlog/bi-repl2.png and b/media/binlog/bi-repl2.png differ diff --git a/media/cdc-cyclic-replication.png b/media/cdc-cyclic-replication.png new file mode 100644 index 000000000000..90bd33baf35e Binary files /dev/null and b/media/cdc-cyclic-replication.png differ diff --git a/media/contribution-map.png b/media/contribution-map.png new file mode 100644 index 000000000000..099691270a84 Binary files /dev/null and b/media/contribution-map.png differ diff --git a/media/dashboard/dashboard-access-login.png b/media/dashboard/dashboard-access-login.png new file mode 100644 index 000000000000..d4e31bcc718f Binary files /dev/null and b/media/dashboard/dashboard-access-login.png differ diff --git a/media/dashboard/dashboard-access-logout.png b/media/dashboard/dashboard-access-logout.png new file mode 100644 index 000000000000..b478d4e66f7d Binary files /dev/null and b/media/dashboard/dashboard-access-logout.png differ diff --git a/media/dashboard/dashboard-access-switch-language.png b/media/dashboard/dashboard-access-switch-language.png new file mode 100644 index 000000000000..87103d718d15 Binary files /dev/null and b/media/dashboard/dashboard-access-switch-language.png differ diff --git a/media/dashboard/dashboard-cluster-info-access.png b/media/dashboard/dashboard-cluster-info-access.png new file mode 100644 index 000000000000..56a3d6cf1dbc Binary files /dev/null and b/media/dashboard/dashboard-cluster-info-access.png differ diff --git a/media/dashboard/dashboard-cluster-info-hosts.png b/media/dashboard/dashboard-cluster-info-hosts.png new file mode 100644 index 000000000000..f97b487f871f Binary files /dev/null and b/media/dashboard/dashboard-cluster-info-hosts.png differ diff --git a/media/dashboard/dashboard-cluster-info-instances.png b/media/dashboard/dashboard-cluster-info-instances.png new file mode 100644 index 000000000000..d477ef5911dc Binary files /dev/null and b/media/dashboard/dashboard-cluster-info-instances.png differ diff --git a/media/dashboard/dashboard-diagnostics-access.png b/media/dashboard/dashboard-diagnostics-access.png new file mode 100644 index 000000000000..51937a32588f Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-access.png differ diff --git a/media/dashboard/dashboard-diagnostics-cluster-hardware.png b/media/dashboard/dashboard-diagnostics-cluster-hardware.png new file mode 100644 index 000000000000..d5b5d036b87f Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-cluster-hardware.png differ diff --git a/media/dashboard/dashboard-diagnostics-cluster-info.png b/media/dashboard/dashboard-diagnostics-cluster-info.png new file mode 100644 index 000000000000..ebde1ecdd833 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-cluster-info.png differ diff --git a/media/dashboard/dashboard-diagnostics-compare-instance-cpu-usage.png b/media/dashboard/dashboard-diagnostics-compare-instance-cpu-usage.png new file mode 100644 index 000000000000..7b28c6a73aa4 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-compare-instance-cpu-usage.png differ diff --git a/media/dashboard/dashboard-diagnostics-compare-process-cpu-usage.png b/media/dashboard/dashboard-diagnostics-compare-process-cpu-usage.png new file mode 100644 index 000000000000..b200537348c5 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-compare-process-cpu-usage.png differ diff --git a/media/dashboard/dashboard-diagnostics-compare-time.png b/media/dashboard/dashboard-diagnostics-compare-time.png new file mode 100644 index 000000000000..16d39cbdde63 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-compare-time.png differ diff --git a/media/dashboard/dashboard-diagnostics-config-change.png b/media/dashboard/dashboard-diagnostics-config-change.png new file mode 100644 index 000000000000..10228575cd1b Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-config-change.png differ diff --git a/media/dashboard/dashboard-diagnostics-error.png b/media/dashboard/dashboard-diagnostics-error.png new file mode 100644 index 000000000000..18b1cbc1a4f4 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-error.png differ diff --git a/media/dashboard/dashboard-diagnostics-example-table.png b/media/dashboard/dashboard-diagnostics-example-table.png new file mode 100644 index 000000000000..3d5ef53c46a5 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-example-table.png differ diff --git a/media/dashboard/dashboard-diagnostics-gen-compare-report.png b/media/dashboard/dashboard-diagnostics-gen-compare-report.png new file mode 100644 index 000000000000..a71e9646503a Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-gen-compare-report.png differ diff --git a/media/dashboard/dashboard-diagnostics-gen-process.png b/media/dashboard/dashboard-diagnostics-gen-process.png new file mode 100644 index 000000000000..7dcd8d920e2b Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-gen-process.png differ diff --git a/media/dashboard/dashboard-diagnostics-gen-report.png b/media/dashboard/dashboard-diagnostics-gen-report.png new file mode 100644 index 000000000000..f9de54e6306e Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-gen-report.png differ diff --git a/media/dashboard/dashboard-diagnostics-goroutines-count.png b/media/dashboard/dashboard-diagnostics-goroutines-count.png new file mode 100644 index 000000000000..170819bbfeee Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-goroutines-count.png differ diff --git a/media/dashboard/dashboard-diagnostics-max-diff-item.png b/media/dashboard/dashboard-diagnostics-max-diff-item.png new file mode 100644 index 000000000000..3bf901a781b9 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-max-diff-item.png differ diff --git a/media/dashboard/dashboard-diagnostics-maximum-different-item.png b/media/dashboard/dashboard-diagnostics-maximum-different-item.png new file mode 100644 index 000000000000..076d7bec632f Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-maximum-different-item.png differ diff --git a/media/dashboard/dashboard-diagnostics-node-load-info.png b/media/dashboard/dashboard-diagnostics-node-load-info.png new file mode 100644 index 000000000000..acd40f31d087 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-node-load-info.png differ diff --git a/media/dashboard/dashboard-diagnostics-process-cpu-usage.png b/media/dashboard/dashboard-diagnostics-process-cpu-usage.png new file mode 100644 index 000000000000..4a9370fb5d1a Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-process-cpu-usage.png differ diff --git a/media/dashboard/dashboard-diagnostics-process-memory-usage.png b/media/dashboard/dashboard-diagnostics-process-memory-usage.png new file mode 100644 index 000000000000..fb630af116b1 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-process-memory-usage.png differ diff --git a/media/dashboard/dashboard-diagnostics-report-time-range.png b/media/dashboard/dashboard-diagnostics-report-time-range.png new file mode 100644 index 000000000000..b16072ac8371 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-report-time-range.png differ diff --git a/media/dashboard/dashboard-diagnostics-thread-cpu-usage.png b/media/dashboard/dashboard-diagnostics-thread-cpu-usage.png new file mode 100644 index 000000000000..194d665f5937 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-thread-cpu-usage.png differ diff --git a/media/dashboard/dashboard-diagnostics-tidb-ddl.png b/media/dashboard/dashboard-diagnostics-tidb-ddl.png new file mode 100644 index 000000000000..8f141f9dc26b Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-tidb-ddl.png differ diff --git a/media/dashboard/dashboard-diagnostics-tidb-txn.png b/media/dashboard/dashboard-diagnostics-tidb-txn.png new file mode 100644 index 000000000000..1f80fab7ec50 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-tidb-txn.png differ diff --git a/media/dashboard/dashboard-diagnostics-time-relation.png b/media/dashboard/dashboard-diagnostics-time-relation.png new file mode 100644 index 000000000000..33b7eac7e987 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-time-relation.png differ diff --git a/media/dashboard/dashboard-diagnostics-total-time-consume.png b/media/dashboard/dashboard-diagnostics-total-time-consume.png new file mode 100644 index 000000000000..048f35ed7da9 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-total-time-consume.png differ diff --git a/media/dashboard/dashboard-diagnostics-usage1.png b/media/dashboard/dashboard-diagnostics-usage1.png new file mode 100644 index 000000000000..8466351edee2 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-usage1.png differ diff --git a/media/dashboard/dashboard-diagnostics-usage2.png b/media/dashboard/dashboard-diagnostics-usage2.png new file mode 100644 index 000000000000..97d45fc1a21f Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-usage2.png differ diff --git a/media/dashboard/dashboard-diagnostics-usage3.png b/media/dashboard/dashboard-diagnostics-usage3.png new file mode 100644 index 000000000000..fab12da1a62d Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-usage3.png differ diff --git a/media/dashboard/dashboard-diagnostics-usage4.png b/media/dashboard/dashboard-diagnostics-usage4.png new file mode 100644 index 000000000000..b90c85ec800d Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-usage4.png differ diff --git a/media/dashboard/dashboard-diagnostics-usage5.png b/media/dashboard/dashboard-diagnostics-usage5.png new file mode 100644 index 000000000000..19edcf2610d4 Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-usage5.png differ diff --git a/media/dashboard/dashboard-diagnostics-usage6.png b/media/dashboard/dashboard-diagnostics-usage6.png new file mode 100644 index 000000000000..5630f7701e3d Binary files /dev/null and b/media/dashboard/dashboard-diagnostics-usage6.png differ diff --git a/media/dashboard/dashboard-intro.gif b/media/dashboard/dashboard-intro.gif new file mode 100644 index 000000000000..404893b88f6f Binary files /dev/null and b/media/dashboard/dashboard-intro.gif differ diff --git a/media/dashboard/dashboard-keyviz-access.png b/media/dashboard/dashboard-keyviz-access.png new file mode 100644 index 000000000000..d30567028f2f Binary files /dev/null and b/media/dashboard/dashboard-keyviz-access.png differ diff --git a/media/dashboard/dashboard-keyviz-continue.png b/media/dashboard/dashboard-keyviz-continue.png new file mode 100644 index 000000000000..8f3160cb29c1 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-continue.png differ diff --git a/media/dashboard/dashboard-keyviz-not-enabled.png b/media/dashboard/dashboard-keyviz-not-enabled.png new file mode 100644 index 000000000000..a908925ec55a Binary files /dev/null and b/media/dashboard/dashboard-keyviz-not-enabled.png differ diff --git a/media/dashboard/dashboard-keyviz-overview.png b/media/dashboard/dashboard-keyviz-overview.png new file mode 100644 index 000000000000..40d53d4ebd1f Binary files /dev/null and b/media/dashboard/dashboard-keyviz-overview.png differ diff --git a/media/dashboard/dashboard-keyviz-period.png b/media/dashboard/dashboard-keyviz-period.png new file mode 100644 index 000000000000..9b83945e2b80 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-period.png differ diff --git a/media/dashboard/dashboard-keyviz-select-time.png b/media/dashboard/dashboard-keyviz-select-time.png new file mode 100644 index 000000000000..bd7646dc6803 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-select-time.png differ diff --git a/media/dashboard/dashboard-keyviz-select-type.png b/media/dashboard/dashboard-keyviz-select-type.png new file mode 100644 index 000000000000..fb301525ced8 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-select-type.png differ diff --git a/media/dashboard/dashboard-keyviz-select-zoom.gif b/media/dashboard/dashboard-keyviz-select-zoom.gif new file mode 100644 index 000000000000..fc3529e2ce74 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-select-zoom.gif differ diff --git a/media/dashboard/dashboard-keyviz-sequential.png b/media/dashboard/dashboard-keyviz-sequential.png new file mode 100644 index 000000000000..8b93b2940889 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-sequential.png differ diff --git a/media/dashboard/dashboard-keyviz-settings-button.png b/media/dashboard/dashboard-keyviz-settings-button.png new file mode 100644 index 000000000000..4e28de992727 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-settings-button.png differ diff --git a/media/dashboard/dashboard-keyviz-settings.png b/media/dashboard/dashboard-keyviz-settings.png new file mode 100644 index 000000000000..a4a3ce9a3f4d Binary files /dev/null and b/media/dashboard/dashboard-keyviz-settings.png differ diff --git a/media/dashboard/dashboard-keyviz-toolbar.png b/media/dashboard/dashboard-keyviz-toolbar.png new file mode 100644 index 000000000000..2401481a8475 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-toolbar.png differ diff --git a/media/dashboard/dashboard-keyviz-tooltip-copy.png b/media/dashboard/dashboard-keyviz-tooltip-copy.png new file mode 100644 index 000000000000..bf3ed6c09260 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-tooltip-copy.png differ diff --git a/media/dashboard/dashboard-keyviz-tooltip.png b/media/dashboard/dashboard-keyviz-tooltip.png new file mode 100644 index 000000000000..9941ae660227 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-tooltip.png differ diff --git a/media/dashboard/dashboard-keyviz-well-dist.png b/media/dashboard/dashboard-keyviz-well-dist.png new file mode 100644 index 000000000000..40e16197f9b7 Binary files /dev/null and b/media/dashboard/dashboard-keyviz-well-dist.png differ diff --git a/media/dashboard/dashboard-log-search-delete-history.png b/media/dashboard/dashboard-log-search-delete-history.png new file mode 100644 index 000000000000..9312eb162691 Binary files /dev/null and b/media/dashboard/dashboard-log-search-delete-history.png differ diff --git a/media/dashboard/dashboard-log-search-history-entry.png b/media/dashboard/dashboard-log-search-history-entry.png new file mode 100644 index 000000000000..77386a96a074 Binary files /dev/null and b/media/dashboard/dashboard-log-search-history-entry.png differ diff --git a/media/dashboard/dashboard-log-search-history.png b/media/dashboard/dashboard-log-search-history.png new file mode 100644 index 000000000000..f2d515756aa6 Binary files /dev/null and b/media/dashboard/dashboard-log-search-history.png differ diff --git a/media/dashboard/dashboard-log-search-home.png b/media/dashboard/dashboard-log-search-home.png new file mode 100644 index 000000000000..d4a50e9c4198 Binary files /dev/null and b/media/dashboard/dashboard-log-search-home.png differ diff --git a/media/dashboard/dashboard-log-search-result.png b/media/dashboard/dashboard-log-search-result.png new file mode 100644 index 000000000000..da14c0b0381b Binary files /dev/null and b/media/dashboard/dashboard-log-search-result.png differ diff --git a/media/dashboard/dashboard-ops-multiple-pd.png b/media/dashboard/dashboard-ops-multiple-pd.png new file mode 100644 index 000000000000..2af6b4bf8c3b Binary files /dev/null and b/media/dashboard/dashboard-ops-multiple-pd.png differ diff --git a/media/dashboard/dashboard-overview-access.png b/media/dashboard/dashboard-overview-access.png new file mode 100644 index 000000000000..e99384fcfd0e Binary files /dev/null and b/media/dashboard/dashboard-overview-access.png differ diff --git a/media/dashboard/dashboard-overview-instances.png b/media/dashboard/dashboard-overview-instances.png new file mode 100644 index 000000000000..ce5cfe95f863 Binary files /dev/null and b/media/dashboard/dashboard-overview-instances.png differ diff --git a/media/dashboard/dashboard-overview-latency.png b/media/dashboard/dashboard-overview-latency.png new file mode 100644 index 000000000000..c84ae30fb9f8 Binary files /dev/null and b/media/dashboard/dashboard-overview-latency.png differ diff --git a/media/dashboard/dashboard-overview-monitor.png b/media/dashboard/dashboard-overview-monitor.png new file mode 100644 index 000000000000..1ebe9cc6db57 Binary files /dev/null and b/media/dashboard/dashboard-overview-monitor.png differ diff --git a/media/dashboard/dashboard-overview-qps.png b/media/dashboard/dashboard-overview-qps.png new file mode 100644 index 000000000000..1c83832dd3d0 Binary files /dev/null and b/media/dashboard/dashboard-overview-qps.png differ diff --git a/media/dashboard/dashboard-overview-slow-query.png b/media/dashboard/dashboard-overview-slow-query.png new file mode 100644 index 000000000000..90a33558aed5 Binary files /dev/null and b/media/dashboard/dashboard-overview-slow-query.png differ diff --git a/media/dashboard/dashboard-overview-top-statements.png b/media/dashboard/dashboard-overview-top-statements.png new file mode 100644 index 000000000000..29e40bc9bca1 Binary files /dev/null and b/media/dashboard/dashboard-overview-top-statements.png differ diff --git a/media/dashboard/dashboard-profiling-access.png b/media/dashboard/dashboard-profiling-access.png new file mode 100644 index 000000000000..107d30b5781e Binary files /dev/null and b/media/dashboard/dashboard-profiling-access.png differ diff --git a/media/dashboard/dashboard-profiling-download.png b/media/dashboard/dashboard-profiling-download.png new file mode 100644 index 000000000000..bdd629bc6a06 Binary files /dev/null and b/media/dashboard/dashboard-profiling-download.png differ diff --git a/media/dashboard/dashboard-profiling-history.png b/media/dashboard/dashboard-profiling-history.png new file mode 100644 index 000000000000..ff3299fa6248 Binary files /dev/null and b/media/dashboard/dashboard-profiling-history.png differ diff --git a/media/dashboard/dashboard-profiling-start.png b/media/dashboard/dashboard-profiling-start.png new file mode 100644 index 000000000000..911cdb03fe2e Binary files /dev/null and b/media/dashboard/dashboard-profiling-start.png differ diff --git a/media/dashboard/dashboard-profiling-view-progress.png b/media/dashboard/dashboard-profiling-view-progress.png new file mode 100644 index 000000000000..b81ee34c7e34 Binary files /dev/null and b/media/dashboard/dashboard-profiling-view-progress.png differ diff --git a/media/dashboard/dashboard-profiling-view-single.png b/media/dashboard/dashboard-profiling-view-single.png new file mode 100644 index 000000000000..817fa2a13ea0 Binary files /dev/null and b/media/dashboard/dashboard-profiling-view-single.png differ diff --git a/media/dashboard/dashboard-slow-queries-access.png b/media/dashboard/dashboard-slow-queries-access.png new file mode 100644 index 000000000000..abdd2124c789 Binary files /dev/null and b/media/dashboard/dashboard-slow-queries-access.png differ diff --git a/media/dashboard/dashboard-slow-queries-detail1.png b/media/dashboard/dashboard-slow-queries-detail1.png new file mode 100644 index 000000000000..3b40093742db Binary files /dev/null and b/media/dashboard/dashboard-slow-queries-detail1.png differ diff --git a/media/dashboard/dashboard-slow-queries-detail2.png b/media/dashboard/dashboard-slow-queries-detail2.png new file mode 100644 index 000000000000..c8048b7a04db Binary files /dev/null and b/media/dashboard/dashboard-slow-queries-detail2.png differ diff --git a/media/dashboard/dashboard-slow-queries-list1.png b/media/dashboard/dashboard-slow-queries-list1.png new file mode 100644 index 000000000000..204e88804f0a Binary files /dev/null and b/media/dashboard/dashboard-slow-queries-list1.png differ diff --git a/media/dashboard/dashboard-slow-queries-list2.png b/media/dashboard/dashboard-slow-queries-list2.png new file mode 100644 index 000000000000..b621eeabcb4c Binary files /dev/null and b/media/dashboard/dashboard-slow-queries-list2.png differ diff --git a/media/dashboard/dashboard-slow-queries-list3.png b/media/dashboard/dashboard-slow-queries-list3.png new file mode 100644 index 000000000000..27fabac4a1e9 Binary files /dev/null and b/media/dashboard/dashboard-slow-queries-list3.png differ diff --git a/media/dashboard/dashboard-statement-access.png b/media/dashboard/dashboard-statement-access.png new file mode 100644 index 000000000000..8d33c589fbb1 Binary files /dev/null and b/media/dashboard/dashboard-statement-access.png differ diff --git a/media/dashboard/dashboard-statement-change-order.png b/media/dashboard/dashboard-statement-change-order.png new file mode 100644 index 000000000000..1ee5d38932ed Binary files /dev/null and b/media/dashboard/dashboard-statement-change-order.png differ diff --git a/media/dashboard/dashboard-statement-columns-selector.png b/media/dashboard/dashboard-statement-columns-selector.png new file mode 100644 index 000000000000..35692d214c5d Binary files /dev/null and b/media/dashboard/dashboard-statement-columns-selector.png differ diff --git a/media/dashboard/dashboard-statement-detail.png b/media/dashboard/dashboard-statement-detail.png new file mode 100644 index 000000000000..02cdc3da506c Binary files /dev/null and b/media/dashboard/dashboard-statement-detail.png differ diff --git a/media/dashboard/dashboard-statement-filter-options.png b/media/dashboard/dashboard-statement-filter-options.png new file mode 100644 index 000000000000..2c6fd04cf092 Binary files /dev/null and b/media/dashboard/dashboard-statement-filter-options.png differ diff --git a/media/dashboard/dashboard-statement-plans-basic.png b/media/dashboard/dashboard-statement-plans-basic.png new file mode 100644 index 000000000000..c365b315fa34 Binary files /dev/null and b/media/dashboard/dashboard-statement-plans-basic.png differ diff --git a/media/dashboard/dashboard-statement-plans-cop-read.png b/media/dashboard/dashboard-statement-plans-cop-read.png new file mode 100644 index 000000000000..95a8571e2349 Binary files /dev/null and b/media/dashboard/dashboard-statement-plans-cop-read.png differ diff --git a/media/dashboard/dashboard-statement-plans-detail.png b/media/dashboard/dashboard-statement-plans-detail.png new file mode 100644 index 000000000000..1e8ac9e3f98a Binary files /dev/null and b/media/dashboard/dashboard-statement-plans-detail.png differ diff --git a/media/dashboard/dashboard-statement-plans-slow-queries.png b/media/dashboard/dashboard-statement-plans-slow-queries.png new file mode 100644 index 000000000000..ad812ae90ba2 Binary files /dev/null and b/media/dashboard/dashboard-statement-plans-slow-queries.png differ diff --git a/media/dashboard/dashboard-statement-plans-time.png b/media/dashboard/dashboard-statement-plans-time.png new file mode 100644 index 000000000000..bb73524f6667 Binary files /dev/null and b/media/dashboard/dashboard-statement-plans-time.png differ diff --git a/media/dashboard/dashboard-statement-plans-transaction.png b/media/dashboard/dashboard-statement-plans-transaction.png new file mode 100644 index 000000000000..43abacbdc118 Binary files /dev/null and b/media/dashboard/dashboard-statement-plans-transaction.png differ diff --git a/media/dashboard/dashboard-statement-setting-entry.png b/media/dashboard/dashboard-statement-setting-entry.png new file mode 100644 index 000000000000..9daa14308a74 Binary files /dev/null and b/media/dashboard/dashboard-statement-setting-entry.png differ diff --git a/media/dashboard/dashboard-statement-settings.png b/media/dashboard/dashboard-statement-settings.png new file mode 100644 index 000000000000..f6542d5699e5 Binary files /dev/null and b/media/dashboard/dashboard-statement-settings.png differ diff --git a/media/failed-query-panel.png b/media/failed-query-panel.png new file mode 100644 index 000000000000..8777cbb99370 Binary files /dev/null and b/media/failed-query-panel.png differ diff --git a/media/garbage-collation-panel.png b/media/garbage-collation-panel.png new file mode 100644 index 000000000000..81042b82f5a7 Binary files /dev/null and b/media/garbage-collation-panel.png differ diff --git a/media/grafana_monitor_overview.png b/media/grafana_monitor_overview.png new file mode 100644 index 000000000000..a3a5a3bb1222 Binary files /dev/null and b/media/grafana_monitor_overview.png differ diff --git a/media/grafana_monitored_groups.png b/media/grafana_monitored_groups.png new file mode 100644 index 000000000000..5ce778446a19 Binary files /dev/null and b/media/grafana_monitored_groups.png differ diff --git a/media/host-panel.png b/media/host-panel.png new file mode 100644 index 000000000000..1eb81836ba24 Binary files /dev/null and b/media/host-panel.png differ diff --git a/media/instance-status-panel.png b/media/instance-status-panel.png new file mode 100644 index 000000000000..3723879f953d Binary files /dev/null and b/media/instance-status-panel.png differ diff --git a/media/kv-duration-panel.png b/media/kv-duration-panel.png new file mode 100644 index 000000000000..32309e7064a6 Binary files /dev/null and b/media/kv-duration-panel.png differ diff --git a/media/multi-data-centers-in-one-city-deployment-sample.png b/media/multi-data-centers-in-one-city-deployment-sample.png new file mode 100644 index 000000000000..f5dd7eb8f873 Binary files /dev/null and b/media/multi-data-centers-in-one-city-deployment-sample.png differ diff --git a/media/overview-panel.png b/media/overview-panel.png new file mode 100644 index 000000000000..353571bc628c Binary files /dev/null and b/media/overview-panel.png differ diff --git a/media/overview.png b/media/overview.png deleted file mode 100644 index 6bcc070a9453..000000000000 Binary files a/media/overview.png and /dev/null differ diff --git a/media/pd-dashboard-balance-v4.png b/media/pd-dashboard-balance-v4.png new file mode 100644 index 000000000000..e13a97c8c8cd Binary files /dev/null and b/media/pd-dashboard-balance-v4.png differ diff --git a/media/pd-dashboard-cluster-v4.png b/media/pd-dashboard-cluster-v4.png new file mode 100644 index 000000000000..1546480621d4 Binary files /dev/null and b/media/pd-dashboard-cluster-v4.png differ diff --git a/media/pd-dashboard-header-v4.png b/media/pd-dashboard-header-v4.png new file mode 100644 index 000000000000..01b7efe29a79 Binary files /dev/null and b/media/pd-dashboard-header-v4.png differ diff --git a/media/pd-dashboard-heartbeat-v4.png b/media/pd-dashboard-heartbeat-v4.png new file mode 100644 index 000000000000..455c52e5c495 Binary files /dev/null and b/media/pd-dashboard-heartbeat-v4.png differ diff --git a/media/pd-dashboard-hotread-v4.png b/media/pd-dashboard-hotread-v4.png new file mode 100644 index 000000000000..526e1acda5c8 Binary files /dev/null and b/media/pd-dashboard-hotread-v4.png differ diff --git a/media/pd-dashboard-hotwrite-v4.png b/media/pd-dashboard-hotwrite-v4.png new file mode 100644 index 000000000000..cafdc0a65a06 Binary files /dev/null and b/media/pd-dashboard-hotwrite-v4.png differ diff --git a/media/pd-dashboard-operator-v4.png b/media/pd-dashboard-operator-v4.png new file mode 100644 index 000000000000..0e41372dbee9 Binary files /dev/null and b/media/pd-dashboard-operator-v4.png differ diff --git a/media/pd-dashboard-scheduler-v4.png b/media/pd-dashboard-scheduler-v4.png new file mode 100644 index 000000000000..2c58b2de548b Binary files /dev/null and b/media/pd-dashboard-scheduler-v4.png differ diff --git a/media/pd-dashboard-tidb-v4.png b/media/pd-dashboard-tidb-v4.png new file mode 100644 index 000000000000..0970eb42ce99 Binary files /dev/null and b/media/pd-dashboard-tidb-v4.png differ diff --git a/media/pd-duration-panel.png b/media/pd-duration-panel.png new file mode 100644 index 000000000000..d5d3d807a969 Binary files /dev/null and b/media/pd-duration-panel.png differ diff --git a/media/pessimistic-transaction-pipelining.png b/media/pessimistic-transaction-pipelining.png new file mode 100644 index 000000000000..7149c374077f Binary files /dev/null and b/media/pessimistic-transaction-pipelining.png differ diff --git a/media/region-panel.png b/media/region-panel.png new file mode 100644 index 000000000000..5b1fa4520c5e Binary files /dev/null and b/media/region-panel.png differ diff --git a/media/sql-analysis-panel.png b/media/sql-analysis-panel.png new file mode 100644 index 000000000000..a60a7c355897 Binary files /dev/null and b/media/sql-analysis-panel.png differ diff --git a/media/sql-optimization.png b/media/sql-optimization.png new file mode 100644 index 000000000000..bfbb528a35c9 Binary files /dev/null and b/media/sql-optimization.png differ diff --git a/media/sqlgram/AdminShowSlow.png b/media/sqlgram/AdminShowSlow.png index e0063eb00b45..cd51cd8a3d02 100644 Binary files a/media/sqlgram/AdminShowSlow.png and b/media/sqlgram/AdminShowSlow.png differ diff --git a/media/sqlgram/AdminStmt.png b/media/sqlgram/AdminStmt.png index 1e375a000f77..a71f6d95b7d4 100644 Binary files a/media/sqlgram/AdminStmt.png and b/media/sqlgram/AdminStmt.png differ diff --git a/media/sqlgram/AlgorithmClause.png b/media/sqlgram/AlgorithmClause.png new file mode 100644 index 000000000000..112ee92ba9ec Binary files /dev/null and b/media/sqlgram/AlgorithmClause.png differ diff --git a/media/sqlgram/AllOrPartitionNameList.png b/media/sqlgram/AllOrPartitionNameList.png new file mode 100644 index 000000000000..e1964e6a59ef Binary files /dev/null and b/media/sqlgram/AllOrPartitionNameList.png differ diff --git a/media/sqlgram/AlterDatabaseStmt.png b/media/sqlgram/AlterDatabaseStmt.png new file mode 100644 index 000000000000..48ea798b76b8 Binary files /dev/null and b/media/sqlgram/AlterDatabaseStmt.png differ diff --git a/media/sqlgram/AlterInstanceStmt.png b/media/sqlgram/AlterInstanceStmt.png new file mode 100644 index 000000000000..8437701d5d77 Binary files /dev/null and b/media/sqlgram/AlterInstanceStmt.png differ diff --git a/media/sqlgram/AlterOrderItem.png b/media/sqlgram/AlterOrderItem.png new file mode 100644 index 000000000000..d60f659b29ad Binary files /dev/null and b/media/sqlgram/AlterOrderItem.png differ diff --git a/media/sqlgram/AlterTableDropIndexSpec.png b/media/sqlgram/AlterTableDropIndexSpec.png new file mode 100755 index 000000000000..a24c4e6bcb54 Binary files /dev/null and b/media/sqlgram/AlterTableDropIndexSpec.png differ diff --git a/media/sqlgram/AlterTableDropIndexStmt.png b/media/sqlgram/AlterTableDropIndexStmt.png new file mode 100755 index 000000000000..bb94d0466ff2 Binary files /dev/null and b/media/sqlgram/AlterTableDropIndexStmt.png differ diff --git a/media/sqlgram/AlterTablePartitionOpt.png b/media/sqlgram/AlterTablePartitionOpt.png new file mode 100644 index 000000000000..45db05ec363d Binary files /dev/null and b/media/sqlgram/AlterTablePartitionOpt.png differ diff --git a/media/sqlgram/AlterTableSpec.png b/media/sqlgram/AlterTableSpec.png index 5560bb40ef7c..d49f68a1d7ec 100644 Binary files a/media/sqlgram/AlterTableSpec.png and b/media/sqlgram/AlterTableSpec.png differ diff --git a/media/sqlgram/AlterTableSpecListOpt.png b/media/sqlgram/AlterTableSpecListOpt.png new file mode 100644 index 000000000000..908ed70837b1 Binary files /dev/null and b/media/sqlgram/AlterTableSpecListOpt.png differ diff --git a/media/sqlgram/AlterTableStmt.png b/media/sqlgram/AlterTableStmt.png index 95a9b1e35686..f691a4e4919b 100644 Binary files a/media/sqlgram/AlterTableStmt.png and b/media/sqlgram/AlterTableStmt.png differ diff --git a/media/sqlgram/AlterUserStmt.png b/media/sqlgram/AlterUserStmt.png index 48334dd68222..20ca635b3cce 100644 Binary files a/media/sqlgram/AlterUserStmt.png and b/media/sqlgram/AlterUserStmt.png differ diff --git a/media/sqlgram/AnalyzeOption.png b/media/sqlgram/AnalyzeOption.png new file mode 100644 index 000000000000..497bcae19eb8 Binary files /dev/null and b/media/sqlgram/AnalyzeOption.png differ diff --git a/media/sqlgram/AnalyzeOptionListOpt.png b/media/sqlgram/AnalyzeOptionListOpt.png new file mode 100644 index 000000000000..3a97317fb48d Binary files /dev/null and b/media/sqlgram/AnalyzeOptionListOpt.png differ diff --git a/media/sqlgram/AnalyzeTableStmt.png b/media/sqlgram/AnalyzeTableStmt.png index da63ac428402..637754807de3 100644 Binary files a/media/sqlgram/AnalyzeTableStmt.png and b/media/sqlgram/AnalyzeTableStmt.png differ diff --git a/media/sqlgram/AnyOrAll.png b/media/sqlgram/AnyOrAll.png index 632062355882..139781b8d5a7 100644 Binary files a/media/sqlgram/AnyOrAll.png and b/media/sqlgram/AnyOrAll.png differ diff --git a/media/sqlgram/AsOpt.png b/media/sqlgram/AsOpt.png index c7f4f1227e0d..2de9722a2b8a 100644 Binary files a/media/sqlgram/AsOpt.png and b/media/sqlgram/AsOpt.png differ diff --git a/media/sqlgram/Assignment.png b/media/sqlgram/Assignment.png index 3c4ad09cf1c2..87ee712d816a 100644 Binary files a/media/sqlgram/Assignment.png and b/media/sqlgram/Assignment.png differ diff --git a/media/sqlgram/AssignmentList.png b/media/sqlgram/AssignmentList.png index 705000ea2d07..07095bb78797 100644 Binary files a/media/sqlgram/AssignmentList.png and b/media/sqlgram/AssignmentList.png differ diff --git a/media/sqlgram/AuthOption.png b/media/sqlgram/AuthOption.png index 4640eaea484c..7abd7ec785a7 100644 Binary files a/media/sqlgram/AuthOption.png and b/media/sqlgram/AuthOption.png differ diff --git a/media/sqlgram/AuthString.png b/media/sqlgram/AuthString.png new file mode 100644 index 000000000000..318a65f09566 Binary files /dev/null and b/media/sqlgram/AuthString.png differ diff --git a/media/sqlgram/BRIEBooleanOptionName.png b/media/sqlgram/BRIEBooleanOptionName.png new file mode 100644 index 000000000000..d2fa7736b508 Binary files /dev/null and b/media/sqlgram/BRIEBooleanOptionName.png differ diff --git a/media/sqlgram/BRIEKeywordOptionName.png b/media/sqlgram/BRIEKeywordOptionName.png new file mode 100644 index 000000000000..b6ea9b185236 Binary files /dev/null and b/media/sqlgram/BRIEKeywordOptionName.png differ diff --git a/media/sqlgram/BRIEOption.png b/media/sqlgram/BRIEOption.png new file mode 100644 index 000000000000..681caf4b151b Binary files /dev/null and b/media/sqlgram/BRIEOption.png differ diff --git a/media/sqlgram/BRIEStmt.png b/media/sqlgram/BRIEStmt.png new file mode 100644 index 000000000000..4be04132f4b2 Binary files /dev/null and b/media/sqlgram/BRIEStmt.png differ diff --git a/media/sqlgram/BRIEStringOptionName.png b/media/sqlgram/BRIEStringOptionName.png new file mode 100644 index 000000000000..a8a70b383727 Binary files /dev/null and b/media/sqlgram/BRIEStringOptionName.png differ diff --git a/media/sqlgram/BRIETables.png b/media/sqlgram/BRIETables.png new file mode 100644 index 000000000000..e460994bfdc0 Binary files /dev/null and b/media/sqlgram/BRIETables.png differ diff --git a/media/sqlgram/BeginTransactionStmt.png b/media/sqlgram/BeginTransactionStmt.png index 1b9e6c371189..b7cda69124b2 100644 Binary files a/media/sqlgram/BeginTransactionStmt.png and b/media/sqlgram/BeginTransactionStmt.png differ diff --git a/media/sqlgram/BetweenOrNotOp.png b/media/sqlgram/BetweenOrNotOp.png index 188861a4623b..cd6aa42eafc9 100644 Binary files a/media/sqlgram/BetweenOrNotOp.png and b/media/sqlgram/BetweenOrNotOp.png differ diff --git a/media/sqlgram/BinlogStmt.png b/media/sqlgram/BinlogStmt.png index 8a960849e816..416142f83cce 100644 Binary files a/media/sqlgram/BinlogStmt.png and b/media/sqlgram/BinlogStmt.png differ diff --git a/media/sqlgram/BitExpr.png b/media/sqlgram/BitExpr.png index 6b9b072101f0..8fbb3e10936a 100644 Binary files a/media/sqlgram/BitExpr.png and b/media/sqlgram/BitExpr.png differ diff --git a/media/sqlgram/BlobType.png b/media/sqlgram/BlobType.png index 169ec7922bcb..5e3e21564277 100644 Binary files a/media/sqlgram/BlobType.png and b/media/sqlgram/BlobType.png differ diff --git a/media/sqlgram/Boolean.png b/media/sqlgram/Boolean.png new file mode 100644 index 000000000000..b44f358d666e Binary files /dev/null and b/media/sqlgram/Boolean.png differ diff --git a/media/sqlgram/BooleanType.png b/media/sqlgram/BooleanType.png index e6c5722e55be..257c5a895bff 100644 Binary files a/media/sqlgram/BooleanType.png and b/media/sqlgram/BooleanType.png differ diff --git a/media/sqlgram/BuggyDefaultFalseDistinctOpt.png b/media/sqlgram/BuggyDefaultFalseDistinctOpt.png index 8ebe8f52a0a8..445384c4f643 100644 Binary files a/media/sqlgram/BuggyDefaultFalseDistinctOpt.png and b/media/sqlgram/BuggyDefaultFalseDistinctOpt.png differ diff --git a/media/sqlgram/ByItem.png b/media/sqlgram/ByItem.png index 3fec9e7443e0..e0d9345531ba 100644 Binary files a/media/sqlgram/ByItem.png and b/media/sqlgram/ByItem.png differ diff --git a/media/sqlgram/ByList.png b/media/sqlgram/ByList.png index 88837f1be6d8..48d4b3848c38 100644 Binary files a/media/sqlgram/ByList.png and b/media/sqlgram/ByList.png differ diff --git a/media/sqlgram/CastType.png b/media/sqlgram/CastType.png index d788d8f03399..20c8311c35a3 100644 Binary files a/media/sqlgram/CastType.png and b/media/sqlgram/CastType.png differ diff --git a/media/sqlgram/ChangeStmt.png b/media/sqlgram/ChangeStmt.png new file mode 100644 index 000000000000..e14644f3b24c Binary files /dev/null and b/media/sqlgram/ChangeStmt.png differ diff --git a/media/sqlgram/Char.png b/media/sqlgram/Char.png new file mode 100644 index 000000000000..4f1b3e307e64 Binary files /dev/null and b/media/sqlgram/Char.png differ diff --git a/media/sqlgram/CharsetKw.png b/media/sqlgram/CharsetKw.png index b0a670481a2c..d3ca449930d8 100644 Binary files a/media/sqlgram/CharsetKw.png and b/media/sqlgram/CharsetKw.png differ diff --git a/media/sqlgram/CharsetName.png b/media/sqlgram/CharsetName.png index d8d499bb82c8..5de51401f29d 100644 Binary files a/media/sqlgram/CharsetName.png and b/media/sqlgram/CharsetName.png differ diff --git a/media/sqlgram/CharsetNameOrDefault.png b/media/sqlgram/CharsetNameOrDefault.png new file mode 100644 index 000000000000..871cea190bce Binary files /dev/null and b/media/sqlgram/CharsetNameOrDefault.png differ diff --git a/media/sqlgram/CharsetOpt.png b/media/sqlgram/CharsetOpt.png index 45dacbeaae62..92378fef46bb 100644 Binary files a/media/sqlgram/CharsetOpt.png and b/media/sqlgram/CharsetOpt.png differ diff --git a/media/sqlgram/ClearPasswordExpireOptions.png b/media/sqlgram/ClearPasswordExpireOptions.png new file mode 100644 index 000000000000..2b1ce8625534 Binary files /dev/null and b/media/sqlgram/ClearPasswordExpireOptions.png differ diff --git a/media/sqlgram/CollationName.png b/media/sqlgram/CollationName.png new file mode 100644 index 000000000000..8584cc53bfc6 Binary files /dev/null and b/media/sqlgram/CollationName.png differ diff --git a/media/sqlgram/ColumnDef.png b/media/sqlgram/ColumnDef.png index ddf993873c8a..0409d474e95a 100644 Binary files a/media/sqlgram/ColumnDef.png and b/media/sqlgram/ColumnDef.png differ diff --git a/media/sqlgram/ColumnFormat.png b/media/sqlgram/ColumnFormat.png new file mode 100644 index 000000000000..0390994bd182 Binary files /dev/null and b/media/sqlgram/ColumnFormat.png differ diff --git a/media/sqlgram/ColumnKeywordOpt.png b/media/sqlgram/ColumnKeywordOpt.png index 6466b9726a3e..cf1091d6efef 100644 Binary files a/media/sqlgram/ColumnKeywordOpt.png and b/media/sqlgram/ColumnKeywordOpt.png differ diff --git a/media/sqlgram/ColumnName.png b/media/sqlgram/ColumnName.png index 86fcc2e9f476..2b8e612df13b 100644 Binary files a/media/sqlgram/ColumnName.png and b/media/sqlgram/ColumnName.png differ diff --git a/media/sqlgram/ColumnNameList.png b/media/sqlgram/ColumnNameList.png index e19e68a90b5b..abcf5b470917 100644 Binary files a/media/sqlgram/ColumnNameList.png and b/media/sqlgram/ColumnNameList.png differ diff --git a/media/sqlgram/ColumnNameListOpt.png b/media/sqlgram/ColumnNameListOpt.png index 2014dd63e70a..55cfe14e0375 100644 Binary files a/media/sqlgram/ColumnNameListOpt.png and b/media/sqlgram/ColumnNameListOpt.png differ diff --git a/media/sqlgram/ColumnNameOrUserVarListOpt.png b/media/sqlgram/ColumnNameOrUserVarListOpt.png new file mode 100644 index 000000000000..9236a3148fd3 Binary files /dev/null and b/media/sqlgram/ColumnNameOrUserVarListOpt.png differ diff --git a/media/sqlgram/ColumnNameOrUserVarListOptWithBrackets.png b/media/sqlgram/ColumnNameOrUserVarListOptWithBrackets.png new file mode 100644 index 000000000000..b447447922c6 Binary files /dev/null and b/media/sqlgram/ColumnNameOrUserVarListOptWithBrackets.png differ diff --git a/media/sqlgram/ColumnNameOrUserVariable.png b/media/sqlgram/ColumnNameOrUserVariable.png new file mode 100644 index 000000000000..61534bdf211a Binary files /dev/null and b/media/sqlgram/ColumnNameOrUserVariable.png differ diff --git a/media/sqlgram/ColumnOption.png b/media/sqlgram/ColumnOption.png index 5dd57820ce54..abe1360c46eb 100644 Binary files a/media/sqlgram/ColumnOption.png and b/media/sqlgram/ColumnOption.png differ diff --git a/media/sqlgram/ColumnOptionList.png b/media/sqlgram/ColumnOptionList.png new file mode 100644 index 000000000000..a32091950944 Binary files /dev/null and b/media/sqlgram/ColumnOptionList.png differ diff --git a/media/sqlgram/ColumnOptionListOpt.png b/media/sqlgram/ColumnOptionListOpt.png index 5c31e00c868a..1d7e47ee4415 100644 Binary files a/media/sqlgram/ColumnOptionListOpt.png and b/media/sqlgram/ColumnOptionListOpt.png differ diff --git a/media/sqlgram/ColumnPosition.png b/media/sqlgram/ColumnPosition.png index 2dc543e0e8f8..5008e0cdf96b 100644 Binary files a/media/sqlgram/ColumnPosition.png and b/media/sqlgram/ColumnPosition.png differ diff --git a/media/sqlgram/ColumnSetValue.png b/media/sqlgram/ColumnSetValue.png index a73716abdaa2..87ee712d816a 100644 Binary files a/media/sqlgram/ColumnSetValue.png and b/media/sqlgram/ColumnSetValue.png differ diff --git a/media/sqlgram/CommitStmt.png b/media/sqlgram/CommitStmt.png index 180ea3a10499..c327b22bdd01 100644 Binary files a/media/sqlgram/CommitStmt.png and b/media/sqlgram/CommitStmt.png differ diff --git a/media/sqlgram/CompareOp.png b/media/sqlgram/CompareOp.png index 3627972dcd13..e265b1772414 100644 Binary files a/media/sqlgram/CompareOp.png and b/media/sqlgram/CompareOp.png differ diff --git a/media/sqlgram/CompletionTypeWithinTransaction.png b/media/sqlgram/CompletionTypeWithinTransaction.png new file mode 100644 index 000000000000..dcb9fea585a2 Binary files /dev/null and b/media/sqlgram/CompletionTypeWithinTransaction.png differ diff --git a/media/sqlgram/ConnectionOption.png b/media/sqlgram/ConnectionOption.png new file mode 100644 index 000000000000..d8bf9433881c Binary files /dev/null and b/media/sqlgram/ConnectionOption.png differ diff --git a/media/sqlgram/ConnectionOptions.png b/media/sqlgram/ConnectionOptions.png new file mode 100644 index 000000000000..3536255cedaf Binary files /dev/null and b/media/sqlgram/ConnectionOptions.png differ diff --git a/media/sqlgram/Constraint.png b/media/sqlgram/Constraint.png index 4fd22ba93cb2..ca8dee46423d 100644 Binary files a/media/sqlgram/Constraint.png and b/media/sqlgram/Constraint.png differ diff --git a/media/sqlgram/ConstraintElem.png b/media/sqlgram/ConstraintElem.png index b6f81d0f7308..b9bc8a10b0af 100644 Binary files a/media/sqlgram/ConstraintElem.png and b/media/sqlgram/ConstraintElem.png differ diff --git a/media/sqlgram/ConstraintKeywordOpt.png b/media/sqlgram/ConstraintKeywordOpt.png index 26ea83630964..d377f94cbae2 100644 Binary files a/media/sqlgram/ConstraintKeywordOpt.png and b/media/sqlgram/ConstraintKeywordOpt.png differ diff --git a/media/sqlgram/CreateBindingStmt.png b/media/sqlgram/CreateBindingStmt.png index 880d909f49ac..8515685b625f 100644 Binary files a/media/sqlgram/CreateBindingStmt.png and b/media/sqlgram/CreateBindingStmt.png differ diff --git a/media/sqlgram/CreateDatabaseStmt.png b/media/sqlgram/CreateDatabaseStmt.png index 240bd250f569..706026e18071 100644 Binary files a/media/sqlgram/CreateDatabaseStmt.png and b/media/sqlgram/CreateDatabaseStmt.png differ diff --git a/media/sqlgram/CreateIndexStmt.png b/media/sqlgram/CreateIndexStmt.png index ae7145675d60..1f03b2a94646 100644 Binary files a/media/sqlgram/CreateIndexStmt.png and b/media/sqlgram/CreateIndexStmt.png differ diff --git a/media/sqlgram/CreateIndexStmtUnique.png.bak b/media/sqlgram/CreateIndexStmtUnique.png.bak new file mode 100644 index 000000000000..0e408c1fe207 Binary files /dev/null and b/media/sqlgram/CreateIndexStmtUnique.png.bak differ diff --git a/media/sqlgram/CreateRoleStmt.png b/media/sqlgram/CreateRoleStmt.png new file mode 100644 index 000000000000..0eb656dde737 Binary files /dev/null and b/media/sqlgram/CreateRoleStmt.png differ diff --git a/media/sqlgram/CreateSequenceOptionListOpt.png b/media/sqlgram/CreateSequenceOptionListOpt.png old mode 100755 new mode 100644 index 317d2ccb2b14..dd533e0cdcdf Binary files a/media/sqlgram/CreateSequenceOptionListOpt.png and b/media/sqlgram/CreateSequenceOptionListOpt.png differ diff --git a/media/sqlgram/CreateSequenceStmt.png b/media/sqlgram/CreateSequenceStmt.png old mode 100755 new mode 100644 index 41609cfc47cb..efe8312f442b Binary files a/media/sqlgram/CreateSequenceStmt.png and b/media/sqlgram/CreateSequenceStmt.png differ diff --git a/media/sqlgram/CreateTableLikeStmt.png b/media/sqlgram/CreateTableLikeStmt.png new file mode 100644 index 000000000000..baf751986e99 Binary files /dev/null and b/media/sqlgram/CreateTableLikeStmt.png differ diff --git a/media/sqlgram/CreateTableOptionListOpt.png b/media/sqlgram/CreateTableOptionListOpt.png index 3c38b3082fe0..453043e33456 100644 Binary files a/media/sqlgram/CreateTableOptionListOpt.png and b/media/sqlgram/CreateTableOptionListOpt.png differ diff --git a/media/sqlgram/CreateTableSelectOpt.png b/media/sqlgram/CreateTableSelectOpt.png index ede7d1311f56..ebcab19b85fa 100644 Binary files a/media/sqlgram/CreateTableSelectOpt.png and b/media/sqlgram/CreateTableSelectOpt.png differ diff --git a/media/sqlgram/CreateTableStmt.png b/media/sqlgram/CreateTableStmt.png index ef749e2381ba..4f1ea3aab651 100644 Binary files a/media/sqlgram/CreateTableStmt.png and b/media/sqlgram/CreateTableStmt.png differ diff --git a/media/sqlgram/CreateUserStmt.png b/media/sqlgram/CreateUserStmt.png index ae181e58f2a6..7ca70f740f14 100644 Binary files a/media/sqlgram/CreateUserStmt.png and b/media/sqlgram/CreateUserStmt.png differ diff --git a/media/sqlgram/CreateViewSelectOpt.png b/media/sqlgram/CreateViewSelectOpt.png new file mode 100644 index 000000000000..017839d6f07c Binary files /dev/null and b/media/sqlgram/CreateViewSelectOpt.png differ diff --git a/media/sqlgram/CreateViewStmt.png b/media/sqlgram/CreateViewStmt.png index 84feef35db27..97340b300636 100644 Binary files a/media/sqlgram/CreateViewStmt.png and b/media/sqlgram/CreateViewStmt.png differ diff --git a/media/sqlgram/CrossOpt.png b/media/sqlgram/CrossOpt.png index 2b8922b3ecdf..6124b61bc4ef 100644 Binary files a/media/sqlgram/CrossOpt.png and b/media/sqlgram/CrossOpt.png differ diff --git a/media/sqlgram/DBName.png b/media/sqlgram/DBName.png index 065f275b7be4..263fefd9b460 100644 Binary files a/media/sqlgram/DBName.png and b/media/sqlgram/DBName.png differ diff --git a/media/sqlgram/DatabaseOption.png b/media/sqlgram/DatabaseOption.png index d91e3a82d700..3ff8821f5143 100644 Binary files a/media/sqlgram/DatabaseOption.png and b/media/sqlgram/DatabaseOption.png differ diff --git a/media/sqlgram/DatabaseOptionList.png b/media/sqlgram/DatabaseOptionList.png new file mode 100644 index 000000000000..31c5ad78c4b7 Binary files /dev/null and b/media/sqlgram/DatabaseOptionList.png differ diff --git a/media/sqlgram/DatabaseOptionListOpt.png b/media/sqlgram/DatabaseOptionListOpt.png index 3c73525b76cf..dc9b0fb51b02 100644 Binary files a/media/sqlgram/DatabaseOptionListOpt.png and b/media/sqlgram/DatabaseOptionListOpt.png differ diff --git a/media/sqlgram/DateAndTimeType.png b/media/sqlgram/DateAndTimeType.png index 57ef5ac8e5db..81d67c4f7a08 100644 Binary files a/media/sqlgram/DateAndTimeType.png and b/media/sqlgram/DateAndTimeType.png differ diff --git a/media/sqlgram/DeallocateStmt.png b/media/sqlgram/DeallocateStmt.png index a381eea0666d..8e3c073ff37b 100644 Binary files a/media/sqlgram/DeallocateStmt.png and b/media/sqlgram/DeallocateStmt.png differ diff --git a/media/sqlgram/DeallocateSym.png b/media/sqlgram/DeallocateSym.png index e134763d93fc..760b59ed1bf6 100644 Binary files a/media/sqlgram/DeallocateSym.png and b/media/sqlgram/DeallocateSym.png differ diff --git a/media/sqlgram/DefaultFalseDistinctOpt.png b/media/sqlgram/DefaultFalseDistinctOpt.png index 7fa6c1e26914..fa965c0c9432 100644 Binary files a/media/sqlgram/DefaultFalseDistinctOpt.png and b/media/sqlgram/DefaultFalseDistinctOpt.png differ diff --git a/media/sqlgram/DefaultKwdOpt.png b/media/sqlgram/DefaultKwdOpt.png index 78f7647cb0ac..78e556ab9964 100644 Binary files a/media/sqlgram/DefaultKwdOpt.png and b/media/sqlgram/DefaultKwdOpt.png differ diff --git a/media/sqlgram/DefaultTrueDistinctOpt.png b/media/sqlgram/DefaultTrueDistinctOpt.png index 7fa6c1e26914..fa965c0c9432 100644 Binary files a/media/sqlgram/DefaultTrueDistinctOpt.png and b/media/sqlgram/DefaultTrueDistinctOpt.png differ diff --git a/media/sqlgram/DefaultValueExpr.png b/media/sqlgram/DefaultValueExpr.png index 0cd8821fde6a..e922171d9445 100644 Binary files a/media/sqlgram/DefaultValueExpr.png and b/media/sqlgram/DefaultValueExpr.png differ diff --git a/media/sqlgram/DeleteFromStmt.png b/media/sqlgram/DeleteFromStmt.png index 7187e89eaaff..fb3101fd5ce3 100644 Binary files a/media/sqlgram/DeleteFromStmt.png and b/media/sqlgram/DeleteFromStmt.png differ diff --git a/media/sqlgram/DistinctKwd.png b/media/sqlgram/DistinctKwd.png index 4a341f918504..7a5355b66763 100644 Binary files a/media/sqlgram/DistinctKwd.png and b/media/sqlgram/DistinctKwd.png differ diff --git a/media/sqlgram/DistinctOpt.png b/media/sqlgram/DistinctOpt.png index da75ba4eb6d2..fd1ebc91bc6f 100644 Binary files a/media/sqlgram/DistinctOpt.png and b/media/sqlgram/DistinctOpt.png differ diff --git a/media/sqlgram/DoStmt.png b/media/sqlgram/DoStmt.png index 993bde6661dd..e4a01f3f2cde 100644 Binary files a/media/sqlgram/DoStmt.png and b/media/sqlgram/DoStmt.png differ diff --git a/media/sqlgram/DropBindingStmt.png b/media/sqlgram/DropBindingStmt.png index 151cd92a89ae..de028d139c88 100644 Binary files a/media/sqlgram/DropBindingStmt.png and b/media/sqlgram/DropBindingStmt.png differ diff --git a/media/sqlgram/DropDatabaseStmt.png b/media/sqlgram/DropDatabaseStmt.png index 099659768005..337606649d43 100644 Binary files a/media/sqlgram/DropDatabaseStmt.png and b/media/sqlgram/DropDatabaseStmt.png differ diff --git a/media/sqlgram/DropIndexStmt.png b/media/sqlgram/DropIndexStmt.png index 8005a0b04d5b..85f7d2524519 100644 Binary files a/media/sqlgram/DropIndexStmt.png and b/media/sqlgram/DropIndexStmt.png differ diff --git a/media/sqlgram/DropRoleStmt.png b/media/sqlgram/DropRoleStmt.png new file mode 100644 index 000000000000..9f65ffec2c89 Binary files /dev/null and b/media/sqlgram/DropRoleStmt.png differ diff --git a/media/sqlgram/DropSequenceStmt.png b/media/sqlgram/DropSequenceStmt.png old mode 100755 new mode 100644 index f51165e62a1a..d4961d7ef6e0 Binary files a/media/sqlgram/DropSequenceStmt.png and b/media/sqlgram/DropSequenceStmt.png differ diff --git a/media/sqlgram/DropStatsStmt.png b/media/sqlgram/DropStatsStmt.png index fc605803d186..5fd10500f620 100644 Binary files a/media/sqlgram/DropStatsStmt.png and b/media/sqlgram/DropStatsStmt.png differ diff --git a/media/sqlgram/DropTableStmt.png b/media/sqlgram/DropTableStmt.png index fa4bb82d4fc6..ee619208451a 100644 Binary files a/media/sqlgram/DropTableStmt.png and b/media/sqlgram/DropTableStmt.png differ diff --git a/media/sqlgram/DropUserStmt.png b/media/sqlgram/DropUserStmt.png index 27427cfe37ca..a009c5fefe58 100644 Binary files a/media/sqlgram/DropUserStmt.png and b/media/sqlgram/DropUserStmt.png differ diff --git a/media/sqlgram/DropViewStmt.png b/media/sqlgram/DropViewStmt.png index c47b8d5180e2..04d791c0e38d 100644 Binary files a/media/sqlgram/DropViewStmt.png and b/media/sqlgram/DropViewStmt.png differ diff --git a/media/sqlgram/DuplicateOpt.png b/media/sqlgram/DuplicateOpt.png index 55a7952e71ae..93a85164fa25 100644 Binary files a/media/sqlgram/DuplicateOpt.png and b/media/sqlgram/DuplicateOpt.png differ diff --git a/media/sqlgram/ElseOpt.png b/media/sqlgram/ElseOpt.png index 6da79a965822..fe00ebb9b99d 100644 Binary files a/media/sqlgram/ElseOpt.png and b/media/sqlgram/ElseOpt.png differ diff --git a/media/sqlgram/EmptyStmt.png b/media/sqlgram/EmptyStmt.png index 4638d4ea9aa9..2b1ce8625534 100644 Binary files a/media/sqlgram/EmptyStmt.png and b/media/sqlgram/EmptyStmt.png differ diff --git a/media/sqlgram/EncryptionOpt.png b/media/sqlgram/EncryptionOpt.png new file mode 100644 index 000000000000..318a65f09566 Binary files /dev/null and b/media/sqlgram/EncryptionOpt.png differ diff --git a/media/sqlgram/EnforcedOrNot.png b/media/sqlgram/EnforcedOrNot.png new file mode 100644 index 000000000000..13c057776701 Binary files /dev/null and b/media/sqlgram/EnforcedOrNot.png differ diff --git a/media/sqlgram/EnforcedOrNotOpt.png b/media/sqlgram/EnforcedOrNotOpt.png new file mode 100644 index 000000000000..0039df570a1e Binary files /dev/null and b/media/sqlgram/EnforcedOrNotOpt.png differ diff --git a/media/sqlgram/EnforcedOrNotOrNotNullOpt.png b/media/sqlgram/EnforcedOrNotOrNotNullOpt.png new file mode 100644 index 000000000000..90b4940d4685 Binary files /dev/null and b/media/sqlgram/EnforcedOrNotOrNotNullOpt.png differ diff --git a/media/sqlgram/EqOpt.png b/media/sqlgram/EqOpt.png index 4638d4ea9aa9..d82f00bbcf53 100644 Binary files a/media/sqlgram/EqOpt.png and b/media/sqlgram/EqOpt.png differ diff --git a/media/sqlgram/EqOrAssignmentEq.png b/media/sqlgram/EqOrAssignmentEq.png new file mode 100644 index 000000000000..3111a71e57d9 Binary files /dev/null and b/media/sqlgram/EqOrAssignmentEq.png differ diff --git a/media/sqlgram/EscapedTableRef.png b/media/sqlgram/EscapedTableRef.png index 52e2756fd340..9cfae30c5505 100644 Binary files a/media/sqlgram/EscapedTableRef.png and b/media/sqlgram/EscapedTableRef.png differ diff --git a/media/sqlgram/ExecuteStmt.png b/media/sqlgram/ExecuteStmt.png index 6ddbf0cacc0e..80737a783817 100644 Binary files a/media/sqlgram/ExecuteStmt.png and b/media/sqlgram/ExecuteStmt.png differ diff --git a/media/sqlgram/ExplainFormatType.png b/media/sqlgram/ExplainFormatType.png new file mode 100644 index 000000000000..5fd2dfaaf19c Binary files /dev/null and b/media/sqlgram/ExplainFormatType.png differ diff --git a/media/sqlgram/ExplainStmt.png b/media/sqlgram/ExplainStmt.png index b76b1f50a319..90a6bb3439a3 100644 Binary files a/media/sqlgram/ExplainStmt.png and b/media/sqlgram/ExplainStmt.png differ diff --git a/media/sqlgram/ExplainSym.png b/media/sqlgram/ExplainSym.png index 200531f14973..c8882f9a8d02 100644 Binary files a/media/sqlgram/ExplainSym.png and b/media/sqlgram/ExplainSym.png differ diff --git a/media/sqlgram/ExplainableStmt.png b/media/sqlgram/ExplainableStmt.png index bddac1e18228..f3dc1085a109 100644 Binary files a/media/sqlgram/ExplainableStmt.png and b/media/sqlgram/ExplainableStmt.png differ diff --git a/media/sqlgram/ExprOrDefault.png b/media/sqlgram/ExprOrDefault.png index 83398cad99a5..26c5161ff455 100644 Binary files a/media/sqlgram/ExprOrDefault.png and b/media/sqlgram/ExprOrDefault.png differ diff --git a/media/sqlgram/Expression.png b/media/sqlgram/Expression.png index 4e00324dcdcf..428b12a17c35 100644 Binary files a/media/sqlgram/Expression.png and b/media/sqlgram/Expression.png differ diff --git a/media/sqlgram/ExpressionList.png b/media/sqlgram/ExpressionList.png index 0eebf99f7206..ca6f75872572 100644 Binary files a/media/sqlgram/ExpressionList.png and b/media/sqlgram/ExpressionList.png differ diff --git a/media/sqlgram/ExpressionListOpt.png b/media/sqlgram/ExpressionListOpt.png index ebd0285c68db..a86a4e18f5f2 100644 Binary files a/media/sqlgram/ExpressionListOpt.png and b/media/sqlgram/ExpressionListOpt.png differ diff --git a/media/sqlgram/ExpressionOpt.png b/media/sqlgram/ExpressionOpt.png index bf7fb8eec393..4b7c5f269608 100644 Binary files a/media/sqlgram/ExpressionOpt.png and b/media/sqlgram/ExpressionOpt.png differ diff --git a/media/sqlgram/Field.png b/media/sqlgram/Field.png index 91934f5fe064..9fe4367060d4 100644 Binary files a/media/sqlgram/Field.png and b/media/sqlgram/Field.png differ diff --git a/media/sqlgram/FieldAsName.png b/media/sqlgram/FieldAsName.png index 67d680e13352..f737c4d1b20f 100644 Binary files a/media/sqlgram/FieldAsName.png and b/media/sqlgram/FieldAsName.png differ diff --git a/media/sqlgram/FieldAsNameOpt.png b/media/sqlgram/FieldAsNameOpt.png index 07df86782a74..94a4eddcbf05 100644 Binary files a/media/sqlgram/FieldAsNameOpt.png and b/media/sqlgram/FieldAsNameOpt.png differ diff --git a/media/sqlgram/FieldItem.png b/media/sqlgram/FieldItem.png new file mode 100644 index 000000000000..6d57c7abac0e Binary files /dev/null and b/media/sqlgram/FieldItem.png differ diff --git a/media/sqlgram/FieldLen.png b/media/sqlgram/FieldLen.png index 26086e832c5c..0ff9a48909ab 100644 Binary files a/media/sqlgram/FieldLen.png and b/media/sqlgram/FieldLen.png differ diff --git a/media/sqlgram/FieldOpt.png b/media/sqlgram/FieldOpt.png index 72f6004e98e3..3171ee4ff3cd 100644 Binary files a/media/sqlgram/FieldOpt.png and b/media/sqlgram/FieldOpt.png differ diff --git a/media/sqlgram/FieldOpts.png b/media/sqlgram/FieldOpts.png index e96900f57897..f997e461e2dd 100644 Binary files a/media/sqlgram/FieldOpts.png and b/media/sqlgram/FieldOpts.png differ diff --git a/media/sqlgram/FieldTerminator.png b/media/sqlgram/FieldTerminator.png new file mode 100644 index 000000000000..10ef4c6fc287 Binary files /dev/null and b/media/sqlgram/FieldTerminator.png differ diff --git a/media/sqlgram/Fields.png b/media/sqlgram/Fields.png index d3c7a2497b19..5195673d51c3 100644 Binary files a/media/sqlgram/Fields.png and b/media/sqlgram/Fields.png differ diff --git a/media/sqlgram/FieldsOrColumns.png b/media/sqlgram/FieldsOrColumns.png index 38d61f912f88..1b42f89d01c8 100644 Binary files a/media/sqlgram/FieldsOrColumns.png and b/media/sqlgram/FieldsOrColumns.png differ diff --git a/media/sqlgram/FixedPointType.png b/media/sqlgram/FixedPointType.png index 521b7baf92f9..aa4a10b808e8 100644 Binary files a/media/sqlgram/FixedPointType.png and b/media/sqlgram/FixedPointType.png differ diff --git a/media/sqlgram/FlashbackTableStmt.png b/media/sqlgram/FlashbackTableStmt.png new file mode 100755 index 000000000000..bfea3eef2e8d Binary files /dev/null and b/media/sqlgram/FlashbackTableStmt.png differ diff --git a/media/sqlgram/FlashbackToNewName.png b/media/sqlgram/FlashbackToNewName.png new file mode 100755 index 000000000000..7c072de89831 Binary files /dev/null and b/media/sqlgram/FlashbackToNewName.png differ diff --git a/media/sqlgram/FloatOpt.png b/media/sqlgram/FloatOpt.png index f0dfa0222495..0068fb3dd754 100644 Binary files a/media/sqlgram/FloatOpt.png and b/media/sqlgram/FloatOpt.png differ diff --git a/media/sqlgram/FloatingPointType.png b/media/sqlgram/FloatingPointType.png index af723847c39b..e354b3e5d9a3 100644 Binary files a/media/sqlgram/FloatingPointType.png and b/media/sqlgram/FloatingPointType.png differ diff --git a/media/sqlgram/FlushOption.png b/media/sqlgram/FlushOption.png index beeccfd23542..2ae15f615b4e 100644 Binary files a/media/sqlgram/FlushOption.png and b/media/sqlgram/FlushOption.png differ diff --git a/media/sqlgram/FlushStmt.png b/media/sqlgram/FlushStmt.png index 98b182fe3eb9..01c8a2262cf7 100644 Binary files a/media/sqlgram/FlushStmt.png and b/media/sqlgram/FlushStmt.png differ diff --git a/media/sqlgram/FromDual.png b/media/sqlgram/FromDual.png index 7fabe7be9854..82b4175de964 100644 Binary files a/media/sqlgram/FromDual.png and b/media/sqlgram/FromDual.png differ diff --git a/media/sqlgram/FromOrIn.png b/media/sqlgram/FromOrIn.png index 82e06a36b625..10344be9c607 100644 Binary files a/media/sqlgram/FromOrIn.png and b/media/sqlgram/FromOrIn.png differ diff --git a/media/sqlgram/FulltextSearchModifierOpt.png b/media/sqlgram/FulltextSearchModifierOpt.png new file mode 100644 index 000000000000..231b693ef4f9 Binary files /dev/null and b/media/sqlgram/FulltextSearchModifierOpt.png differ diff --git a/media/sqlgram/FuncDatetimePrec.png b/media/sqlgram/FuncDatetimePrec.png index fa5dda98229c..b9084b77e498 100644 Binary files a/media/sqlgram/FuncDatetimePrec.png and b/media/sqlgram/FuncDatetimePrec.png differ diff --git a/media/sqlgram/FuncDatetimePrecList.png b/media/sqlgram/FuncDatetimePrecList.png new file mode 100644 index 000000000000..cdccd0fdf897 Binary files /dev/null and b/media/sqlgram/FuncDatetimePrecList.png differ diff --git a/media/sqlgram/FuncDatetimePrecListOpt.png b/media/sqlgram/FuncDatetimePrecListOpt.png index 4638d4ea9aa9..7cd1de97a0e8 100644 Binary files a/media/sqlgram/FuncDatetimePrecListOpt.png and b/media/sqlgram/FuncDatetimePrecListOpt.png differ diff --git a/media/sqlgram/FunctionCallGeneric.png b/media/sqlgram/FunctionCallGeneric.png new file mode 100644 index 000000000000..539f4b945663 Binary files /dev/null and b/media/sqlgram/FunctionCallGeneric.png differ diff --git a/media/sqlgram/FunctionCallKeyword.png b/media/sqlgram/FunctionCallKeyword.png index 402242b627db..722561b0aa33 100644 Binary files a/media/sqlgram/FunctionCallKeyword.png and b/media/sqlgram/FunctionCallKeyword.png differ diff --git a/media/sqlgram/FunctionCallNonKeyword.png b/media/sqlgram/FunctionCallNonKeyword.png index d94fdee067ea..501ddc5c6731 100644 Binary files a/media/sqlgram/FunctionCallNonKeyword.png and b/media/sqlgram/FunctionCallNonKeyword.png differ diff --git a/media/sqlgram/FunctionNameConflict.png b/media/sqlgram/FunctionNameConflict.png index 2ed740ad152a..79099e2ed9e5 100644 Binary files a/media/sqlgram/FunctionNameConflict.png and b/media/sqlgram/FunctionNameConflict.png differ diff --git a/media/sqlgram/FunctionNameDateArith.png b/media/sqlgram/FunctionNameDateArith.png new file mode 100644 index 000000000000..b17261e82adb Binary files /dev/null and b/media/sqlgram/FunctionNameDateArith.png differ diff --git a/media/sqlgram/FunctionNameDateArithMultiForms.png b/media/sqlgram/FunctionNameDateArithMultiForms.png new file mode 100644 index 000000000000..3ee138c8214c Binary files /dev/null and b/media/sqlgram/FunctionNameDateArithMultiForms.png differ diff --git a/media/sqlgram/FunctionNameDatetimePrecision.png b/media/sqlgram/FunctionNameDatetimePrecision.png index 6c42fdf8a408..97f4e9fddaa2 100644 Binary files a/media/sqlgram/FunctionNameDatetimePrecision.png and b/media/sqlgram/FunctionNameDatetimePrecision.png differ diff --git a/media/sqlgram/FunctionNameOptionalBraces.png b/media/sqlgram/FunctionNameOptionalBraces.png index b3aa68bd0652..88e79b01dea3 100644 Binary files a/media/sqlgram/FunctionNameOptionalBraces.png and b/media/sqlgram/FunctionNameOptionalBraces.png differ diff --git a/media/sqlgram/FunctionNameSequence.png b/media/sqlgram/FunctionNameSequence.png new file mode 100644 index 000000000000..da0ae859d5bc Binary files /dev/null and b/media/sqlgram/FunctionNameSequence.png differ diff --git a/media/sqlgram/GeneratedAlways.png b/media/sqlgram/GeneratedAlways.png index 8d87e83cf7df..df4ecc71b3db 100644 Binary files a/media/sqlgram/GeneratedAlways.png and b/media/sqlgram/GeneratedAlways.png differ diff --git a/media/sqlgram/GetFormatSelector.png b/media/sqlgram/GetFormatSelector.png index ad385bde3324..c28d88579316 100644 Binary files a/media/sqlgram/GetFormatSelector.png and b/media/sqlgram/GetFormatSelector.png differ diff --git a/media/sqlgram/GlobalScope.png b/media/sqlgram/GlobalScope.png index f5f7dbd2496a..1c6bb656fd8b 100644 Binary files a/media/sqlgram/GlobalScope.png and b/media/sqlgram/GlobalScope.png differ diff --git a/media/sqlgram/GrantRoleStmt.png b/media/sqlgram/GrantRoleStmt.png new file mode 100644 index 000000000000..c2984fdc001d Binary files /dev/null and b/media/sqlgram/GrantRoleStmt.png differ diff --git a/media/sqlgram/GrantStmt.png b/media/sqlgram/GrantStmt.png index ac8bc76a9107..fb7bcdc02b29 100644 Binary files a/media/sqlgram/GrantStmt.png and b/media/sqlgram/GrantStmt.png differ diff --git a/media/sqlgram/GroupByClause.png b/media/sqlgram/GroupByClause.png index 289893da6a63..7ce456c2486c 100644 Binary files a/media/sqlgram/GroupByClause.png and b/media/sqlgram/GroupByClause.png differ diff --git a/media/sqlgram/HandleRange.png b/media/sqlgram/HandleRange.png index a71a2bfdee4c..7a45eaae9be3 100644 Binary files a/media/sqlgram/HandleRange.png and b/media/sqlgram/HandleRange.png differ diff --git a/media/sqlgram/HashString.png b/media/sqlgram/HashString.png new file mode 100644 index 000000000000..318a65f09566 Binary files /dev/null and b/media/sqlgram/HashString.png differ diff --git a/media/sqlgram/HavingClause.png b/media/sqlgram/HavingClause.png index 0a4e521712d6..f823e172545e 100644 Binary files a/media/sqlgram/HavingClause.png and b/media/sqlgram/HavingClause.png differ diff --git a/media/sqlgram/Identifier.png b/media/sqlgram/Identifier.png index c021b2d3fb3a..0aafe5667367 100644 Binary files a/media/sqlgram/Identifier.png and b/media/sqlgram/Identifier.png differ diff --git a/media/sqlgram/IfExists.png b/media/sqlgram/IfExists.png old mode 100644 new mode 100755 index cf5ca4d5cd07..000bc54a555f Binary files a/media/sqlgram/IfExists.png and b/media/sqlgram/IfExists.png differ diff --git a/media/sqlgram/IfNotExists.png b/media/sqlgram/IfNotExists.png index 363cf2bbe865..c4c95dbf5164 100644 Binary files a/media/sqlgram/IfNotExists.png and b/media/sqlgram/IfNotExists.png differ diff --git a/media/sqlgram/IgnoreLines.png b/media/sqlgram/IgnoreLines.png index 59c3757d8be8..79341dfe46c1 100644 Binary files a/media/sqlgram/IgnoreLines.png and b/media/sqlgram/IgnoreLines.png differ diff --git a/media/sqlgram/IgnoreOptional.png b/media/sqlgram/IgnoreOptional.png old mode 100644 new mode 100755 index f3b4f0045a8c..5211204ee1b2 Binary files a/media/sqlgram/IgnoreOptional.png and b/media/sqlgram/IgnoreOptional.png differ diff --git a/media/sqlgram/InOrNotOp.png b/media/sqlgram/InOrNotOp.png index f702fb70fa14..0d195ccf54b9 100644 Binary files a/media/sqlgram/InOrNotOp.png and b/media/sqlgram/InOrNotOp.png differ diff --git a/media/sqlgram/IndexAdviseStmt.png b/media/sqlgram/IndexAdviseStmt.png new file mode 100644 index 000000000000..4d9f6424b3d0 Binary files /dev/null and b/media/sqlgram/IndexAdviseStmt.png differ diff --git a/media/sqlgram/IndexHint.png b/media/sqlgram/IndexHint.png index 9f7bc267999f..363b2d79cbdc 100644 Binary files a/media/sqlgram/IndexHint.png and b/media/sqlgram/IndexHint.png differ diff --git a/media/sqlgram/IndexHintListOpt.png b/media/sqlgram/IndexHintListOpt.png index 4cb5aedc4dc7..adc66dcd60c4 100644 Binary files a/media/sqlgram/IndexHintListOpt.png and b/media/sqlgram/IndexHintListOpt.png differ diff --git a/media/sqlgram/IndexHintScope.png b/media/sqlgram/IndexHintScope.png index bb78cae45589..e27b80619702 100644 Binary files a/media/sqlgram/IndexHintScope.png and b/media/sqlgram/IndexHintScope.png differ diff --git a/media/sqlgram/IndexHintType.png b/media/sqlgram/IndexHintType.png index f0f26ab7033e..a3c72c32b3a9 100644 Binary files a/media/sqlgram/IndexHintType.png and b/media/sqlgram/IndexHintType.png differ diff --git a/media/sqlgram/IndexInvisible.png b/media/sqlgram/IndexInvisible.png new file mode 100644 index 000000000000..41d02b729e9c Binary files /dev/null and b/media/sqlgram/IndexInvisible.png differ diff --git a/media/sqlgram/IndexKeyTypeOpt.png b/media/sqlgram/IndexKeyTypeOpt.png new file mode 100644 index 000000000000..e49f54505d21 Binary files /dev/null and b/media/sqlgram/IndexKeyTypeOpt.png differ diff --git a/media/sqlgram/IndexLockAndAlgorithmOpt.png b/media/sqlgram/IndexLockAndAlgorithmOpt.png new file mode 100644 index 000000000000..5105f631f723 Binary files /dev/null and b/media/sqlgram/IndexLockAndAlgorithmOpt.png differ diff --git a/media/sqlgram/IndexName.png b/media/sqlgram/IndexName.png index 01affb7e7711..c9d3ac22387b 100644 Binary files a/media/sqlgram/IndexName.png and b/media/sqlgram/IndexName.png differ diff --git a/media/sqlgram/IndexNameAndTypeOpt.png b/media/sqlgram/IndexNameAndTypeOpt.png new file mode 100644 index 000000000000..e49fd291e554 Binary files /dev/null and b/media/sqlgram/IndexNameAndTypeOpt.png differ diff --git a/media/sqlgram/IndexNameList.png b/media/sqlgram/IndexNameList.png index 2946fe801ce0..6c3ea1f60238 100644 Binary files a/media/sqlgram/IndexNameList.png and b/media/sqlgram/IndexNameList.png differ diff --git a/media/sqlgram/IndexOption.png b/media/sqlgram/IndexOption.png index 15623c3ab0ff..7cbcff2e9108 100644 Binary files a/media/sqlgram/IndexOption.png and b/media/sqlgram/IndexOption.png differ diff --git a/media/sqlgram/IndexOptionList.png b/media/sqlgram/IndexOptionList.png index fb5d448e94cd..fe52d3763932 100644 Binary files a/media/sqlgram/IndexOptionList.png and b/media/sqlgram/IndexOptionList.png differ diff --git a/media/sqlgram/IndexPartSpecification.png b/media/sqlgram/IndexPartSpecification.png new file mode 100644 index 000000000000..bef0cf883e7c Binary files /dev/null and b/media/sqlgram/IndexPartSpecification.png differ diff --git a/media/sqlgram/IndexPartSpecificationList.png b/media/sqlgram/IndexPartSpecificationList.png new file mode 100644 index 000000000000..85419990add5 Binary files /dev/null and b/media/sqlgram/IndexPartSpecificationList.png differ diff --git a/media/sqlgram/IndexPartSpecificationListOpt.png b/media/sqlgram/IndexPartSpecificationListOpt.png new file mode 100644 index 000000000000..6c159d5a300c Binary files /dev/null and b/media/sqlgram/IndexPartSpecificationListOpt.png differ diff --git a/media/sqlgram/IndexType.png b/media/sqlgram/IndexType.png index 8e090d25e5bd..a2c285781ded 100644 Binary files a/media/sqlgram/IndexType.png and b/media/sqlgram/IndexType.png differ diff --git a/media/sqlgram/IndexTypeName.png b/media/sqlgram/IndexTypeName.png new file mode 100644 index 000000000000..d390ad6ea4d0 Binary files /dev/null and b/media/sqlgram/IndexTypeName.png differ diff --git a/media/sqlgram/IndexTypeOpt.png b/media/sqlgram/IndexTypeOpt.png index 5345a1ed32d8..0987b0964c6c 100644 Binary files a/media/sqlgram/IndexTypeOpt.png and b/media/sqlgram/IndexTypeOpt.png differ diff --git a/media/sqlgram/InsertIntoStmt.png b/media/sqlgram/InsertIntoStmt.png index f0bab97cf0a7..19c3d46ea418 100644 Binary files a/media/sqlgram/InsertIntoStmt.png and b/media/sqlgram/InsertIntoStmt.png differ diff --git a/media/sqlgram/InsertValues.png b/media/sqlgram/InsertValues.png index 9b6f90247ffe..8ba4ae1f4eac 100644 Binary files a/media/sqlgram/InsertValues.png and b/media/sqlgram/InsertValues.png differ diff --git a/media/sqlgram/InstanceOption.png b/media/sqlgram/InstanceOption.png new file mode 100644 index 000000000000..bfc05d4d66ab Binary files /dev/null and b/media/sqlgram/InstanceOption.png differ diff --git a/media/sqlgram/Int64Num.png b/media/sqlgram/Int64Num.png new file mode 100755 index 000000000000..e5fcd5310d7b Binary files /dev/null and b/media/sqlgram/Int64Num.png differ diff --git a/media/sqlgram/IntegerType.png b/media/sqlgram/IntegerType.png index 9378e28583ce..cfe2e1c20450 100644 Binary files a/media/sqlgram/IntegerType.png and b/media/sqlgram/IntegerType.png differ diff --git a/media/sqlgram/IntoOpt.png b/media/sqlgram/IntoOpt.png index 18f3a0fd1211..29ecc99339f6 100644 Binary files a/media/sqlgram/IntoOpt.png and b/media/sqlgram/IntoOpt.png differ diff --git a/media/sqlgram/IsOrNotOp.png b/media/sqlgram/IsOrNotOp.png index bdebee044839..cdfd8596ad26 100644 Binary files a/media/sqlgram/IsOrNotOp.png and b/media/sqlgram/IsOrNotOp.png differ diff --git a/media/sqlgram/IsolationLevel.png b/media/sqlgram/IsolationLevel.png index e4143e2ce6d1..4cc6a40bfb8f 100644 Binary files a/media/sqlgram/IsolationLevel.png and b/media/sqlgram/IsolationLevel.png differ diff --git a/media/sqlgram/JoinTable.png b/media/sqlgram/JoinTable.png index 794086e52634..f980b06b9319 100644 Binary files a/media/sqlgram/JoinTable.png and b/media/sqlgram/JoinTable.png differ diff --git a/media/sqlgram/JoinType.png b/media/sqlgram/JoinType.png index 90330a1efc7e..36f4492a79be 100644 Binary files a/media/sqlgram/JoinType.png and b/media/sqlgram/JoinType.png differ diff --git a/media/sqlgram/KeyOrIndex.png b/media/sqlgram/KeyOrIndex.png index 387f9cd1b993..07c143db9513 100644 Binary files a/media/sqlgram/KeyOrIndex.png and b/media/sqlgram/KeyOrIndex.png differ diff --git a/media/sqlgram/KeyOrIndexOpt.png b/media/sqlgram/KeyOrIndexOpt.png index a51a5b28c62f..051ae13cedb5 100644 Binary files a/media/sqlgram/KeyOrIndexOpt.png and b/media/sqlgram/KeyOrIndexOpt.png differ diff --git a/media/sqlgram/KillOrKillTiDB.png b/media/sqlgram/KillOrKillTiDB.png index deb97d683fe2..183016a93bfb 100644 Binary files a/media/sqlgram/KillOrKillTiDB.png and b/media/sqlgram/KillOrKillTiDB.png differ diff --git a/media/sqlgram/KillStmt.png b/media/sqlgram/KillStmt.png index 9f2a6e91fe90..0f68ae0096aa 100644 Binary files a/media/sqlgram/KillStmt.png and b/media/sqlgram/KillStmt.png differ diff --git a/media/sqlgram/LengthNum.png b/media/sqlgram/LengthNum.png index d98daaa364eb..ce90e05ecb59 100644 Binary files a/media/sqlgram/LengthNum.png and b/media/sqlgram/LengthNum.png differ diff --git a/media/sqlgram/LikeEscapeOpt.png b/media/sqlgram/LikeEscapeOpt.png index 4638d4ea9aa9..783eb5cbf5c3 100644 Binary files a/media/sqlgram/LikeEscapeOpt.png and b/media/sqlgram/LikeEscapeOpt.png differ diff --git a/media/sqlgram/LikeOrNotOp.png b/media/sqlgram/LikeOrNotOp.png index 62830897fc92..7e1a1998b341 100644 Binary files a/media/sqlgram/LikeOrNotOp.png and b/media/sqlgram/LikeOrNotOp.png differ diff --git a/media/sqlgram/LikeTableWithOrWithoutParen.png b/media/sqlgram/LikeTableWithOrWithoutParen.png index 0d83ef47bf74..39323e876a7e 100644 Binary files a/media/sqlgram/LikeTableWithOrWithoutParen.png and b/media/sqlgram/LikeTableWithOrWithoutParen.png differ diff --git a/media/sqlgram/LimitClause.png b/media/sqlgram/LimitClause.png index 3e4565047f85..1966ad8e3ef4 100644 Binary files a/media/sqlgram/LimitClause.png and b/media/sqlgram/LimitClause.png differ diff --git a/media/sqlgram/LimitOption.png b/media/sqlgram/LimitOption.png index 7ed6c8e173e7..5acb2454af3e 100644 Binary files a/media/sqlgram/LimitOption.png and b/media/sqlgram/LimitOption.png differ diff --git a/media/sqlgram/LinearOpt.png b/media/sqlgram/LinearOpt.png new file mode 100644 index 000000000000..6442f3c70633 Binary files /dev/null and b/media/sqlgram/LinearOpt.png differ diff --git a/media/sqlgram/Lines.png b/media/sqlgram/Lines.png index 5cd146534e24..842ff00635a8 100644 Binary files a/media/sqlgram/Lines.png and b/media/sqlgram/Lines.png differ diff --git a/media/sqlgram/LinesTerminated.png b/media/sqlgram/LinesTerminated.png index 4638d4ea9aa9..80a009d97b9f 100644 Binary files a/media/sqlgram/LinesTerminated.png and b/media/sqlgram/LinesTerminated.png differ diff --git a/media/sqlgram/Literal.png b/media/sqlgram/Literal.png index 635c84b6d1e4..877239e14b06 100644 Binary files a/media/sqlgram/Literal.png and b/media/sqlgram/Literal.png differ diff --git a/media/sqlgram/LoadDataSetItem.png b/media/sqlgram/LoadDataSetItem.png new file mode 100644 index 000000000000..55f368989df5 Binary files /dev/null and b/media/sqlgram/LoadDataSetItem.png differ diff --git a/media/sqlgram/LoadDataSetSpecOpt.png b/media/sqlgram/LoadDataSetSpecOpt.png new file mode 100644 index 000000000000..c7ae1043a101 Binary files /dev/null and b/media/sqlgram/LoadDataSetSpecOpt.png differ diff --git a/media/sqlgram/LoadDataStmt.png b/media/sqlgram/LoadDataStmt.png index 054dd1d59178..5c61fc9d168e 100644 Binary files a/media/sqlgram/LoadDataStmt.png and b/media/sqlgram/LoadDataStmt.png differ diff --git a/media/sqlgram/LoadStatsStmt.png b/media/sqlgram/LoadStatsStmt.png new file mode 100644 index 000000000000..ba86fba3e143 Binary files /dev/null and b/media/sqlgram/LoadStatsStmt.png differ diff --git a/media/sqlgram/LocalOpt.png b/media/sqlgram/LocalOpt.png index 2f03ab2c3369..173ff2eb6a08 100644 Binary files a/media/sqlgram/LocalOpt.png and b/media/sqlgram/LocalOpt.png differ diff --git a/media/sqlgram/LocationLabelList.png b/media/sqlgram/LocationLabelList.png new file mode 100644 index 000000000000..3070fb153365 Binary files /dev/null and b/media/sqlgram/LocationLabelList.png differ diff --git a/media/sqlgram/LockClause.png b/media/sqlgram/LockClause.png new file mode 100644 index 000000000000..500e827cd260 Binary files /dev/null and b/media/sqlgram/LockClause.png differ diff --git a/media/sqlgram/LockTablesStmt.png b/media/sqlgram/LockTablesStmt.png index d25b3d30f13f..4b423da1c9da 100644 Binary files a/media/sqlgram/LockTablesStmt.png and b/media/sqlgram/LockTablesStmt.png differ diff --git a/media/sqlgram/LockType.png b/media/sqlgram/LockType.png index 5153b805240c..6f6fe4bc5c4d 100644 Binary files a/media/sqlgram/LockType.png and b/media/sqlgram/LockType.png differ diff --git a/media/sqlgram/LogTypeOpt.png b/media/sqlgram/LogTypeOpt.png new file mode 100644 index 000000000000..dc7a8454f83d Binary files /dev/null and b/media/sqlgram/LogTypeOpt.png differ diff --git a/media/sqlgram/Match.png b/media/sqlgram/Match.png new file mode 100644 index 000000000000..d8c0886fe6bb Binary files /dev/null and b/media/sqlgram/Match.png differ diff --git a/media/sqlgram/MatchOpt.png b/media/sqlgram/MatchOpt.png new file mode 100644 index 000000000000..45c7e17d212d Binary files /dev/null and b/media/sqlgram/MatchOpt.png differ diff --git a/media/sqlgram/MaxIndexNumOpt.png b/media/sqlgram/MaxIndexNumOpt.png new file mode 100644 index 000000000000..9ab28c20d542 Binary files /dev/null and b/media/sqlgram/MaxIndexNumOpt.png differ diff --git a/media/sqlgram/MaxMinutesOpt.png b/media/sqlgram/MaxMinutesOpt.png new file mode 100644 index 000000000000..cfd03c61f662 Binary files /dev/null and b/media/sqlgram/MaxMinutesOpt.png differ diff --git a/media/sqlgram/MaxValueOrExpression.png b/media/sqlgram/MaxValueOrExpression.png index ffa4c231db67..d4c1b0cbbc40 100644 Binary files a/media/sqlgram/MaxValueOrExpression.png and b/media/sqlgram/MaxValueOrExpression.png differ diff --git a/media/sqlgram/MaxValueOrExpressionList.png b/media/sqlgram/MaxValueOrExpressionList.png new file mode 100644 index 000000000000..191b436ea00f Binary files /dev/null and b/media/sqlgram/MaxValueOrExpressionList.png differ diff --git a/media/sqlgram/NChar.png b/media/sqlgram/NChar.png new file mode 100644 index 000000000000..f6d34452509f Binary files /dev/null and b/media/sqlgram/NChar.png differ diff --git a/media/sqlgram/NUM.png b/media/sqlgram/NUM.png new file mode 100755 index 000000000000..2496532b415c Binary files /dev/null and b/media/sqlgram/NUM.png differ diff --git a/media/sqlgram/NVarchar.png b/media/sqlgram/NVarchar.png new file mode 100644 index 000000000000..cd02a08ce8c3 Binary files /dev/null and b/media/sqlgram/NVarchar.png differ diff --git a/media/sqlgram/NextValueForSequence.png b/media/sqlgram/NextValueForSequence.png new file mode 100644 index 000000000000..aec2d223d980 Binary files /dev/null and b/media/sqlgram/NextValueForSequence.png differ diff --git a/media/sqlgram/NoWriteToBinLogAliasOpt.png b/media/sqlgram/NoWriteToBinLogAliasOpt.png index 3ca9bbf42f9b..f073ffbbaff9 100644 Binary files a/media/sqlgram/NoWriteToBinLogAliasOpt.png and b/media/sqlgram/NoWriteToBinLogAliasOpt.png differ diff --git a/media/sqlgram/NotKeywordToken.png b/media/sqlgram/NotKeywordToken.png index c02b1a02cca4..896aa75f2d77 100644 Binary files a/media/sqlgram/NotKeywordToken.png and b/media/sqlgram/NotKeywordToken.png differ diff --git a/media/sqlgram/NowSym.png b/media/sqlgram/NowSym.png index ed66d7cdf36a..2bcf0b2b9703 100644 Binary files a/media/sqlgram/NowSym.png and b/media/sqlgram/NowSym.png differ diff --git a/media/sqlgram/NowSymFunc.png b/media/sqlgram/NowSymFunc.png index ed66d7cdf36a..c93a02da918f 100644 Binary files a/media/sqlgram/NowSymFunc.png and b/media/sqlgram/NowSymFunc.png differ diff --git a/media/sqlgram/NowSymOptionFraction.png b/media/sqlgram/NowSymOptionFraction.png index 1a158a099db9..07146b034eb0 100644 Binary files a/media/sqlgram/NowSymOptionFraction.png and b/media/sqlgram/NowSymOptionFraction.png differ diff --git a/media/sqlgram/NumList.png b/media/sqlgram/NumList.png index 11683d4a64ff..dcfdcd438b5b 100644 Binary files a/media/sqlgram/NumList.png and b/media/sqlgram/NumList.png differ diff --git a/media/sqlgram/NumLiteral.png b/media/sqlgram/NumLiteral.png index 8701d3550ce5..bc27b7cd0ab9 100644 Binary files a/media/sqlgram/NumLiteral.png and b/media/sqlgram/NumLiteral.png differ diff --git a/media/sqlgram/NumericType.png b/media/sqlgram/NumericType.png index 67e1eb910b26..e00455fb0040 100644 Binary files a/media/sqlgram/NumericType.png and b/media/sqlgram/NumericType.png differ diff --git a/media/sqlgram/ODBCDateTimeType.png b/media/sqlgram/ODBCDateTimeType.png new file mode 100644 index 000000000000..db0a2aeabfc2 Binary files /dev/null and b/media/sqlgram/ODBCDateTimeType.png differ diff --git a/media/sqlgram/ObjectType.png b/media/sqlgram/ObjectType.png index 40ed08c122c3..e342925a738a 100644 Binary files a/media/sqlgram/ObjectType.png and b/media/sqlgram/ObjectType.png differ diff --git a/media/sqlgram/OnDelete.png b/media/sqlgram/OnDelete.png new file mode 100644 index 000000000000..f8e5d45cfad5 Binary files /dev/null and b/media/sqlgram/OnDelete.png differ diff --git a/media/sqlgram/OnDeleteUpdateOpt.png b/media/sqlgram/OnDeleteUpdateOpt.png new file mode 100644 index 000000000000..cea83e5d31ef Binary files /dev/null and b/media/sqlgram/OnDeleteUpdateOpt.png differ diff --git a/media/sqlgram/OnDuplicateKeyUpdate.png b/media/sqlgram/OnDuplicateKeyUpdate.png index 4638d4ea9aa9..3a27c028fa58 100644 Binary files a/media/sqlgram/OnDuplicateKeyUpdate.png and b/media/sqlgram/OnDuplicateKeyUpdate.png differ diff --git a/media/sqlgram/OnUpdate.png b/media/sqlgram/OnUpdate.png new file mode 100644 index 000000000000..7921a5d1e3ff Binary files /dev/null and b/media/sqlgram/OnUpdate.png differ diff --git a/media/sqlgram/OptBinMod.png b/media/sqlgram/OptBinMod.png index dae2787e80ca..9d63907aaaa2 100644 Binary files a/media/sqlgram/OptBinMod.png and b/media/sqlgram/OptBinMod.png differ diff --git a/media/sqlgram/OptBinary.png b/media/sqlgram/OptBinary.png index 569c9b06fa0a..d7d007687440 100644 Binary files a/media/sqlgram/OptBinary.png and b/media/sqlgram/OptBinary.png differ diff --git a/media/sqlgram/OptCharset.png b/media/sqlgram/OptCharset.png index 60a5010c42e4..d2779c5ab5fb 100644 Binary files a/media/sqlgram/OptCharset.png and b/media/sqlgram/OptCharset.png differ diff --git a/media/sqlgram/OptCharsetWithOptBinary.png b/media/sqlgram/OptCharsetWithOptBinary.png new file mode 100644 index 000000000000..c0b086ff2787 Binary files /dev/null and b/media/sqlgram/OptCharsetWithOptBinary.png differ diff --git a/media/sqlgram/OptCollate.png b/media/sqlgram/OptCollate.png index 59b11f22c8d5..e0761f5bfc64 100644 Binary files a/media/sqlgram/OptCollate.png and b/media/sqlgram/OptCollate.png differ diff --git a/media/sqlgram/OptExistingWindowName.png b/media/sqlgram/OptExistingWindowName.png index bc1605065d94..f6a8b78e7448 100644 Binary files a/media/sqlgram/OptExistingWindowName.png and b/media/sqlgram/OptExistingWindowName.png differ diff --git a/media/sqlgram/OptFieldLen.png b/media/sqlgram/OptFieldLen.png index b76d252df13d..211b2aeed0b3 100644 Binary files a/media/sqlgram/OptFieldLen.png and b/media/sqlgram/OptFieldLen.png differ diff --git a/media/sqlgram/OptFromFirstLast.png b/media/sqlgram/OptFromFirstLast.png index efe2860885c4..40c610f6d4c7 100644 Binary files a/media/sqlgram/OptFromFirstLast.png and b/media/sqlgram/OptFromFirstLast.png differ diff --git a/media/sqlgram/OptFull.png b/media/sqlgram/OptFull.png index 96cbdfcdbd0c..d97f1913a25e 100644 Binary files a/media/sqlgram/OptFull.png and b/media/sqlgram/OptFull.png differ diff --git a/media/sqlgram/OptGConcatSeparator.png b/media/sqlgram/OptGConcatSeparator.png index 4638d4ea9aa9..413ef7f4efc2 100644 Binary files a/media/sqlgram/OptGConcatSeparator.png and b/media/sqlgram/OptGConcatSeparator.png differ diff --git a/media/sqlgram/OptInteger.png b/media/sqlgram/OptInteger.png index 2d7b0842b864..5cfccec34df5 100644 Binary files a/media/sqlgram/OptInteger.png and b/media/sqlgram/OptInteger.png differ diff --git a/media/sqlgram/OptLLDefault.png b/media/sqlgram/OptLLDefault.png index 8c550299f369..8ed16e5cb535 100644 Binary files a/media/sqlgram/OptLLDefault.png and b/media/sqlgram/OptLLDefault.png differ diff --git a/media/sqlgram/OptLeadLagInfo.png b/media/sqlgram/OptLeadLagInfo.png index 4638d4ea9aa9..020082a4d384 100644 Binary files a/media/sqlgram/OptLeadLagInfo.png and b/media/sqlgram/OptLeadLagInfo.png differ diff --git a/media/sqlgram/OptNullTreatment.png b/media/sqlgram/OptNullTreatment.png index a74a754524a7..8e827d56fc14 100644 Binary files a/media/sqlgram/OptNullTreatment.png and b/media/sqlgram/OptNullTreatment.png differ diff --git a/media/sqlgram/OptPartitionClause.png b/media/sqlgram/OptPartitionClause.png index 0ac1b3641d5b..124f30606976 100644 Binary files a/media/sqlgram/OptPartitionClause.png and b/media/sqlgram/OptPartitionClause.png differ diff --git a/media/sqlgram/OptTable.png b/media/sqlgram/OptTable.png index 40ed08c122c3..e342925a738a 100644 Binary files a/media/sqlgram/OptTable.png and b/media/sqlgram/OptTable.png differ diff --git a/media/sqlgram/OptTemporary.png b/media/sqlgram/OptTemporary.png old mode 100755 new mode 100644 index 6f786ec4e80e..f08d152fd278 Binary files a/media/sqlgram/OptTemporary.png and b/media/sqlgram/OptTemporary.png differ diff --git a/media/sqlgram/OptWild.png b/media/sqlgram/OptWild.png new file mode 100644 index 000000000000..22545b30b6c5 Binary files /dev/null and b/media/sqlgram/OptWild.png differ diff --git a/media/sqlgram/OptWindowFrameClause.png b/media/sqlgram/OptWindowFrameClause.png index 6f6416a973ac..b596266c26c0 100644 Binary files a/media/sqlgram/OptWindowFrameClause.png and b/media/sqlgram/OptWindowFrameClause.png differ diff --git a/media/sqlgram/OptWindowOrderByClause.png b/media/sqlgram/OptWindowOrderByClause.png index 65ab9b054da6..12579ba52b84 100644 Binary files a/media/sqlgram/OptWindowOrderByClause.png and b/media/sqlgram/OptWindowOrderByClause.png differ diff --git a/media/sqlgram/OptWindowingClause.png b/media/sqlgram/OptWindowingClause.png index 36353dd3dfc1..338e988b3b65 100644 Binary files a/media/sqlgram/OptWindowingClause.png and b/media/sqlgram/OptWindowingClause.png differ diff --git a/media/sqlgram/OptionalBraces.png b/media/sqlgram/OptionalBraces.png index fa5dda98229c..7b84bafe403f 100644 Binary files a/media/sqlgram/OptionalBraces.png and b/media/sqlgram/OptionalBraces.png differ diff --git a/media/sqlgram/OrReplace.png b/media/sqlgram/OrReplace.png index e94a3e140826..597bdfa90539 100644 Binary files a/media/sqlgram/OrReplace.png and b/media/sqlgram/OrReplace.png differ diff --git a/media/sqlgram/Order.png b/media/sqlgram/Order.png index 565693918265..a25da473bcc8 100644 Binary files a/media/sqlgram/Order.png and b/media/sqlgram/Order.png differ diff --git a/media/sqlgram/OrderBy.png b/media/sqlgram/OrderBy.png index 16f654b1335d..dac243dcb7a6 100644 Binary files a/media/sqlgram/OrderBy.png and b/media/sqlgram/OrderBy.png differ diff --git a/media/sqlgram/OrderByOptional.png b/media/sqlgram/OrderByOptional.png index c6f443b352dd..d634a6f4c0b5 100644 Binary files a/media/sqlgram/OrderByOptional.png and b/media/sqlgram/OrderByOptional.png differ diff --git a/media/sqlgram/OuterOpt.png b/media/sqlgram/OuterOpt.png index bbe107766c84..162f9232793e 100644 Binary files a/media/sqlgram/OuterOpt.png and b/media/sqlgram/OuterOpt.png differ diff --git a/media/sqlgram/PartDefOption.png b/media/sqlgram/PartDefOption.png index 131fda09bd09..cef53717ba19 100644 Binary files a/media/sqlgram/PartDefOption.png and b/media/sqlgram/PartDefOption.png differ diff --git a/media/sqlgram/PartDefOptionList.png b/media/sqlgram/PartDefOptionList.png new file mode 100644 index 000000000000..243825fb08c6 Binary files /dev/null and b/media/sqlgram/PartDefOptionList.png differ diff --git a/media/sqlgram/PartDefValuesOpt.png b/media/sqlgram/PartDefValuesOpt.png index 4c8ba3db15dc..4d8f05db8919 100644 Binary files a/media/sqlgram/PartDefValuesOpt.png and b/media/sqlgram/PartDefValuesOpt.png differ diff --git a/media/sqlgram/PartitionDefinition.png b/media/sqlgram/PartitionDefinition.png index 90a33057ca41..7926dfcefab8 100644 Binary files a/media/sqlgram/PartitionDefinition.png and b/media/sqlgram/PartitionDefinition.png differ diff --git a/media/sqlgram/PartitionDefinitionList.png b/media/sqlgram/PartitionDefinitionList.png new file mode 100644 index 000000000000..753419cd7459 Binary files /dev/null and b/media/sqlgram/PartitionDefinitionList.png differ diff --git a/media/sqlgram/PartitionDefinitionListOpt.png b/media/sqlgram/PartitionDefinitionListOpt.png index 810edd937ab2..cb8e7e3f5245 100644 Binary files a/media/sqlgram/PartitionDefinitionListOpt.png and b/media/sqlgram/PartitionDefinitionListOpt.png differ diff --git a/media/sqlgram/PartitionKeyAlgorithmOpt.png b/media/sqlgram/PartitionKeyAlgorithmOpt.png new file mode 100644 index 000000000000..0e77d31fe5f3 Binary files /dev/null and b/media/sqlgram/PartitionKeyAlgorithmOpt.png differ diff --git a/media/sqlgram/PartitionMethod.png b/media/sqlgram/PartitionMethod.png new file mode 100644 index 000000000000..f6c44aefd3a0 Binary files /dev/null and b/media/sqlgram/PartitionMethod.png differ diff --git a/media/sqlgram/PartitionNameList.png b/media/sqlgram/PartitionNameList.png index 4158610f7881..cc7cff80701a 100644 Binary files a/media/sqlgram/PartitionNameList.png and b/media/sqlgram/PartitionNameList.png differ diff --git a/media/sqlgram/PartitionNameListOpt.png b/media/sqlgram/PartitionNameListOpt.png old mode 100644 new mode 100755 index 162e9c6ad613..0ff961cd4edc Binary files a/media/sqlgram/PartitionNameListOpt.png and b/media/sqlgram/PartitionNameListOpt.png differ diff --git a/media/sqlgram/PartitionNumOpt.png b/media/sqlgram/PartitionNumOpt.png index 8c45351e819a..5f77a56b9cbd 100644 Binary files a/media/sqlgram/PartitionNumOpt.png and b/media/sqlgram/PartitionNumOpt.png differ diff --git a/media/sqlgram/PartitionOpt.png b/media/sqlgram/PartitionOpt.png index b11a0334f52e..c650cfabac8f 100644 Binary files a/media/sqlgram/PartitionOpt.png and b/media/sqlgram/PartitionOpt.png differ diff --git a/media/sqlgram/PasswordExpire.png b/media/sqlgram/PasswordExpire.png new file mode 100644 index 000000000000..ac7cdb2b906c Binary files /dev/null and b/media/sqlgram/PasswordExpire.png differ diff --git a/media/sqlgram/PasswordOpt.png b/media/sqlgram/PasswordOpt.png index 1e5159671341..bd1ac838ddf4 100644 Binary files a/media/sqlgram/PasswordOpt.png and b/media/sqlgram/PasswordOpt.png differ diff --git a/media/sqlgram/PasswordOrLockOption.png b/media/sqlgram/PasswordOrLockOption.png new file mode 100644 index 000000000000..efaf324e1b63 Binary files /dev/null and b/media/sqlgram/PasswordOrLockOption.png differ diff --git a/media/sqlgram/PasswordOrLockOptions.png b/media/sqlgram/PasswordOrLockOptions.png new file mode 100644 index 000000000000..518f4c4f3c03 Binary files /dev/null and b/media/sqlgram/PasswordOrLockOptions.png differ diff --git a/media/sqlgram/PerDB.png b/media/sqlgram/PerDB.png new file mode 100644 index 000000000000..ed3628f0c9de Binary files /dev/null and b/media/sqlgram/PerDB.png differ diff --git a/media/sqlgram/PerTable.png b/media/sqlgram/PerTable.png new file mode 100644 index 000000000000..5d177ff95394 Binary files /dev/null and b/media/sqlgram/PerTable.png differ diff --git a/media/sqlgram/PluginNameList.png b/media/sqlgram/PluginNameList.png new file mode 100644 index 000000000000..cc7cff80701a Binary files /dev/null and b/media/sqlgram/PluginNameList.png differ diff --git a/media/sqlgram/Precision.png b/media/sqlgram/Precision.png index 1246640a3730..aec950ef3bd4 100644 Binary files a/media/sqlgram/Precision.png and b/media/sqlgram/Precision.png differ diff --git a/media/sqlgram/PredicateExpr.png b/media/sqlgram/PredicateExpr.png index 1197c60a1a1b..a058875e8682 100644 Binary files a/media/sqlgram/PredicateExpr.png and b/media/sqlgram/PredicateExpr.png differ diff --git a/media/sqlgram/PrepareSQL.png b/media/sqlgram/PrepareSQL.png index c64f10fd95b7..adff8a5c625f 100644 Binary files a/media/sqlgram/PrepareSQL.png and b/media/sqlgram/PrepareSQL.png differ diff --git a/media/sqlgram/PreparedStmt.png b/media/sqlgram/PreparedStmt.png index 0eaad0903967..cdbf8d004d93 100644 Binary files a/media/sqlgram/PreparedStmt.png and b/media/sqlgram/PreparedStmt.png differ diff --git a/media/sqlgram/PrimaryOpt.png b/media/sqlgram/PrimaryOpt.png index 052a40a4eb57..418098ea9ab1 100644 Binary files a/media/sqlgram/PrimaryOpt.png and b/media/sqlgram/PrimaryOpt.png differ diff --git a/media/sqlgram/PriorityOpt.png b/media/sqlgram/PriorityOpt.png index 4aed507b07b0..19d1a243fc49 100644 Binary files a/media/sqlgram/PriorityOpt.png and b/media/sqlgram/PriorityOpt.png differ diff --git a/media/sqlgram/PrivElem.png b/media/sqlgram/PrivElem.png index 2fa90c4104f4..09483f799c60 100644 Binary files a/media/sqlgram/PrivElem.png and b/media/sqlgram/PrivElem.png differ diff --git a/media/sqlgram/PrivElemList.png b/media/sqlgram/PrivElemList.png index a993d4a9d4c8..ad4ebefe19b5 100644 Binary files a/media/sqlgram/PrivElemList.png and b/media/sqlgram/PrivElemList.png differ diff --git a/media/sqlgram/PrivLevel.png b/media/sqlgram/PrivLevel.png index 9e9d136d3e9f..0cf78a85f078 100644 Binary files a/media/sqlgram/PrivLevel.png and b/media/sqlgram/PrivLevel.png differ diff --git a/media/sqlgram/PrivType.png b/media/sqlgram/PrivType.png index 19e1b7236737..d789b12c9cc3 100644 Binary files a/media/sqlgram/PrivType.png and b/media/sqlgram/PrivType.png differ diff --git a/media/sqlgram/QuickOptional.png b/media/sqlgram/QuickOptional.png index 4bc77e2bb450..d2293bd4b49a 100644 Binary files a/media/sqlgram/QuickOptional.png and b/media/sqlgram/QuickOptional.png differ diff --git a/media/sqlgram/rr-1.59.1797.png b/media/sqlgram/Railroad-Diagram-Generator.png similarity index 100% rename from media/sqlgram/rr-1.59.1797.png rename to media/sqlgram/Railroad-Diagram-Generator.png diff --git a/media/sqlgram/RecoverTableStmt.png b/media/sqlgram/RecoverTableStmt.png new file mode 100755 index 000000000000..6ce2ce7b4c14 Binary files /dev/null and b/media/sqlgram/RecoverTableStmt.png differ diff --git a/media/sqlgram/ReferDef.png b/media/sqlgram/ReferDef.png index 3cb6b1da5f80..e89bbcc62f61 100644 Binary files a/media/sqlgram/ReferDef.png and b/media/sqlgram/ReferDef.png differ diff --git a/media/sqlgram/ReferOpt.png b/media/sqlgram/ReferOpt.png index 6313e12426dc..b12b4019f330 100644 Binary files a/media/sqlgram/ReferOpt.png and b/media/sqlgram/ReferOpt.png differ diff --git a/media/sqlgram/RegexpOrNotOp.png b/media/sqlgram/RegexpOrNotOp.png index 51e1fcaa8b1e..d458da045ae0 100644 Binary files a/media/sqlgram/RegexpOrNotOp.png and b/media/sqlgram/RegexpOrNotOp.png differ diff --git a/media/sqlgram/RegexpSym.png b/media/sqlgram/RegexpSym.png index f03feabd0d14..ef668f11fb9c 100644 Binary files a/media/sqlgram/RegexpSym.png and b/media/sqlgram/RegexpSym.png differ diff --git a/media/sqlgram/RenameTableStmt.png b/media/sqlgram/RenameTableStmt.png old mode 100644 new mode 100755 index d4e6574fe6ee..e0f463e09ad2 Binary files a/media/sqlgram/RenameTableStmt.png and b/media/sqlgram/RenameTableStmt.png differ diff --git a/media/sqlgram/ReorganizePartitionRuleOpt.png b/media/sqlgram/ReorganizePartitionRuleOpt.png new file mode 100644 index 000000000000..9edad09bbf5d Binary files /dev/null and b/media/sqlgram/ReorganizePartitionRuleOpt.png differ diff --git a/media/sqlgram/ReplaceIntoStmt.png b/media/sqlgram/ReplaceIntoStmt.png index 4d9622921026..8717b1d6714e 100644 Binary files a/media/sqlgram/ReplaceIntoStmt.png and b/media/sqlgram/ReplaceIntoStmt.png differ diff --git a/media/sqlgram/RequireClause.png b/media/sqlgram/RequireClause.png new file mode 100644 index 000000000000..8c3eabafd614 Binary files /dev/null and b/media/sqlgram/RequireClause.png differ diff --git a/media/sqlgram/RequireClauseOpt.png b/media/sqlgram/RequireClauseOpt.png new file mode 100644 index 000000000000..243c2d1a0c9a Binary files /dev/null and b/media/sqlgram/RequireClauseOpt.png differ diff --git a/media/sqlgram/RequireListElement.png b/media/sqlgram/RequireListElement.png new file mode 100644 index 000000000000..0e12be0be63d Binary files /dev/null and b/media/sqlgram/RequireListElement.png differ diff --git a/media/sqlgram/RestrictOrCascadeOpt.png b/media/sqlgram/RestrictOrCascadeOpt.png index 198ab814341b..a077a2395bb5 100644 Binary files a/media/sqlgram/RestrictOrCascadeOpt.png and b/media/sqlgram/RestrictOrCascadeOpt.png differ diff --git a/media/sqlgram/RevokeRoleStmt.png b/media/sqlgram/RevokeRoleStmt.png new file mode 100644 index 000000000000..e9c0b6b6e70e Binary files /dev/null and b/media/sqlgram/RevokeRoleStmt.png differ diff --git a/media/sqlgram/RevokeStmt.png b/media/sqlgram/RevokeStmt.png index 0469da480559..505a960c096f 100644 Binary files a/media/sqlgram/RevokeStmt.png and b/media/sqlgram/RevokeStmt.png differ diff --git a/media/sqlgram/RoleNameString.png b/media/sqlgram/RoleNameString.png new file mode 100644 index 000000000000..f3e4356433af Binary files /dev/null and b/media/sqlgram/RoleNameString.png differ diff --git a/media/sqlgram/RoleSpec.png b/media/sqlgram/RoleSpec.png new file mode 100644 index 000000000000..222e142f9809 Binary files /dev/null and b/media/sqlgram/RoleSpec.png differ diff --git a/media/sqlgram/Rolename.png b/media/sqlgram/Rolename.png new file mode 100755 index 000000000000..787c153370b2 Binary files /dev/null and b/media/sqlgram/Rolename.png differ diff --git a/media/sqlgram/RolenameList.png b/media/sqlgram/RolenameList.png new file mode 100755 index 000000000000..7c1e351293bb Binary files /dev/null and b/media/sqlgram/RolenameList.png differ diff --git a/media/sqlgram/RollbackStmt.png b/media/sqlgram/RollbackStmt.png index 483728f4578b..72bb4e483d09 100644 Binary files a/media/sqlgram/RollbackStmt.png and b/media/sqlgram/RollbackStmt.png differ diff --git a/media/sqlgram/RowFormat.png b/media/sqlgram/RowFormat.png index b067d9d0d3d5..533ce3eb982c 100644 Binary files a/media/sqlgram/RowFormat.png and b/media/sqlgram/RowFormat.png differ diff --git a/media/sqlgram/RowValue.png b/media/sqlgram/RowValue.png old mode 100644 new mode 100755 index 3e518c267232..86320061c6e0 Binary files a/media/sqlgram/RowValue.png and b/media/sqlgram/RowValue.png differ diff --git a/media/sqlgram/SHOW_STATS_BUCKETS.png b/media/sqlgram/SHOW_STATS_BUCKETS.png new file mode 100644 index 000000000000..5f1c1aa6458b Binary files /dev/null and b/media/sqlgram/SHOW_STATS_BUCKETS.png differ diff --git a/media/sqlgram/SelectLockOpt.png b/media/sqlgram/SelectLockOpt.png index c30f8da20a86..c36ae018a053 100644 Binary files a/media/sqlgram/SelectLockOpt.png and b/media/sqlgram/SelectLockOpt.png differ diff --git a/media/sqlgram/SelectStmt.png b/media/sqlgram/SelectStmt.png index aa2ba75cbb14..0abf236d324e 100644 Binary files a/media/sqlgram/SelectStmt.png and b/media/sqlgram/SelectStmt.png differ diff --git a/media/sqlgram/SelectStmtBasic.png b/media/sqlgram/SelectStmtBasic.png index b0782df4e015..f00ca58fada1 100644 Binary files a/media/sqlgram/SelectStmtBasic.png and b/media/sqlgram/SelectStmtBasic.png differ diff --git a/media/sqlgram/SelectStmtCalcFoundRows.png b/media/sqlgram/SelectStmtCalcFoundRows.png index 9f235608db3b..952263db5fc1 100644 Binary files a/media/sqlgram/SelectStmtCalcFoundRows.png and b/media/sqlgram/SelectStmtCalcFoundRows.png differ diff --git a/media/sqlgram/SelectStmtFieldList.png b/media/sqlgram/SelectStmtFieldList.png index 6b2301c1b6af..177608e499c7 100644 Binary files a/media/sqlgram/SelectStmtFieldList.png and b/media/sqlgram/SelectStmtFieldList.png differ diff --git a/media/sqlgram/SelectStmtFromDualTable.png b/media/sqlgram/SelectStmtFromDualTable.png index f75e7ed7becd..8cd0a4fee85f 100644 Binary files a/media/sqlgram/SelectStmtFromDualTable.png and b/media/sqlgram/SelectStmtFromDualTable.png differ diff --git a/media/sqlgram/SelectStmtFromTable.png b/media/sqlgram/SelectStmtFromTable.png index afed289767ea..0ad2c7fe8792 100644 Binary files a/media/sqlgram/SelectStmtFromTable.png and b/media/sqlgram/SelectStmtFromTable.png differ diff --git a/media/sqlgram/SelectStmtGroup.png b/media/sqlgram/SelectStmtGroup.png index 680afe583c5c..73731a4b5221 100644 Binary files a/media/sqlgram/SelectStmtGroup.png and b/media/sqlgram/SelectStmtGroup.png differ diff --git a/media/sqlgram/SelectStmtIntoOption.png b/media/sqlgram/SelectStmtIntoOption.png new file mode 100644 index 000000000000..992255e5a60c Binary files /dev/null and b/media/sqlgram/SelectStmtIntoOption.png differ diff --git a/media/sqlgram/SelectStmtLimit.png b/media/sqlgram/SelectStmtLimit.png index f537cf150aad..86cdc43b4082 100644 Binary files a/media/sqlgram/SelectStmtLimit.png and b/media/sqlgram/SelectStmtLimit.png differ diff --git a/media/sqlgram/SelectStmtOpts.png b/media/sqlgram/SelectStmtOpts.png index d439e0e8f16c..ed02d3343bec 100644 Binary files a/media/sqlgram/SelectStmtOpts.png and b/media/sqlgram/SelectStmtOpts.png differ diff --git a/media/sqlgram/SelectStmtSQLBigResult.png b/media/sqlgram/SelectStmtSQLBigResult.png new file mode 100644 index 000000000000..dec95901b23f Binary files /dev/null and b/media/sqlgram/SelectStmtSQLBigResult.png differ diff --git a/media/sqlgram/SelectStmtSQLBufferResult.png b/media/sqlgram/SelectStmtSQLBufferResult.png new file mode 100644 index 000000000000..e027b2ab529e Binary files /dev/null and b/media/sqlgram/SelectStmtSQLBufferResult.png differ diff --git a/media/sqlgram/SelectStmtSQLCache.png b/media/sqlgram/SelectStmtSQLCache.png index b153aa161512..f661760c2eff 100644 Binary files a/media/sqlgram/SelectStmtSQLCache.png and b/media/sqlgram/SelectStmtSQLCache.png differ diff --git a/media/sqlgram/SelectStmtSQLSmallResult.png b/media/sqlgram/SelectStmtSQLSmallResult.png new file mode 100644 index 000000000000..d58733abc1fe Binary files /dev/null and b/media/sqlgram/SelectStmtSQLSmallResult.png differ diff --git a/media/sqlgram/SelectStmtStraightJoin.png b/media/sqlgram/SelectStmtStraightJoin.png index bc74163896ca..b1c60f88c2a5 100644 Binary files a/media/sqlgram/SelectStmtStraightJoin.png and b/media/sqlgram/SelectStmtStraightJoin.png differ diff --git a/media/sqlgram/SequenceOption.png b/media/sqlgram/SequenceOption.png old mode 100755 new mode 100644 index fac6cb71044d..ee02aff3f189 Binary files a/media/sqlgram/SequenceOption.png and b/media/sqlgram/SequenceOption.png differ diff --git a/media/sqlgram/SequenceOptionList.png b/media/sqlgram/SequenceOptionList.png new file mode 100644 index 000000000000..8fcb6722f5e0 Binary files /dev/null and b/media/sqlgram/SequenceOptionList.png differ diff --git a/media/sqlgram/SetDefaultRoleOpt.png b/media/sqlgram/SetDefaultRoleOpt.png new file mode 100644 index 000000000000..02cb81cb85de Binary files /dev/null and b/media/sqlgram/SetDefaultRoleOpt.png differ diff --git a/media/sqlgram/SetDefaultRoleStmt.png b/media/sqlgram/SetDefaultRoleStmt.png new file mode 100644 index 000000000000..b67a272eb386 Binary files /dev/null and b/media/sqlgram/SetDefaultRoleStmt.png differ diff --git a/media/sqlgram/SetExpr.png b/media/sqlgram/SetExpr.png index b35de99c236d..bf7e71cf96e8 100644 Binary files a/media/sqlgram/SetExpr.png and b/media/sqlgram/SetExpr.png differ diff --git a/media/sqlgram/SetNamesStmt.png b/media/sqlgram/SetNamesStmt.png new file mode 100644 index 000000000000..381e0ea7cbad Binary files /dev/null and b/media/sqlgram/SetNamesStmt.png differ diff --git a/media/sqlgram/SetRoleOpt.png b/media/sqlgram/SetRoleOpt.png new file mode 100644 index 000000000000..96fd1e018e27 Binary files /dev/null and b/media/sqlgram/SetRoleOpt.png differ diff --git a/media/sqlgram/SetRoleStmt.png b/media/sqlgram/SetRoleStmt.png new file mode 100644 index 000000000000..a2ddc8533858 Binary files /dev/null and b/media/sqlgram/SetRoleStmt.png differ diff --git a/media/sqlgram/SetStmt.png b/media/sqlgram/SetStmt.png index a8c1990dc6e6..017911832ef8 100644 Binary files a/media/sqlgram/SetStmt.png and b/media/sqlgram/SetStmt.png differ diff --git a/media/sqlgram/ShowBuiltinsStmt.png b/media/sqlgram/ShowBuiltinsStmt.png new file mode 100644 index 000000000000..9943067ab349 Binary files /dev/null and b/media/sqlgram/ShowBuiltinsStmt.png differ diff --git a/media/sqlgram/ShowCharsetStmt.png b/media/sqlgram/ShowCharsetStmt.png new file mode 100644 index 000000000000..32efbaba311b Binary files /dev/null and b/media/sqlgram/ShowCharsetStmt.png differ diff --git a/media/sqlgram/ShowCollationStmt.png b/media/sqlgram/ShowCollationStmt.png new file mode 100644 index 000000000000..d62e81acd5f1 Binary files /dev/null and b/media/sqlgram/ShowCollationStmt.png differ diff --git a/media/sqlgram/ShowColumnsFilterable.png b/media/sqlgram/ShowColumnsFilterable.png new file mode 100644 index 000000000000..6bc80f109abd Binary files /dev/null and b/media/sqlgram/ShowColumnsFilterable.png differ diff --git a/media/sqlgram/ShowCreateSequenceStmt.png b/media/sqlgram/ShowCreateSequenceStmt.png new file mode 100644 index 000000000000..6f60823db474 Binary files /dev/null and b/media/sqlgram/ShowCreateSequenceStmt.png differ diff --git a/media/sqlgram/ShowCreateTableStmt.png b/media/sqlgram/ShowCreateTableStmt.png new file mode 100755 index 000000000000..43e47c39334c Binary files /dev/null and b/media/sqlgram/ShowCreateTableStmt.png differ diff --git a/media/sqlgram/ShowCreateUserStmt.png b/media/sqlgram/ShowCreateUserStmt.png new file mode 100755 index 000000000000..12137c20c020 Binary files /dev/null and b/media/sqlgram/ShowCreateUserStmt.png differ diff --git a/media/sqlgram/ShowDatabaseNameOpt.png b/media/sqlgram/ShowDatabaseNameOpt.png index 3526a0c318da..8065db22195f 100644 Binary files a/media/sqlgram/ShowDatabaseNameOpt.png and b/media/sqlgram/ShowDatabaseNameOpt.png differ diff --git a/media/sqlgram/ShowDatabasesStmt.png b/media/sqlgram/ShowDatabasesStmt.png new file mode 100755 index 000000000000..d4f6dceef539 Binary files /dev/null and b/media/sqlgram/ShowDatabasesStmt.png differ diff --git a/media/sqlgram/ShowEnginesStmt.png b/media/sqlgram/ShowEnginesStmt.png new file mode 100644 index 000000000000..8af6f4f12bd6 Binary files /dev/null and b/media/sqlgram/ShowEnginesStmt.png differ diff --git a/media/sqlgram/ShowErrorsStmt.png b/media/sqlgram/ShowErrorsStmt.png new file mode 100644 index 000000000000..70f900033a95 Binary files /dev/null and b/media/sqlgram/ShowErrorsStmt.png differ diff --git a/media/sqlgram/ShowGrantsStmt.png b/media/sqlgram/ShowGrantsStmt.png new file mode 100755 index 000000000000..630955759ccb Binary files /dev/null and b/media/sqlgram/ShowGrantsStmt.png differ diff --git a/media/sqlgram/ShowIndexKwd.png b/media/sqlgram/ShowIndexKwd.png index cbf592f12735..24ff77c3b409 100644 Binary files a/media/sqlgram/ShowIndexKwd.png and b/media/sqlgram/ShowIndexKwd.png differ diff --git a/media/sqlgram/ShowIndexStmt.png b/media/sqlgram/ShowIndexStmt.png new file mode 100755 index 000000000000..0caf829a0cd3 Binary files /dev/null and b/media/sqlgram/ShowIndexStmt.png differ diff --git a/media/sqlgram/ShowLikeOrWhereOpt.png b/media/sqlgram/ShowLikeOrWhereOpt.png index c2e3cd080751..c1ec7efaf56a 100644 Binary files a/media/sqlgram/ShowLikeOrWhereOpt.png and b/media/sqlgram/ShowLikeOrWhereOpt.png differ diff --git a/media/sqlgram/ShowProcesslistStmt.png b/media/sqlgram/ShowProcesslistStmt.png new file mode 100644 index 000000000000..87bd25e3727f Binary files /dev/null and b/media/sqlgram/ShowProcesslistStmt.png differ diff --git a/media/sqlgram/ShowProfileArgsOpt.png b/media/sqlgram/ShowProfileArgsOpt.png new file mode 100644 index 000000000000..1eae547cbfbd Binary files /dev/null and b/media/sqlgram/ShowProfileArgsOpt.png differ diff --git a/media/sqlgram/ShowProfileType.png b/media/sqlgram/ShowProfileType.png new file mode 100644 index 000000000000..6e913ef7c829 Binary files /dev/null and b/media/sqlgram/ShowProfileType.png differ diff --git a/media/sqlgram/ShowProfileTypesOpt.png b/media/sqlgram/ShowProfileTypesOpt.png new file mode 100644 index 000000000000..c1f29c61d9b6 Binary files /dev/null and b/media/sqlgram/ShowProfileTypesOpt.png differ diff --git a/media/sqlgram/ShowStatsHealthy.png b/media/sqlgram/ShowStatsHealthy.png new file mode 100644 index 000000000000..266501a9d592 Binary files /dev/null and b/media/sqlgram/ShowStatsHealthy.png differ diff --git a/media/sqlgram/ShowStmt.png b/media/sqlgram/ShowStmt.png old mode 100755 new mode 100644 index c3acc89c639b..967ec2a42dc1 Binary files a/media/sqlgram/ShowStmt.png and b/media/sqlgram/ShowStmt.png differ diff --git a/media/sqlgram/ShowTableAliasOpt.png b/media/sqlgram/ShowTableAliasOpt.png index 63a13c8a3db1..2e599f1104fd 100644 Binary files a/media/sqlgram/ShowTableAliasOpt.png and b/media/sqlgram/ShowTableAliasOpt.png differ diff --git a/media/sqlgram/ShowTableNextRowIDStmt.png b/media/sqlgram/ShowTableNextRowIDStmt.png new file mode 100644 index 000000000000..d226bb6c1379 Binary files /dev/null and b/media/sqlgram/ShowTableNextRowIDStmt.png differ diff --git a/media/sqlgram/ShowTableRegionStmt.png b/media/sqlgram/ShowTableRegionStmt.png new file mode 100755 index 000000000000..38d7412eb0e2 Binary files /dev/null and b/media/sqlgram/ShowTableRegionStmt.png differ diff --git a/media/sqlgram/ShowTableStatusStmt.png b/media/sqlgram/ShowTableStatusStmt.png new file mode 100644 index 000000000000..c80600ca1f3a Binary files /dev/null and b/media/sqlgram/ShowTableStatusStmt.png differ diff --git a/media/sqlgram/ShowTablesStmt.png b/media/sqlgram/ShowTablesStmt.png new file mode 100755 index 000000000000..6eeb55e724f8 Binary files /dev/null and b/media/sqlgram/ShowTablesStmt.png differ diff --git a/media/sqlgram/ShowTargetFilterable.png b/media/sqlgram/ShowTargetFilterable.png index f8e3ad0cd65d..a46c89dbaa50 100644 Binary files a/media/sqlgram/ShowTargetFilterable.png and b/media/sqlgram/ShowTargetFilterable.png differ diff --git a/media/sqlgram/ShowWarningsStmt.png b/media/sqlgram/ShowWarningsStmt.png new file mode 100644 index 000000000000..6fb9c79daa84 Binary files /dev/null and b/media/sqlgram/ShowWarningsStmt.png differ diff --git a/media/sqlgram/ShutdownStmt.png b/media/sqlgram/ShutdownStmt.png new file mode 100644 index 000000000000..31781abff7e1 Binary files /dev/null and b/media/sqlgram/ShutdownStmt.png differ diff --git a/media/sqlgram/SignedLiteral.png b/media/sqlgram/SignedLiteral.png index e0ffacd7cd69..278e8be2a564 100644 Binary files a/media/sqlgram/SignedLiteral.png and b/media/sqlgram/SignedLiteral.png differ diff --git a/media/sqlgram/SignedNum.png b/media/sqlgram/SignedNum.png new file mode 100644 index 000000000000..d1b8ebb76653 Binary files /dev/null and b/media/sqlgram/SignedNum.png differ diff --git a/media/sqlgram/SimpleExpr.png b/media/sqlgram/SimpleExpr.png index 9fa501a9995c..88650fd397f9 100644 Binary files a/media/sqlgram/SimpleExpr.png and b/media/sqlgram/SimpleExpr.png differ diff --git a/media/sqlgram/SimpleIdent.png b/media/sqlgram/SimpleIdent.png index 31d6a51f29ac..c259addc2949 100644 Binary files a/media/sqlgram/SimpleIdent.png and b/media/sqlgram/SimpleIdent.png differ diff --git a/media/sqlgram/SplitOption.png b/media/sqlgram/SplitOption.png new file mode 100755 index 000000000000..9895bdf3c2eb Binary files /dev/null and b/media/sqlgram/SplitOption.png differ diff --git a/media/sqlgram/SplitRegionStmt.png b/media/sqlgram/SplitRegionStmt.png new file mode 100755 index 000000000000..f7187c3d0ce1 Binary files /dev/null and b/media/sqlgram/SplitRegionStmt.png differ diff --git a/media/sqlgram/SplitSyntaxOption.png b/media/sqlgram/SplitSyntaxOption.png new file mode 100755 index 000000000000..25c111a73d7a Binary files /dev/null and b/media/sqlgram/SplitSyntaxOption.png differ diff --git a/media/sqlgram/Start.png b/media/sqlgram/Start.png index fdf69d377dfa..2ca7c6b6e7ad 100644 Binary files a/media/sqlgram/Start.png and b/media/sqlgram/Start.png differ diff --git a/media/sqlgram/Starting.png b/media/sqlgram/Starting.png index 4638d4ea9aa9..b9996c962e02 100644 Binary files a/media/sqlgram/Starting.png and b/media/sqlgram/Starting.png differ diff --git a/media/sqlgram/Statement.png b/media/sqlgram/Statement.png index 84104ba44d3a..61b4f73e0664 100644 Binary files a/media/sqlgram/Statement.png and b/media/sqlgram/Statement.png differ diff --git a/media/sqlgram/StatsPersistentVal.png b/media/sqlgram/StatsPersistentVal.png index e7fc12e8ebcd..892c30b0e723 100644 Binary files a/media/sqlgram/StatsPersistentVal.png and b/media/sqlgram/StatsPersistentVal.png differ diff --git a/media/sqlgram/StatusTableName.png b/media/sqlgram/StatusTableName.png new file mode 100644 index 000000000000..263fefd9b460 Binary files /dev/null and b/media/sqlgram/StatusTableName.png differ diff --git a/media/sqlgram/StorageMedia.png b/media/sqlgram/StorageMedia.png new file mode 100644 index 000000000000..2dadf6c3a4bb Binary files /dev/null and b/media/sqlgram/StorageMedia.png differ diff --git a/media/sqlgram/StringList.png b/media/sqlgram/StringList.png new file mode 100644 index 000000000000..587b16dce9e6 Binary files /dev/null and b/media/sqlgram/StringList.png differ diff --git a/media/sqlgram/StringName.png b/media/sqlgram/StringName.png index 065f275b7be4..263fefd9b460 100644 Binary files a/media/sqlgram/StringName.png and b/media/sqlgram/StringName.png differ diff --git a/media/sqlgram/StringNameOrBRIEOptionKeyword.png b/media/sqlgram/StringNameOrBRIEOptionKeyword.png new file mode 100644 index 000000000000..d9766c693a06 Binary files /dev/null and b/media/sqlgram/StringNameOrBRIEOptionKeyword.png differ diff --git a/media/sqlgram/StringType.png b/media/sqlgram/StringType.png index 92e0c9ba4ff6..636e0007779b 100644 Binary files a/media/sqlgram/StringType.png and b/media/sqlgram/StringType.png differ diff --git a/media/sqlgram/SubPartDefinition.png b/media/sqlgram/SubPartDefinition.png new file mode 100644 index 000000000000..a8dbc8d792f0 Binary files /dev/null and b/media/sqlgram/SubPartDefinition.png differ diff --git a/media/sqlgram/SubPartDefinitionListOpt.png b/media/sqlgram/SubPartDefinitionListOpt.png new file mode 100644 index 000000000000..585079bcf8d5 Binary files /dev/null and b/media/sqlgram/SubPartDefinitionListOpt.png differ diff --git a/media/sqlgram/SubPartitionMethod.png b/media/sqlgram/SubPartitionMethod.png new file mode 100644 index 000000000000..f733c6aebec4 Binary files /dev/null and b/media/sqlgram/SubPartitionMethod.png differ diff --git a/media/sqlgram/SubPartitionNumOpt.png b/media/sqlgram/SubPartitionNumOpt.png index adc78d76e654..7f7185cc670f 100644 Binary files a/media/sqlgram/SubPartitionNumOpt.png and b/media/sqlgram/SubPartitionNumOpt.png differ diff --git a/media/sqlgram/SubPartitionOpt.png b/media/sqlgram/SubPartitionOpt.png index 654540b3799b..fad097989795 100644 Binary files a/media/sqlgram/SubPartitionOpt.png and b/media/sqlgram/SubPartitionOpt.png differ diff --git a/media/sqlgram/SubSelect.png b/media/sqlgram/SubSelect.png index 4ba56cd3338d..8d0654ec4998 100644 Binary files a/media/sqlgram/SubSelect.png and b/media/sqlgram/SubSelect.png differ diff --git a/media/sqlgram/SumExpr.png b/media/sqlgram/SumExpr.png index 233af5524e9b..f0bc538e9ea2 100644 Binary files a/media/sqlgram/SumExpr.png and b/media/sqlgram/SumExpr.png differ diff --git a/media/sqlgram/Symbol.png b/media/sqlgram/Symbol.png index 065f275b7be4..ddbd106c1733 100644 Binary files a/media/sqlgram/Symbol.png and b/media/sqlgram/Symbol.png differ diff --git a/media/sqlgram/SystemVariable.png b/media/sqlgram/SystemVariable.png new file mode 100644 index 000000000000..69d8711d4b22 Binary files /dev/null and b/media/sqlgram/SystemVariable.png differ diff --git a/media/sqlgram/TableAliasRefList.png b/media/sqlgram/TableAliasRefList.png new file mode 100644 index 000000000000..40be500a471f Binary files /dev/null and b/media/sqlgram/TableAliasRefList.png differ diff --git a/media/sqlgram/TableAsName.png b/media/sqlgram/TableAsName.png index 67d680e13352..10d690bebb50 100644 Binary files a/media/sqlgram/TableAsName.png and b/media/sqlgram/TableAsName.png differ diff --git a/media/sqlgram/TableAsNameOpt.png b/media/sqlgram/TableAsNameOpt.png index cda8ce1a00f9..c9276a437895 100644 Binary files a/media/sqlgram/TableAsNameOpt.png and b/media/sqlgram/TableAsNameOpt.png differ diff --git a/media/sqlgram/TableElement.png b/media/sqlgram/TableElement.png index 49d54cd00537..8859611c78a8 100644 Binary files a/media/sqlgram/TableElement.png and b/media/sqlgram/TableElement.png differ diff --git a/media/sqlgram/TableElementList.png b/media/sqlgram/TableElementList.png new file mode 100644 index 000000000000..f106c752dc37 Binary files /dev/null and b/media/sqlgram/TableElementList.png differ diff --git a/media/sqlgram/TableElementListOpt.png b/media/sqlgram/TableElementListOpt.png index 12d9436b7c42..72f45117130c 100644 Binary files a/media/sqlgram/TableElementListOpt.png and b/media/sqlgram/TableElementListOpt.png differ diff --git a/media/sqlgram/TableFactor.png b/media/sqlgram/TableFactor.png index 8b367a1d0d8c..903859882256 100644 Binary files a/media/sqlgram/TableFactor.png and b/media/sqlgram/TableFactor.png differ diff --git a/media/sqlgram/TableLock.png b/media/sqlgram/TableLock.png index 5cb847b2eab8..762fa166ddf8 100644 Binary files a/media/sqlgram/TableLock.png and b/media/sqlgram/TableLock.png differ diff --git a/media/sqlgram/TableName.png b/media/sqlgram/TableName.png old mode 100644 new mode 100755 index 296811cbfd9a..7d063393d640 Binary files a/media/sqlgram/TableName.png and b/media/sqlgram/TableName.png differ diff --git a/media/sqlgram/TableNameList.png b/media/sqlgram/TableNameList.png index 2fd3076caa93..28abe8fbdbca 100644 Binary files a/media/sqlgram/TableNameList.png and b/media/sqlgram/TableNameList.png differ diff --git a/media/sqlgram/TableNameListOpt.png b/media/sqlgram/TableNameListOpt.png index bffdf101a935..91a293934f82 100644 Binary files a/media/sqlgram/TableNameListOpt.png and b/media/sqlgram/TableNameListOpt.png differ diff --git a/media/sqlgram/TableNameOptWild.png b/media/sqlgram/TableNameOptWild.png new file mode 100644 index 000000000000..f7f3b9595aeb Binary files /dev/null and b/media/sqlgram/TableNameOptWild.png differ diff --git a/media/sqlgram/TableOptimizerHints.png b/media/sqlgram/TableOptimizerHints.png index 4638d4ea9aa9..762d2077d434 100644 Binary files a/media/sqlgram/TableOptimizerHints.png and b/media/sqlgram/TableOptimizerHints.png differ diff --git a/media/sqlgram/TableOption.png b/media/sqlgram/TableOption.png index 732ef918bde3..8d8d721cb770 100644 Binary files a/media/sqlgram/TableOption.png and b/media/sqlgram/TableOption.png differ diff --git a/media/sqlgram/TableOptionList.png b/media/sqlgram/TableOptionList.png index 2109bdd8fc87..b5af7615b289 100644 Binary files a/media/sqlgram/TableOptionList.png and b/media/sqlgram/TableOptionList.png differ diff --git a/media/sqlgram/TableOrTables.png b/media/sqlgram/TableOrTables.png index aacd0694727b..68a6cee7b31f 100644 Binary files a/media/sqlgram/TableOrTables.png and b/media/sqlgram/TableOrTables.png differ diff --git a/media/sqlgram/TableRef.png b/media/sqlgram/TableRef.png index 69ebe857e7d5..f7826c59c46b 100644 Binary files a/media/sqlgram/TableRef.png and b/media/sqlgram/TableRef.png differ diff --git a/media/sqlgram/TableRefs.png b/media/sqlgram/TableRefs.png index d28039049b1d..435d321b9155 100644 Binary files a/media/sqlgram/TableRefs.png and b/media/sqlgram/TableRefs.png differ diff --git a/media/sqlgram/TableRefsClause.png b/media/sqlgram/TableRefsClause.png index 76e9305fcba2..0ddd28e32a74 100644 Binary files a/media/sqlgram/TableRefsClause.png and b/media/sqlgram/TableRefsClause.png differ diff --git a/media/sqlgram/TableToTable.png b/media/sqlgram/TableToTable.png old mode 100644 new mode 100755 index 4adf7d2f8b33..2228d0dbdc28 Binary files a/media/sqlgram/TableToTable.png and b/media/sqlgram/TableToTable.png differ diff --git a/media/sqlgram/TablesTerminalSym.png b/media/sqlgram/TablesTerminalSym.png index 5988c7b8b3e4..98bf7204d0ef 100644 Binary files a/media/sqlgram/TablesTerminalSym.png and b/media/sqlgram/TablesTerminalSym.png differ diff --git a/media/sqlgram/TextType.png b/media/sqlgram/TextType.png index 085786820299..db1c21dc1ea7 100644 Binary files a/media/sqlgram/TextType.png and b/media/sqlgram/TextType.png differ diff --git a/media/sqlgram/TiDBKeyword.png b/media/sqlgram/TiDBKeyword.png index b86384425331..0e74ba33b9d4 100644 Binary files a/media/sqlgram/TiDBKeyword.png and b/media/sqlgram/TiDBKeyword.png differ diff --git a/media/sqlgram/TimeUnit.png b/media/sqlgram/TimeUnit.png index 8858d82ace3d..4bf26ac3e0a1 100644 Binary files a/media/sqlgram/TimeUnit.png and b/media/sqlgram/TimeUnit.png differ diff --git a/media/sqlgram/TimestampBound.png b/media/sqlgram/TimestampBound.png new file mode 100644 index 000000000000..234ed0a401aa Binary files /dev/null and b/media/sqlgram/TimestampBound.png differ diff --git a/media/sqlgram/TimestampUnit.png b/media/sqlgram/TimestampUnit.png index 75a2eef1964d..216954d6614b 100644 Binary files a/media/sqlgram/TimestampUnit.png and b/media/sqlgram/TimestampUnit.png differ diff --git a/media/sqlgram/TraceStmt.png b/media/sqlgram/TraceStmt.png index f4023451875b..e8a7a3914c63 100644 Binary files a/media/sqlgram/TraceStmt.png and b/media/sqlgram/TraceStmt.png differ diff --git a/media/sqlgram/TraceableStmt.png b/media/sqlgram/TraceableStmt.png index bddac1e18228..60e11af91b95 100644 Binary files a/media/sqlgram/TraceableStmt.png and b/media/sqlgram/TraceableStmt.png differ diff --git a/media/sqlgram/TransactionChar.png b/media/sqlgram/TransactionChar.png index bbd0bfb3ac5a..cf198efab561 100644 Binary files a/media/sqlgram/TransactionChar.png and b/media/sqlgram/TransactionChar.png differ diff --git a/media/sqlgram/TrimDirection.png b/media/sqlgram/TrimDirection.png index 89a994a84e24..d51f41c8c325 100644 Binary files a/media/sqlgram/TrimDirection.png and b/media/sqlgram/TrimDirection.png differ diff --git a/media/sqlgram/TruncateTableStmt.png b/media/sqlgram/TruncateTableStmt.png index baa15a6d6788..428ea3f19acf 100644 Binary files a/media/sqlgram/TruncateTableStmt.png and b/media/sqlgram/TruncateTableStmt.png differ diff --git a/media/sqlgram/Type.png b/media/sqlgram/Type.png index 6ca36679743e..fed60aa7ad33 100644 Binary files a/media/sqlgram/Type.png and b/media/sqlgram/Type.png differ diff --git a/media/sqlgram/UnReservedKeyword.png b/media/sqlgram/UnReservedKeyword.png index c92e93602746..a932eec0cd29 100644 Binary files a/media/sqlgram/UnReservedKeyword.png and b/media/sqlgram/UnReservedKeyword.png differ diff --git a/media/sqlgram/UnionOpt.png b/media/sqlgram/UnionOpt.png index 9f7c7b30481c..33a8b680b585 100644 Binary files a/media/sqlgram/UnionOpt.png and b/media/sqlgram/UnionOpt.png differ diff --git a/media/sqlgram/UnionSelect.png b/media/sqlgram/UnionSelect.png index 0fd534d55a21..684aa8064577 100644 Binary files a/media/sqlgram/UnionSelect.png and b/media/sqlgram/UnionSelect.png differ diff --git a/media/sqlgram/UnionStmt.png b/media/sqlgram/UnionStmt.png index a37f3893a063..94411aa606d4 100644 Binary files a/media/sqlgram/UnionStmt.png and b/media/sqlgram/UnionStmt.png differ diff --git a/media/sqlgram/UnlockTablesStmt.png b/media/sqlgram/UnlockTablesStmt.png index fdc904c310b5..b1051e347a17 100644 Binary files a/media/sqlgram/UnlockTablesStmt.png and b/media/sqlgram/UnlockTablesStmt.png differ diff --git a/media/sqlgram/UpdateStmt.png b/media/sqlgram/UpdateStmt.png index 35c4ebf57f00..a780025ac235 100644 Binary files a/media/sqlgram/UpdateStmt.png and b/media/sqlgram/UpdateStmt.png differ diff --git a/media/sqlgram/UseStmt.png b/media/sqlgram/UseStmt.png index 23206eda5ad1..873716e54ad9 100644 Binary files a/media/sqlgram/UseStmt.png and b/media/sqlgram/UseStmt.png differ diff --git a/media/sqlgram/UserSpec.png b/media/sqlgram/UserSpec.png index bd74951a3c17..7ef8fe048b4a 100644 Binary files a/media/sqlgram/UserSpec.png and b/media/sqlgram/UserSpec.png differ diff --git a/media/sqlgram/UserSpecList.png b/media/sqlgram/UserSpecList.png index 5c06ec4fd1a0..bc48b489a19f 100644 Binary files a/media/sqlgram/UserSpecList.png and b/media/sqlgram/UserSpecList.png differ diff --git a/media/sqlgram/UserVariable.png b/media/sqlgram/UserVariable.png new file mode 100644 index 000000000000..064fccfa603e Binary files /dev/null and b/media/sqlgram/UserVariable.png differ diff --git a/media/sqlgram/Username.png b/media/sqlgram/Username.png index 10588135ec9f..c7d7a0a100c5 100644 Binary files a/media/sqlgram/Username.png and b/media/sqlgram/Username.png differ diff --git a/media/sqlgram/UsernameList.png b/media/sqlgram/UsernameList.png new file mode 100644 index 000000000000..490382c1928b Binary files /dev/null and b/media/sqlgram/UsernameList.png differ diff --git a/media/sqlgram/UsingRoles.png b/media/sqlgram/UsingRoles.png new file mode 100755 index 000000000000..41ff3a60d64c Binary files /dev/null and b/media/sqlgram/UsingRoles.png differ diff --git a/media/sqlgram/ValueSym.png b/media/sqlgram/ValueSym.png index 1f206d86724c..79d4fc5306fe 100644 Binary files a/media/sqlgram/ValueSym.png and b/media/sqlgram/ValueSym.png differ diff --git a/media/sqlgram/ValuesList.png b/media/sqlgram/ValuesList.png index 6a3696d45b9c..5518955dda3c 100644 Binary files a/media/sqlgram/ValuesList.png and b/media/sqlgram/ValuesList.png differ diff --git a/media/sqlgram/ValuesOpt.png b/media/sqlgram/ValuesOpt.png index 535eabec0232..13b9e5fd975f 100644 Binary files a/media/sqlgram/ValuesOpt.png and b/media/sqlgram/ValuesOpt.png differ diff --git a/media/sqlgram/Varchar.png b/media/sqlgram/Varchar.png index 142a9eca4cb4..c4ef6641a460 100644 Binary files a/media/sqlgram/Varchar.png and b/media/sqlgram/Varchar.png differ diff --git a/media/sqlgram/Variable.png b/media/sqlgram/Variable.png index b246d5e803f1..d0a48edde033 100644 Binary files a/media/sqlgram/Variable.png and b/media/sqlgram/Variable.png differ diff --git a/media/sqlgram/VariableAssignment.png b/media/sqlgram/VariableAssignment.png index 73a3e7487733..6dee3c5dd560 100644 Binary files a/media/sqlgram/VariableAssignment.png and b/media/sqlgram/VariableAssignment.png differ diff --git a/media/sqlgram/VariableAssignmentList.png b/media/sqlgram/VariableAssignmentList.png new file mode 100644 index 000000000000..fa110accf258 Binary files /dev/null and b/media/sqlgram/VariableAssignmentList.png differ diff --git a/media/sqlgram/VariableName.png b/media/sqlgram/VariableName.png new file mode 100644 index 000000000000..8f40d55f7ded Binary files /dev/null and b/media/sqlgram/VariableName.png differ diff --git a/media/sqlgram/ViewAlgorithm.png b/media/sqlgram/ViewAlgorithm.png index 43bf148eb348..ea596e4f9e41 100644 Binary files a/media/sqlgram/ViewAlgorithm.png and b/media/sqlgram/ViewAlgorithm.png differ diff --git a/media/sqlgram/ViewCheckOption.png b/media/sqlgram/ViewCheckOption.png index 12237a4361c1..8efc992efe3b 100644 Binary files a/media/sqlgram/ViewCheckOption.png and b/media/sqlgram/ViewCheckOption.png differ diff --git a/media/sqlgram/ViewDefiner.png b/media/sqlgram/ViewDefiner.png index 7d44d72eb31c..17f1094c621a 100644 Binary files a/media/sqlgram/ViewDefiner.png and b/media/sqlgram/ViewDefiner.png differ diff --git a/media/sqlgram/ViewFieldList.png b/media/sqlgram/ViewFieldList.png index 8bfb381bfb53..4e8ac8a996d3 100644 Binary files a/media/sqlgram/ViewFieldList.png and b/media/sqlgram/ViewFieldList.png differ diff --git a/media/sqlgram/ViewName.png b/media/sqlgram/ViewName.png index 47dafce7d661..10ebb2f6065a 100644 Binary files a/media/sqlgram/ViewName.png and b/media/sqlgram/ViewName.png differ diff --git a/media/sqlgram/ViewSQLSecurity.png b/media/sqlgram/ViewSQLSecurity.png index 592eef52ef6b..f75124f1e369 100644 Binary files a/media/sqlgram/ViewSQLSecurity.png and b/media/sqlgram/ViewSQLSecurity.png differ diff --git a/media/sqlgram/VirtualOrStored.png b/media/sqlgram/VirtualOrStored.png index 066096c580bb..b1b56c86518b 100644 Binary files a/media/sqlgram/VirtualOrStored.png and b/media/sqlgram/VirtualOrStored.png differ diff --git a/media/sqlgram/WhenClause.png b/media/sqlgram/WhenClause.png index 0ce6a4052728..eabc424d914c 100644 Binary files a/media/sqlgram/WhenClause.png and b/media/sqlgram/WhenClause.png differ diff --git a/media/sqlgram/WhereClause.png b/media/sqlgram/WhereClause.png old mode 100644 new mode 100755 index 8a46aacf6513..290645f687db Binary files a/media/sqlgram/WhereClause.png and b/media/sqlgram/WhereClause.png differ diff --git a/media/sqlgram/WhereClauseOptional.png b/media/sqlgram/WhereClauseOptional.png old mode 100644 new mode 100755 index 1b8979a8b012..b6c6a3e46df7 Binary files a/media/sqlgram/WhereClauseOptional.png and b/media/sqlgram/WhereClauseOptional.png differ diff --git a/media/sqlgram/WindowClauseOptional.png b/media/sqlgram/WindowClauseOptional.png index d7a617bdc95c..150f42e26acc 100644 Binary files a/media/sqlgram/WindowClauseOptional.png and b/media/sqlgram/WindowClauseOptional.png differ diff --git a/media/sqlgram/WindowDefinition.png b/media/sqlgram/WindowDefinition.png index e28cc161971b..3f839b06fd1b 100644 Binary files a/media/sqlgram/WindowDefinition.png and b/media/sqlgram/WindowDefinition.png differ diff --git a/media/sqlgram/WindowFrameBetween.png b/media/sqlgram/WindowFrameBetween.png index cf54f99b5816..edc1f190b79a 100644 Binary files a/media/sqlgram/WindowFrameBetween.png and b/media/sqlgram/WindowFrameBetween.png differ diff --git a/media/sqlgram/WindowFrameBound.png b/media/sqlgram/WindowFrameBound.png index be09bc8f2021..c08926251fce 100644 Binary files a/media/sqlgram/WindowFrameBound.png and b/media/sqlgram/WindowFrameBound.png differ diff --git a/media/sqlgram/WindowFrameExtent.png b/media/sqlgram/WindowFrameExtent.png index f87c85d8e62a..3c16ddddd358 100644 Binary files a/media/sqlgram/WindowFrameExtent.png and b/media/sqlgram/WindowFrameExtent.png differ diff --git a/media/sqlgram/WindowFrameStart.png b/media/sqlgram/WindowFrameStart.png index 92dbbf84d7dc..195c698e129f 100644 Binary files a/media/sqlgram/WindowFrameStart.png and b/media/sqlgram/WindowFrameStart.png differ diff --git a/media/sqlgram/WindowFrameUnits.png b/media/sqlgram/WindowFrameUnits.png index fc94832a3873..91c9d75be2d6 100644 Binary files a/media/sqlgram/WindowFrameUnits.png and b/media/sqlgram/WindowFrameUnits.png differ diff --git a/media/sqlgram/WindowFuncCall.png b/media/sqlgram/WindowFuncCall.png index dcc580c0230c..816e92fb245a 100644 Binary files a/media/sqlgram/WindowFuncCall.png and b/media/sqlgram/WindowFuncCall.png differ diff --git a/media/sqlgram/WindowName.png b/media/sqlgram/WindowName.png index 065f275b7be4..ddbd106c1733 100644 Binary files a/media/sqlgram/WindowName.png and b/media/sqlgram/WindowName.png differ diff --git a/media/sqlgram/WindowNameOrSpec.png b/media/sqlgram/WindowNameOrSpec.png index b8dac6fbb988..d952ff834710 100644 Binary files a/media/sqlgram/WindowNameOrSpec.png and b/media/sqlgram/WindowNameOrSpec.png differ diff --git a/media/sqlgram/WindowSpec.png b/media/sqlgram/WindowSpec.png index 2a7ee0740dd9..a238f1af315a 100644 Binary files a/media/sqlgram/WindowSpec.png and b/media/sqlgram/WindowSpec.png differ diff --git a/media/sqlgram/WindowSpecDetails.png b/media/sqlgram/WindowSpecDetails.png index 9f2219d3a07a..a945364fc226 100644 Binary files a/media/sqlgram/WindowSpecDetails.png and b/media/sqlgram/WindowSpecDetails.png differ diff --git a/media/sqlgram/WindowingClause.png b/media/sqlgram/WindowingClause.png index 01b37b5ce9bf..74233bec84ec 100644 Binary files a/media/sqlgram/WindowingClause.png and b/media/sqlgram/WindowingClause.png differ diff --git a/media/sqlgram/WithGrantOptionOpt.png b/media/sqlgram/WithGrantOptionOpt.png index 9b626f3e3fb8..f4f9017ded35 100644 Binary files a/media/sqlgram/WithGrantOptionOpt.png and b/media/sqlgram/WithGrantOptionOpt.png differ diff --git a/media/sqlgram/WithReadLockOpt.png b/media/sqlgram/WithReadLockOpt.png index 44a704d2f749..c88c45496311 100644 Binary files a/media/sqlgram/WithReadLockOpt.png and b/media/sqlgram/WithReadLockOpt.png differ diff --git a/media/sqlgram/WithValidation.png b/media/sqlgram/WithValidation.png new file mode 100644 index 000000000000..7f17b4e382e8 Binary files /dev/null and b/media/sqlgram/WithValidation.png differ diff --git a/media/sqlgram/WithValidationOpt.png b/media/sqlgram/WithValidationOpt.png new file mode 100644 index 000000000000..7fb1b34653db Binary files /dev/null and b/media/sqlgram/WithValidationOpt.png differ diff --git a/media/sqlgram/Year.png b/media/sqlgram/Year.png new file mode 100644 index 000000000000..d245047911fb Binary files /dev/null and b/media/sqlgram/Year.png differ diff --git a/media/sqlgram/logAnd.png b/media/sqlgram/logAnd.png index c7ab4999a319..7a9242b928c0 100644 Binary files a/media/sqlgram/logAnd.png and b/media/sqlgram/logAnd.png differ diff --git a/media/sqlgram/logOr.png b/media/sqlgram/logOr.png index cefac60d19f1..b4cd4358a3ce 100644 Binary files a/media/sqlgram/logOr.png and b/media/sqlgram/logOr.png differ diff --git a/media/sqlgram/rr-1.45.1338.png b/media/sqlgram/rr-1.45.1338.png deleted file mode 100644 index 22b50eb63785..000000000000 Binary files a/media/sqlgram/rr-1.45.1338.png and /dev/null differ diff --git a/media/sqlgram/rr-1.62.png b/media/sqlgram/rr-1.62.png new file mode 100644 index 000000000000..d7fc4c9c91ac Binary files /dev/null and b/media/sqlgram/rr-1.62.png differ diff --git a/media/statistics-1.png b/media/statistics-1.png new file mode 100755 index 000000000000..3bf886a5af3a Binary files /dev/null and b/media/statistics-1.png differ diff --git a/media/sysbench_v4vsv3_point_select.png b/media/sysbench_v4vsv3_point_select.png new file mode 100644 index 000000000000..b9a4cbba03bc Binary files /dev/null and b/media/sysbench_v4vsv3_point_select.png differ diff --git a/media/sysbench_v4vsv3_read_write.png b/media/sysbench_v4vsv3_read_write.png new file mode 100644 index 000000000000..9b3d48ec22d2 Binary files /dev/null and b/media/sysbench_v4vsv3_read_write.png differ diff --git a/media/sysbench_v4vsv3_update_index.png b/media/sysbench_v4vsv3_update_index.png new file mode 100644 index 000000000000..d58689b519df Binary files /dev/null and b/media/sysbench_v4vsv3_update_index.png differ diff --git a/media/sysbench_v4vsv3_update_non_index.png b/media/sysbench_v4vsv3_update_non_index.png new file mode 100644 index 000000000000..d158d731a26c Binary files /dev/null and b/media/sysbench_v4vsv3_update_non_index.png differ diff --git a/media/three-data-centers-in-two-cities-deployment-01.png b/media/three-data-centers-in-two-cities-deployment-01.png new file mode 100644 index 000000000000..d61058d3c06e Binary files /dev/null and b/media/three-data-centers-in-two-cities-deployment-01.png differ diff --git a/media/three-data-centers-in-two-cities-deployment-02.png b/media/three-data-centers-in-two-cities-deployment-02.png new file mode 100644 index 000000000000..d1d6c6e38d84 Binary files /dev/null and b/media/three-data-centers-in-two-cities-deployment-02.png differ diff --git a/media/three-data-centers-in-two-cities-deployment-03.png b/media/three-data-centers-in-two-cities-deployment-03.png new file mode 100644 index 000000000000..2dd50ef67b43 Binary files /dev/null and b/media/three-data-centers-in-two-cities-deployment-03.png differ diff --git a/media/tidb-architecture-1.png b/media/tidb-architecture-1.png new file mode 100644 index 000000000000..c9f9ecbb593e Binary files /dev/null and b/media/tidb-architecture-1.png differ diff --git a/media/tidb-computing-dist-sql-flow.png b/media/tidb-computing-dist-sql-flow.png new file mode 100644 index 000000000000..f68a7d9f2417 Binary files /dev/null and b/media/tidb-computing-dist-sql-flow.png differ diff --git a/media/tidb-computing-native-sql-flow.jpeg b/media/tidb-computing-native-sql-flow.jpeg new file mode 100644 index 000000000000..e058f4a7765f Binary files /dev/null and b/media/tidb-computing-native-sql-flow.jpeg differ diff --git a/media/tidb-computing-tidb-sql-layer.png b/media/tidb-computing-tidb-sql-layer.png new file mode 100644 index 000000000000..c496493bdb4d Binary files /dev/null and b/media/tidb-computing-tidb-sql-layer.png differ diff --git a/media/tidb-storage-1.png b/media/tidb-storage-1.png new file mode 100644 index 000000000000..04c8c338ad15 Binary files /dev/null and b/media/tidb-storage-1.png differ diff --git a/media/tidb-storage-2.png b/media/tidb-storage-2.png new file mode 100644 index 000000000000..f98bdb590889 Binary files /dev/null and b/media/tidb-storage-2.png differ diff --git a/media/tidb-storage-3.png b/media/tidb-storage-3.png new file mode 100644 index 000000000000..5a013b7df06e Binary files /dev/null and b/media/tidb-storage-3.png differ diff --git a/media/tidb-storage-architecture.png b/media/tidb-storage-architecture.png new file mode 100644 index 000000000000..89e1fe8589b4 Binary files /dev/null and b/media/tidb-storage-architecture.png differ diff --git a/media/tiflash/tidb-display.png b/media/tiflash/tidb-display.png deleted file mode 100644 index e1f99803077e..000000000000 Binary files a/media/tiflash/tidb-display.png and /dev/null differ diff --git a/media/tiflash/tiflash-architecture.jpg b/media/tiflash/tiflash-architecture.jpg deleted file mode 100644 index 7b92faabd472..000000000000 Binary files a/media/tiflash/tiflash-architecture.jpg and /dev/null differ diff --git a/media/tiflash/tiflash-architecture.png b/media/tiflash/tiflash-architecture.png new file mode 100644 index 000000000000..1aa62c59398b Binary files /dev/null and b/media/tiflash/tiflash-architecture.png differ diff --git a/media/tikv-arch.png b/media/tikv-arch.png new file mode 100644 index 000000000000..7272faf31e01 Binary files /dev/null and b/media/tikv-arch.png differ diff --git a/media/tikv-rocksdb.png b/media/tikv-rocksdb.png new file mode 100644 index 000000000000..639e38b1d391 Binary files /dev/null and b/media/tikv-rocksdb.png differ diff --git a/media/titan/titan-1.png b/media/titan/titan-1.png new file mode 100644 index 000000000000..d98ccc68e42d Binary files /dev/null and b/media/titan/titan-1.png differ diff --git a/media/titan/titan-2.png b/media/titan/titan-2.png new file mode 100644 index 000000000000..d4d236e50cc5 Binary files /dev/null and b/media/titan/titan-2.png differ diff --git a/media/titan/titan-3.png b/media/titan/titan-3.png new file mode 100644 index 000000000000..3c8e0cd38aa4 Binary files /dev/null and b/media/titan/titan-3.png differ diff --git a/media/titan/titan-4.png b/media/titan/titan-4.png new file mode 100644 index 000000000000..5a5a162e6609 Binary files /dev/null and b/media/titan/titan-4.png differ diff --git a/media/titan/titan-5.png b/media/titan/titan-5.png new file mode 100644 index 000000000000..8e26e32bc86b Binary files /dev/null and b/media/titan/titan-5.png differ diff --git a/media/titan/titan-6.png b/media/titan/titan-6.png new file mode 100644 index 000000000000..d25cd4a1f5f6 Binary files /dev/null and b/media/titan/titan-6.png differ diff --git a/media/titan/titan-7.png b/media/titan/titan-7.png new file mode 100644 index 000000000000..a5261ad25170 Binary files /dev/null and b/media/titan/titan-7.png differ diff --git a/media/tiup/grafana-login.png b/media/tiup/grafana-login.png new file mode 100644 index 000000000000..c052324e9cb7 Binary files /dev/null and b/media/tiup/grafana-login.png differ diff --git a/media/tiup/grafana-overview.png b/media/tiup/grafana-overview.png new file mode 100644 index 000000000000..75adea8e6db1 Binary files /dev/null and b/media/tiup/grafana-overview.png differ diff --git a/media/tiup/tidb-dashboard-status.png b/media/tiup/tidb-dashboard-status.png new file mode 100644 index 000000000000..7d183a13000a Binary files /dev/null and b/media/tiup/tidb-dashboard-status.png differ diff --git a/media/tiup/tidb-dashboard.png b/media/tiup/tidb-dashboard.png new file mode 100644 index 000000000000..fb58ab877240 Binary files /dev/null and b/media/tiup/tidb-dashboard.png differ diff --git a/media/tpcc-3.0-4.0.png b/media/tpcc-3.0-4.0.png new file mode 100644 index 000000000000..8756579cd6d9 Binary files /dev/null and b/media/tpcc-3.0-4.0.png differ diff --git a/media/tpcc_v4vsv3.png b/media/tpcc_v4vsv3.png new file mode 100644 index 000000000000..d33e844b5453 Binary files /dev/null and b/media/tpcc_v4vsv3.png differ diff --git a/media/tpch_v4vsv3.png b/media/tpch_v4vsv3.png new file mode 100644 index 000000000000..198ce7e95525 Binary files /dev/null and b/media/tpch_v4vsv3.png differ diff --git a/media/troubleshoot-hot-spot-issues-1.png b/media/troubleshoot-hot-spot-issues-1.png new file mode 100644 index 000000000000..41576bdd61bb Binary files /dev/null and b/media/troubleshoot-hot-spot-issues-1.png differ diff --git a/media/troubleshoot-hot-spot-issues-2.png b/media/troubleshoot-hot-spot-issues-2.png new file mode 100644 index 000000000000..ce82b1041a16 Binary files /dev/null and b/media/troubleshoot-hot-spot-issues-2.png differ diff --git a/media/troubleshoot-hot-spot-issues-3.png b/media/troubleshoot-hot-spot-issues-3.png new file mode 100644 index 000000000000..4a9b58b39e9c Binary files /dev/null and b/media/troubleshoot-hot-spot-issues-3.png differ diff --git a/media/troubleshoot-hot-spot-issues-4.png b/media/troubleshoot-hot-spot-issues-4.png new file mode 100644 index 000000000000..56c3d5f81148 Binary files /dev/null and b/media/troubleshoot-hot-spot-issues-4.png differ diff --git a/media/troubleshoot-hot-spot-issues-5.png b/media/troubleshoot-hot-spot-issues-5.png new file mode 100644 index 000000000000..421b60db76a2 Binary files /dev/null and b/media/troubleshoot-hot-spot-issues-5.png differ diff --git a/media/troubleshoot-hot-spot-issues-6.png b/media/troubleshoot-hot-spot-issues-6.png new file mode 100644 index 000000000000..70b7c78ae2c4 Binary files /dev/null and b/media/troubleshoot-hot-spot-issues-6.png differ diff --git a/media/troubleshoot-hot-spot-issues-7.png b/media/troubleshoot-hot-spot-issues-7.png new file mode 100644 index 000000000000..b723c72af3e4 Binary files /dev/null and b/media/troubleshoot-hot-spot-issues-7.png differ diff --git a/media/troubleshoot-hot-spot-issues-8.png b/media/troubleshoot-hot-spot-issues-8.png new file mode 100644 index 000000000000..f70c396c3bf1 Binary files /dev/null and b/media/troubleshoot-hot-spot-issues-8.png differ diff --git a/media/troubleshooting-lock-pic-01.png b/media/troubleshooting-lock-pic-01.png new file mode 100644 index 000000000000..61e923236bd0 Binary files /dev/null and b/media/troubleshooting-lock-pic-01.png differ diff --git a/media/troubleshooting-lock-pic-04.png b/media/troubleshooting-lock-pic-04.png new file mode 100644 index 000000000000..96e94d58113e Binary files /dev/null and b/media/troubleshooting-lock-pic-04.png differ diff --git a/media/troubleshooting-lock-pic-05.png b/media/troubleshooting-lock-pic-05.png new file mode 100644 index 000000000000..efcc7b92cfd7 Binary files /dev/null and b/media/troubleshooting-lock-pic-05.png differ diff --git a/media/troubleshooting-lock-pic-06.png b/media/troubleshooting-lock-pic-06.png new file mode 100644 index 000000000000..7b6bb90d93f3 Binary files /dev/null and b/media/troubleshooting-lock-pic-06.png differ diff --git a/media/troubleshooting-lock-pic-07.png b/media/troubleshooting-lock-pic-07.png new file mode 100644 index 000000000000..f42ad5c146b7 Binary files /dev/null and b/media/troubleshooting-lock-pic-07.png differ diff --git a/media/troubleshooting-lock-pic-08.png b/media/troubleshooting-lock-pic-08.png new file mode 100644 index 000000000000..3aa44a66bbbf Binary files /dev/null and b/media/troubleshooting-lock-pic-08.png differ diff --git a/media/troubleshooting-lock-pic-09.png b/media/troubleshooting-lock-pic-09.png new file mode 100644 index 000000000000..78c5cd47a5cb Binary files /dev/null and b/media/troubleshooting-lock-pic-09.png differ diff --git a/media/troubleshooting-write-conflict-kv-backoff-ops.png b/media/troubleshooting-write-conflict-kv-backoff-ops.png new file mode 100644 index 000000000000..87990de57500 Binary files /dev/null and b/media/troubleshooting-write-conflict-kv-backoff-ops.png differ diff --git a/media/troubleshooting-write-conflict-kv-retry-duration.png b/media/troubleshooting-write-conflict-kv-retry-duration.png new file mode 100644 index 000000000000..32383610b5fa Binary files /dev/null and b/media/troubleshooting-write-conflict-kv-retry-duration.png differ diff --git a/media/troubleshooting-write-conflict-lock-resolve-ops.png b/media/troubleshooting-write-conflict-lock-resolve-ops.png new file mode 100644 index 000000000000..c96724ab8c74 Binary files /dev/null and b/media/troubleshooting-write-conflict-lock-resolve-ops.png differ diff --git a/migrate-from-aurora-mysql-database.md b/migrate-from-aurora-mysql-database.md new file mode 100644 index 000000000000..36fa404e0012 --- /dev/null +++ b/migrate-from-aurora-mysql-database.md @@ -0,0 +1,208 @@ +--- +title: 从 MySQL 迁移数据——以 Amazon Aurora MySQL 为例 +summary: 使用 DM 从 MySQL/Amazon Aurora MySQL 迁移数据。 +category: how-to +aliases: ['/docs-cn/stable/how-to/migrate/from-mysql-aurora/'] +--- + +# 从 MySQL 迁移数据——以 Amazon Aurora MySQL 为例 + +本文以 [Amazon Aurora MySQL](https://aws.amazon.com/cn/rds/aurora/details/mysql-details/) 为例介绍如何使用 DM 从 MySQL 协议数据库迁移数据到 TiDB。 + +## 第 1 步:在 Aurora 集群中启用 binlog + +假设有两个 Aurora 集群需要迁移数据到 TiDB,其集群信息如下,其中 Aurora-1 包含一个独立的读取器节点。 + +| 集群 | 终端节点 | 端口 | 角色 | +|:-------- |:--- | :--- | :--- | +| Aurora-1 | pingcap-1.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | 写入器 | +| Aurora-1 | pingcap-1-us-east-2a.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | 读取器 | +| Aurora-2 | pingcap-2.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | 写入器 | + +DM 在增量同步阶段依赖 `ROW` 格式的 binlog,如果未启用 binlog 及设置正确的 binlog 格式,则不能正常使用 DM 进行数据同步,具体可参见[检查内容](https://pingcap.com/docs-cn/tidb-data-migration/stable/precheck/#检查内容)。 + +> **注意:** +> +> Aurora 读取器不能开启 binlog,因此不能作为 DM 数据迁移时的上游 master server。 + +如果需要基于 GTID 进行数据迁移,还需要为 Aurora 集群启用 GTID 支持。 + +> **注意:** +> +> 基于 GTID 的数据迁移需要 MySQL 5.7 (Aurora 2.04.1) 或更高版本。 + +### 为 Aurora 集群修改 binlog 相关参数 + +在 Aurora 集群中,binlog 相关参数是**集群参数组中的集群级参数**,有关如何为 Aurora 集群启用 binlog 支持,请参考[在复制主实例上启用二进制日志记录](https://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Replication.MySQL.html#AuroraMySQL.Replication.MySQL.EnableBinlog)。在使用 DM 进行数据迁移时,需要将 `binlog_format` 参数设置为 `ROW`。 + +如果需要基于 GTID 进行数据迁移,需要将 `gtid-mode` 与 `enforce_gtid_consistency` 均设置为 `ON`。有关如何为 Aurora 集群启用基于 GTID 的数据迁移支持,请参考 [Configuring GTID-Based Replication for an Aurora MySQL Cluster](https://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/AuroraUserGuide/mysql-replication-gtid.html#mysql-replication-gtid.configuring-aurora)。 + +> **注意:** +> +> 在 Aurora 管理后台中,`gtid_mode` 参数表示为 `gtid-mode`。 + +## 第 2 步:部署 DM 集群 + +目前推荐使用 DM-Ansible 部署 DM 集群,具体部署方法参照[使用 DM-Ansible 部署 DM 集群](https://pingcap.com/docs-cn/tidb-data-migration/stable/deploy-a-dm-cluster-using-ansible/)。 + +> **注意:** +> +> - 在 DM 所有的配置文件中,数据库的密码要使用 dmctl 加密后的密文。如果数据库密码为空,则不需要加密。关于如何使用 dmctl 加密明文密码,参考[使用 dmctl 加密上游 MySQL 用户密码](https://pingcap.com/docs-cn/tidb-data-migration/stable/deploy-a-dm-cluster-using-ansible/#使用-dmctl-加密上游-mysql-用户密码)。 +> - 上下游数据库用户必须拥有相应的读写权限。 + +## 第 3 步:检查集群信息 + +使用 DM-Ansible 部署 DM 集群后,相关配置信息如下: + +- DM 集群相关组件配置信息 + + | 组件 | 主机 | 端口 | + |:------|:---- |:---- | + | dm_worker1 | 172.16.10.72 | 8262 | + | dm_worker2 | 172.16.10.73 | 8262 | + | dm_master | 172.16.10.71 | 8261 | + +- 上下游数据库实例相关信息 + + | 数据库实例 | 主机 | 端口 | 用户名 | 加密密码 | + |:-------- |:--- | :--- | :--- | :--- | + | 上游 Aurora-1 | pingcap-1.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | root | VjX8cEeTX+qcvZ3bPaO4h0C80pe/1aU= | + | 上游 Aurora-2 | pingcap-2.h8emfqdptyc4.us-east-2.rds.amazonaws.com | 3306 | root | VjX8cEeTX+qcvZ3bPaO4h0C80pe/1aU= | + | 下游 TiDB | 172.16.10.83 | 4000 | root | | + +- dm-master 进程配置文件 `{ansible deploy}/conf/dm-master.toml` 中的配置 + + ```toml + # Master 配置。 + + [[deploy]] + source-id = "mysql-replica-01" + dm-worker = "172.16.10.72:8262" + + [[deploy]] + source-id = "mysql-replica-02" + dm-worker = "172.16.10.73:8262" + ``` + +## 第 4 步:配置任务 + +假设需要将 Aurora-1 和 Aurora-2 实例的 `test_db` 库的 `test_table` 表以**全量+增量**的模式同步到下游 TiDB 的 `test_db` 库的 `test_table` 表。 + +复制并编辑 `{ansible deploy}/conf/task.yaml.example`,生成如下任务配置文件 `task.yaml`: + +```yaml +# 任务名,多个同时运行的任务不能重名。 +name: "test" +# 全量+增量 (all) 同步模式。 +task-mode: "all" +# 下游 TiDB 配置信息。 +target-database: + host: "172.16.10.83" + port: 4000 + user: "root" + password: "" + +# 当前数据同步任务需要的全部上游 MySQL 实例配置。 +mysql-instances: +- + # 上游实例或者复制组 ID,参考 `inventory.ini` 的 `source_id` 或者 `dm-master.toml` 的 `source-id 配置`。 + source-id: "mysql-replica-01" + # 需要同步的库名或表名的黑白名单的配置项名称,用于引用全局的黑白名单配置,全局配置见下面的 `black-white-list` 的配置。 + black-white-list: "global" + # Mydumper 的配置项名称,用于引用全局的 Mydumper 配置。 + mydumper-config-name: "global" + +- + source-id: "mysql-replica-02" + black-white-list: "global" + mydumper-config-name: "global" + +# 黑白名单全局配置,各实例通过配置项名引用。 +black-white-list: + global: + do-tables: # 需要同步的上游表的白名单。 + - db-name: "test_db" # 需要同步的表的库名。 + tbl-name: "test_table" # 需要同步的表的名称。 + +# Mydumper 全局配置,各实例通过配置项名引用。 +mydumpers: + global: + extra-args: "-B test_db -T test_table" # mydumper 的其他参数,从 DM 1.0.2 版本开始,DM 会自动生成 table-list 配置,在其之前的版本仍然需要人工配置。 +``` + +## 第 5 步:启动任务 + +1. 进入 dmctl 目录 `/home/tidb/dm-ansible/resources/bin/` + +2. 执行以下命令启动 dmctl + + {{< copyable "shell-regular" >}} + + ```bash + ./dmctl --master-addr 172.16.10.71:8261 + ``` + +3. 执行以下命令启动数据同步任务(`task.yaml` 是之前编辑的配置文件) + + {{< copyable "shell-regular" >}} + + ```bash + start-task ./task.yaml + ``` + + - 如果执行命令后的返回结果中不包含错误信息,则表明任务已经成功启动 + - 如果包含以下错误信息,则表明上游 Aurora 用户可能拥有 TiDB 不支持的权限类型 + + ```json + { + "id": 4, + "name": "source db dump privilege chcker", + "desc": "check dump privileges of source DB", + "state": "fail", + "errorMsg": "line 1 column 285 near \"LOAD FROM S3, SELECT INTO S3 ON *.* TO 'root'@'%' WITH GRANT OPTION\" ...", + "instruction": "", + "extra": "address of db instance - pingcap-1.h8emfqdptyc4.us-east-2.rds.amazonaws.com" + }, + { + "id": 5, + "name": "source db replication privilege chcker", + "desc": "check replication privileges of source DB", + "state": "fail", + "errorMsg": "line 1 column 285 near \"LOAD FROM S3, SELECT INTO S3 ON *.* TO 'root'@'%' WITH GRANT OPTION\" ...", + "instruction": "", + "extra": "address of db instance - pingcap-1.h8emfqdptyc4.us-east-2.rds.amazonaws.com" + } + ``` + + 此时可以选择以下两种处理方法中的任意一种进行处理后,再使用 `start-task` 尝试重新启动任务: + + 1. 为用于进行数据迁移的 Aurora 用户移除不被 TiDB 支持的不必要的权限 + 2. 如果能确保 Aurora 用户拥有 DM 所需要的权限,可以在 `task.yaml` 配置文件中添加如下顶级配置项以跳过启用任务时的前置权限检查 + + ```yaml + ignore-checking-items: ["dump_privilege", "replication_privilege"] + ``` + +## 第 6 步:查询任务 + +如需了解 DM 集群中是否存在正在运行的同步任务及任务状态等信息,可在 dmctl 内使用以下命令进行查询: + +{{< copyable "shell-regular" >}} + +```bash +query-status +``` + +> **注意:** +> +> 如果查询命令的返回结果中包含以下错误信息,则表明在全量同步的 dump 阶段不能获得相应的 lock: +> +> ``` +> Couldn't acquire global lock, snapshots will not be consistent: Access denied for user 'root'@'%' (using password: YES) +> ``` +> +> 此时如果能接受不使用 FTWL 来确保 dump 文件与 metadata 的一致或上游能暂时停止写入,可以通过为 `mydumpers` 下的 `extra-args` 添加 `--no-locks` 参数来进行绕过,具体方法为: +> +> 1. 使用 `stop-task` 停止当前由于不能正常 dump 而已经转为 paused 的任务 +> 2. 将原 `task.yaml` 中的 `extra-args: "-B test_db -T test_table"` 更新为 `extra-args: "-B test_db -T test_table --no-locks"` +> 3. 使用 `start-task` 重新启动任务 diff --git a/migrate-from-mysql-mydumper-files.md b/migrate-from-mysql-mydumper-files.md new file mode 100644 index 000000000000..7641a1928b3d --- /dev/null +++ b/migrate-from-mysql-mydumper-files.md @@ -0,0 +1,62 @@ +--- +title: 从 MySQL SQL 文件迁移数据 +summary: 使用 TiDB Lightning 从 MySQL 迁移数据。 +category: how-to +--- + +# 从 MySQL SQL 文件迁移数据 + +本文介绍如何使用 TiDB Lightning 从 MySQL SQL 文件迁移数据到 TiDB。关于如何生成 MySQL SQL 文件,可以参考 [Mydumper](/mydumper-overview.md) 或者 [Dumpling](/export-or-backup-using-dumpling.md) 文档。 + +## 第 1 步:部署 TiDB Lightning + +使用 Lightning 将数据导入 TiDB,Lightning 具体的部署方法见 [TiDB Lightning 部署](/tidb-lightning/deploy-tidb-lightning.md)。 + +> **注意:** +> +> - 如果选用 Importer Backend 来导入数据,除需要部署 TiDB Lightning 组件外,也需要部署 TiKV Importer 组件。导入期间集群无法提供正常的服务,速度更快,适用于导入大量的数据(TB 以上级别)。 +> - 如果选用 TiDB Backend 来导入数据,只需要部署 TiDB Lightning 组件。导入期间集群可以正常提供服务。 +> - 二者的具体差别参见 [TiDB Lightning Backend](/tidb-lightning/tidb-lightning-tidb-backend.md)。 + +## 第 2 步:配置 TiDB Lightning 的数据源 + +本文以选用 TiDB Backend 导入数据为例。增加 `tidb-lightning.toml 配置文件`,在文件中添加以下主要配置: + +1. 将 `[mydumper]` 下的 `data-source-dir` 设置为 MySQL 的 SQL 文件路径。 + + ``` + [mydumper] + # 数据源目录 + data-source-dir = "/data/export" + ``` + + > **注意:** + > + > 如果下游已经存在对应的 schema,那么可以设置 `no-schema=true` 来跳过 schema 创建的步骤。 + +2. 增加目标集群 TiDB 的配置。 + + ``` + [tidb] + # 目标集群的信息。tidb-server 的地址,填一个即可 + host = "172.16.31.1" + port = 4000 + user = "root" + password = "" + ``` + +其它配置参考 [TiDB Lightning 配置](/tidb-lightning/tidb-lightning-configuration.md)。 + +## 第 3 步:开启 TiDB Lightning 进行数据导入 + +运行 TiDB Lightning。如果直接在命令行中用 `nohup` 启动程序,可能会因为 SIGHUP 信号而退出,建议把 `nohup` 放到脚本里面,如: + +``` +# !/bin/bash +nohup ./tidb-lightning -config tidb-lightning.toml > nohup.out & +``` + +导入开始后,可以采用以下两种方式查看进度: + +- 通过 `grep` 日志关键字 `progress` 查看进度,默认 5 分钟更新一次。 +- 通过监控面板查看进度,具体参见 [TiDB-Lightning 监控](/tidb-lightning/monitor-tidb-lightning.md)。 diff --git a/migration-overview.md b/migration-overview.md new file mode 100644 index 000000000000..9e7aa0e06068 --- /dev/null +++ b/migration-overview.md @@ -0,0 +1,63 @@ +--- +title: 数据迁移概述 +summary: 本文档介绍支持哪些路径将数据迁移到 TiDB。 +category: reference +aliases: ['/docs-cn/stable/data-migration-route'] +--- + +# 数据迁移概述 + +本文档介绍支持从哪些路径将数据迁移到 TiDB,包括从 MySQL 迁移到 TiDB 和从 CSV/SQL 文件迁移到 TiDB。 + +## 从 MySQL 迁移到 TiDB + +目前推荐使用以下两种方式将 MySQL 数据迁移到 TiDB。 + +- [使用 Mydumper 和 TiDB Lightning 迁移全量数据](#使用-mydumper-和-tidb-lightning-迁移全量数据) +- [使用 DM 迁移数据](#使用-dm-迁移数据) + +### 使用 Mydumper 和 TiDB Lightning 迁移全量数据 + +#### 适合场景 + +适合 MySQL 全量数据的大小大于 1TB 的场景。该方案只能迁移全量数据,如果需要继续同步增量数据,需要再使用 TiDB Data Migration (DM) 创建增量同步任务。 + +#### 迁移方法 + +使用 Mydumper 导出 MySQL 的全量数据,再使用 TiDB Lightning 将全量数据导入到 TiDB,详细信息可参考[从 Mydumper 文件迁移](/migrate-from-mysql-mydumper-files.md) + +### 使用 DM 迁移数据 + +#### 适合场景 + +适合迁移 MySQL 全量数据并同步增量数据的场景,且全量数据的大小小于 1TB。如果全量数据的大小大于 1TB,建议使用 Mydumper 和 TiDB Lightning 导入全量数据后,再使用 DM 同步增量数据。 + +#### 迁移方法 + +DM 支持将 MySQL 全量数据迁移到 TiDB,并同步 MySQL 的增量数据到 TiDB,详细信息可参考[使用 DM 工具从 Amazon Aurora MySQL 迁移](/migrate-from-aurora-mysql-database.md) + +## 从文件迁移到 TiDB + +支持通过 CSV 和 SQL 两种格式文件将数据迁移到 TiDB。 + +### 从 CSV 文件迁移到 TiDB + +#### 适合场景 + +适合将不兼容 MySQL 协议的异构数据库的数据迁移到 TiDB。 + +#### 迁移方法 + +将全量数据导出到 CSV 格式的文件中,将 CSV 文件导入到 TiDB 有以下两种方法: + +- 使用 TiDB Lightning 将 CSV 格式的数据导入到 TiDB + + TiDB Lightning 导入速度快,适合 CSV 文件数据量较大的场景。详细信息可参考[从 CSV 文件迁移至 TiDB](/tidb-lightning/migrate-from-csv-using-tidb-lightning.md)。 + +- 使用 `LOAD DATA` 语句将 CSV 格式的数据导入到 TiDB + + 在 TiDB 中执行 `LOAD DATA` SQL 语句导入 CSV 格式的数据,这种导入方法使用比较方便,但是如果在导入过程中出现错误或者中断,需要人工介入,检查数据的一致性和完整性,因此不建议在生产环境中使用。详细信息可参考 [LOAD DATA](/sql-statements/sql-statement-load-data.md)。 + +### 从 SQL 文件迁移到 TiDB + +该部分内容与[使用 Mydumper 和 TiDB Lightning 迁移全量数据](#使用-mydumper-和-tidb-lightning-迁移全量数据)相同。 diff --git a/minimal-deployment-topology.md b/minimal-deployment-topology.md new file mode 100644 index 000000000000..011ccfc91292 --- /dev/null +++ b/minimal-deployment-topology.md @@ -0,0 +1,29 @@ +--- +title: 最小拓扑架构 +summary: 介绍 TiDB 集群的最小拓扑。 +category: how-to +--- + +# 最小拓扑架构 + +本文档介绍 TiDB 集群最小部署的拓扑架构。 + +## 拓扑信息 + +|实例 | 个数 | 物理机配置 | IP |配置 | +| :-- | :-- | :-- | :-- | :-- | +| TiDB |3 | 16 VCore 32GB * 1 | 10.0.1.1
10.0.1.2
10.0.1.3 | 默认端口
全局目录配置 | +| PD | 3 | 4 VCore 8GB * 1 |10.0.1.4
10.0.1.5
10.0.1.6 | 默认端口
全局目录配置 | +| TiKV | 3 | 16 VCore 32GB 2TB (nvme ssd) * 1 | 10.0.1.7
10.0.1.8
10.0.1.9 | 默认端口
全局目录配置 | +| Monitoring & Grafana | 1 | 4 VCore 8GB * 1 500GB (ssd) | 10.0.1.11 | 默认端口
全局目录配置 | + +### 拓扑模版 + +[简单最小配置模板](https://github.com/pingcap/docs-cn/blob/release-4.0/config-templates/simple-mini.yaml) + +[详细最小配置模板](https://github.com/pingcap/docs-cn/blob/release-4.0/config-templates/complex-mini.yaml) + +> **注意:** +> +> - 无需手动创建配置文件中的 `tidb` 用户,TiUP cluster 组件会在目标主机上自动创建该用户。可以自定义用户,也可以和中控机的用户保持一致。 +> - 如果部署目录配置为相对路径,会部署在用户家目录下。 diff --git a/multi-data-centers-in-one-city-deployment.md b/multi-data-centers-in-one-city-deployment.md new file mode 100644 index 000000000000..04b6919113f3 --- /dev/null +++ b/multi-data-centers-in-one-city-deployment.md @@ -0,0 +1,132 @@ +--- +title: 同城多数据中心部署 TiDB +summary: 本文档介绍同城多数据中心部署 TiDB 方案。 +category: tutorial +aliases: ['/docs-cn/stable/how-to/deploy/geographic-redundancy/overview/','/docs-cn/stable/geo-redundancy-deployment/'] +--- + +# 同城多数据中心部署 TiDB + +作为 NewSQL 数据库,TiDB 兼顾了传统关系型数据库的优秀特性、NoSQL 数据库可扩展性以及跨数据中心场景下的高可用。本文档旨在介绍同城多数据中心部署 TiDB 方案。 + +## 了解 Raft 协议 + +Raft 是一种分布式一致性算法,在 TiDB 集群的多种组件中,PD 和 TiKV 都通过 Raft 实现了数据的容灾。Raft 的灾难恢复能力通过如下机制实现: + +- Raft 成员的本质是日志复制和状态机。Raft 成员之间通过复制日志来实现数据同步;Raft 成员在不同条件下切换自己的成员状态,其目标是选出 leader 以提供对外服务。 +- Raft 是一个表决系统,它遵循多数派协议,在一个 Raft Group 中,某成员获得大多数投票,它的成员状态就会转变为 leader。也就是说,当一个 Raft Group 还保有大多数节点 (majority) 时,它就能够选出 leader 以提供对外服务。 + +遵循 Raft 可靠性的特点,放到现实场景中: + +- 想克服任意 1 台服务器 (host) 的故障,应至少提供 3 台服务器。 +- 想克服任意 1 个机柜 (rack) 的故障,应至少提供 3 个机柜。 +- 想克服任意 1 个数据中心(dc,又称机房)的故障,应至少提供 3 个数据中心。 +- 想应对任意 1 个城市的灾难场景,应至少规划 3 个城市用于部署。 + +可见,原生 Raft 协议对于偶数副本的支持并不是很友好,考虑跨城网络延迟影响,或许同城三数据中心是最适合部署 Raft 的高可用及容灾方案。 + +## 同城三数据中心方案 + +同城三数据中心方案,即同城存有三个机房部署 TiDB 集群,同城三数据中心间的数据同步通过集群自身内部(Raft 协议)完成。同城三数据中心可同时对外进行读写服务,任意中心发生故障不影响数据一致性。 + +### 简易架构图 + +集群 TiDB、TiKV 和 PD 组件分别分布在 3 个不同的数据中心,这是最常规且高可用性最高的方案。 + +![三中心部署](/media/deploy-3dc.png) + +**优点:** + +- 所有数据的副本分布在三个数据中心,具备高可用和容灾能力 +- 任何一个数据中心失效后,不会产生任何数据丢失 (RPO = 0) +- 任何一个数据中心失效后,其他两个数据中心会自动发起 leader election,并在合理长的时间内(通常情况 20s 以内)自动恢复服务 (RTO <= 20s) + +![三中心部署容灾](/media/deploy-3dc-dr.png) + +**缺点:** + +性能受网络延迟影响。具体影响如下: + +- 对于写入的场景,所有写入的数据需要同步复制到至少 2 个数据中心,由于 TiDB 写入过程使用两阶段提交,故写入延迟至少需要 2 倍数据中心间的延迟。 +- 对于读请求来说,如果数据 leader 与发起读取的 TiDB 节点不在同一个数据中心,也会受网络延迟影响。 +- TiDB 中的每个事务都需要向 PD leader 获取 TSO,当 TiDB 与 PD leader 不在同一个数据中心时,它上面运行的事务也会因此受网络延迟影响,每个有写入的事务会获取两次 TSO。 + +### 架构优化图 + +如果不需要每个数据中心同时对外提供服务,可以将业务流量全部派发到一个数据中心,并通过调度策略把 Region leader 和 PD leader 都迁移到同一个数据中心。这样一来,不管是从 PD 获取 TSO,还是读取 Region,都不会受数据中心间网络的影响。当该数据中心失效后,PD leader 和 Region leader 会自动在其它数据中心选出,只需要把业务流量转移至其他存活的数据中心即可。 + +![三中心部署读性能优化](/media/deploy-3dc-optimize.png) + +**优点:** + +集群 TSO 获取能力以及读取性能有所提升。具体调度策略设置模板参照如下: + +```shell +-- 其他机房统一驱逐 leader 到业务流量机房 +config set label-property reject-leader LabelName labelValue + +-- 迁移 PD leader 并设置优先级 +member leader transfer pdName1 +member leader_priority pdName1 5 +member leader_priority pdName2 4 +member leader_priority pdName3 3 +``` + +**缺点:** + +- 写入场景仍受数据中心网络延迟影响,这是因为遵循 Raft 多数派协议,所有写入的数据需要同步复制到至少 2 个数据中心 +- TiDB Server 数据中心级别单点 +- 业务流量纯走单数据中心,性能受限于单数据中心网络带宽压力 +- TSO 获取能力以及读取性能受限于业务流量数据中心集群 PD、TiKV 组件是否正常,否则仍受跨数据中心网络交互影响 + +### 样例部署图 + +#### 样例拓扑架构 + +下面假设某城存有 IDC1、IDC2、IDC3 三机房,机房 IDC 中存有两套机架,每个机架存有三台服务器,不考虑混布以及单台机器多实例部署下,同城三数据中心架构集群(3 副本)部署参考如下: + +![同城三数据中心集群部署](/media/multi-data-centers-in-one-city-deployment-sample.png) + +#### TiKV Labels 简介 + +TiKV 是一个 Multi-Raft 系统,其数据按 Region(默认 96M)切分,每个 Region 的 3 个副本构成了一个 Raft Group。假设一个 3 副本 TiDB 集群,由于 Region 的副本数与 TiKV 实例数量无关,则一个 Region 的 3 个副本只会被调度到其中 3 个 TiKV 实例上,也就是说即使集群扩容 N 个 TiKV 实例,其本质仍是一个 3 副本集群。 + +由于 3 副本的 Raft Group 只能容忍 1 副本故障,当集群被扩容到 N 个 TiKV 实例时,这个集群依然只能容忍一个 TiKV 实例的故障。2 个 TiKV 实例的故障可能会导致某些 Region 丢失多个副本,整个集群的数据也不再完整,访问到这些 Region 上的数据的 SQL 请求将会失败。而 N 个 TiKV 实例中同时有两个发生故障的概率是远远高于 3 个 TiKV 中同时有两个发生故障的概率的,也就是说 Multi-Raft 系统集群扩容 TiKV 实例越多,其可用性是逐渐降低的。 + +正因为 Multi-Raft TiKV 系统局限性, Labels 标签应运而出,其主要用于描述 TiKV 的位置信息。Label 信息随着部署或滚动更新操作刷新到 TiKV 的启动配置文件中,启动后的 TiKV 会将自己最新的 Label 信息上报给 PD,PD 根据用户登记的 Label 名称(也就是 Label 元信息),结合 TiKV 的拓扑进行 Region 副本的最优调度,从而提高系统可用性。 + +#### TiKV Labels 样例规划 + +针对 TiKV Labels 标签,你需要根据已有的物理资源、容灾能力容忍度等方面进行设计与规划,进而提升系统的可用性和容灾能力。并根据已规划的拓扑架构,配置相关 tidb-ansible inventory.ini 文件(此处省略其他非重点项): + +```ini +[tikv_servers] +TiKV-30 ansible_host=10.63.10.30 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z1,dc=d1,rack=r1,host=30" +TiKV-31 ansible_host=10.63.10.31 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z1,dc=d1,rack=r1,host=31" +TiKV-32 ansible_host=10.63.10.32 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z1,dc=d1,rack=r2,host=30" +TiKV-33 ansible_host=10.63.10.33 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z1,dc=d1,rack=r2,host=30" + +TiKV-34 ansible_host=10.63.10.34 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z2,dc=d1,rack=r1,host=34" +TiKV-35 ansible_host=10.63.10.35 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z2,dc=d1,rack=r1,host=35" +TiKV-36 ansible_host=10.63.10.36 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z2,dc=d1,rack=r2,host=36" +TiKV-37 ansible_host=10.63.10.36 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z2,dc=d1,rack=r2,host=37" + +TiKV-38 ansible_host=10.63.10.38 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z3,dc=d1,rack=r1,host=38" +TiKV-39 ansible_host=10.63.10.39 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z3,dc=d1,rack=r1,host=39" +TiKV-40 ansible_host=10.63.10.40 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z3,dc=d1,rack=r2,host=40" +TiKV-41 ansible_host=10.63.10.41 deploy_dir=/data/tidb_cluster/tikv tikv_port=20170 tikv_status_port=20180 labels="zone=z3,dc=d1,rack=r2,host=41" + +## Group variables +[pd_servers:vars] +location_labels = ["zone","dc","rack","host"] +``` + +本例中,zone 表示逻辑可用区层级,用于控制副本的隔离(当前集群 3 副本)。 + +不直接采用 dc,rack,host 三层 Label 结构的原因是考虑到将来可能发生 dc(数据中心)的扩容,假设新扩容的 dc 编号是 d2,d3,d4,则只需在对应可用区下扩容 dc;rack 扩容只需在对应 dc 下扩容即可。 + +如果直接采用 dc,rack,host 三层 Label 结构,那么扩容 dc 操作可能需重打 Label,TiKV 数据整体需要 Rebalance。 + +### 高可用和容灾分析 + +同城多数据中心方案提供的保障是,任意一个数据中心故障时,集群能自动恢复服务,不需要人工介入,并能保证数据一致性。注意,各种调度策略都是用于帮助性能优化的,当发生故障时,调度机制总是第一优先考虑可用性而不是性能。 diff --git a/mydumper-overview.md b/mydumper-overview.md new file mode 100644 index 000000000000..0162fe6787a2 --- /dev/null +++ b/mydumper-overview.md @@ -0,0 +1,191 @@ +--- +title: Mydumper 使用文档 +summary: 使用 Mydumper 从 TiDB 导出数据。 +category: reference +aliases: ['/docs-cn/stable/reference/tools/mydumper/'] +--- + +# Mydumper 使用文档 + +## Mydumper 简介 + +[Mydumper](https://github.com/pingcap/mydumper) 是一个 fork 项目,可以用于对 **MySQL** 或者 **TiDB** 进行逻辑备份,并针对 TiDB 的特性进行了优化。 + +Mydumper 包含在 tidb-enterprise-tools 安装包中,可[在此下载](/download-ecosystem-tools.md)。 + +### 相比于普通的 Mydumper,此工具有哪些改进之处? + ++ 对于 TiDB 可以设置 [tidb_snapshot](/read-historical-data.md#操作流程) 的值指定备份数据的时间点,从而保证备份的一致性,而不是通过 `FLUSH TABLES WITH READ LOCK` 来保证备份一致性。 + ++ 使用 TiDB 的隐藏列 `_tidb_rowid` 优化了单表内数据的并发导出性能。 + +## 基本用法 + +### 新添参数 + +- `-z` 或 `--tidb-snapshot`:设置 `tidb_snapshot` 用于备份。默认值为当前 TSO(`SHOW MASTER STATUS` 输出的 `Position` 字段)。此参数可设为 TSO 或有效的 `datetime` 时间,例如:`-z "2016-10-08 16:45:26"`。 + +### 需要的权限 + +- SELECT +- RELOAD +- LOCK TABLES +- REPLICATION CLIENT + +### 使用举例 + +执行如下命令从 TiDB 备份数据,需要根据实际情况添加命令行参数: + +{{< copyable "shell-regular" >}} + +```bash +./bin/mydumper -h 127.0.0.1 -u root -P 4000 +``` + +## 表内并发 Dump + +### 原理 + +Mydumper 首先计算 `min(_tidb_rowid)` 和 `max(_tidb_rowid)`,然后按照 `-r` 设定的值对表划分 chunks,将 chunks 分配到不同线程并发导出。 + +### 并发 Dump 相关参数 + +- `-t` 或 `--threads`:并发线程数,默认值为 `4`。 +- `-r` 或 `--rows`:每个 chunks 包含的最大行数。设置该值后,Mydumper 将会忽略 `--chunk-filesize` 值。 + +### 示例 + +以下是一条完整的 Mydumper 命令: + +{{< copyable "shell-regular" >}} + +```bash +./bin/mydumper -h 127.0.0.1 -u root -P 4000 -r 10000 -t 4 +``` + +### 支持 `_tidb_rowid` 索引的 TiDB 版本 + +由于表内并发使用 TiDB 的隐藏列 `_tidb_rowid`,数据库需要支持 `_tidb_rowid` 索引才能发挥并发导出的优势。 + +以下 TiDB 版本支持 `_tidb_rowid` 索引: + +- v2.1.3 及以上 +- v3.0 及以上,包括 v3.1 及未来版本 + +### 性能评估 + +在 Dump 操作前需要进行性能评估。由于并发 Scan 操作对 TiDB、TiKV 集群都会产生一定压力,所以需要评估与测试 Dump 操作对数据库集群和业务的影响。 + +## FAQ + +### 如何判断使用的 Mydumper 是否为 PingCAP 优化的版本? + +执行如下命令: + +{{< copyable "shell-regular" >}} + +```bash +./bin/mydumper -V +``` + +如果输出结果中包含 `githash`(如下列示例输出中的 `d3e6fec8b069daee772d0dbaa47579f67a5947e7`),则使用的 Mydumper 为 PingCAP 优化的版本。 + +``` +mydumper 0.9.5 (d3e6fec8b069daee772d0dbaa47579f67a5947e7), built against MySQL 5.7.24 +``` + +### 使用 Loader 恢复 Mydumper 备份出来的数据时报错 "invalid mydumper files for there are no `-schema-create.sql` files found",应该如何解决? + +检查使用 Mydumper 备份数据时是否使用了 `-T` 或者 `--tables-list` 配置,如果使用了这些配置,Mydumper 就不会生成包含建库 SQL 的文件。 + +**解决方法**:在 Mydumper 备份数据目录下创建文件 `{schema-name}-schema-create.sql`,在文件中写入 "CREATE DATABASE `{schema-name}`",再运行 Loader 即可。 + +### 为什么使用 Mydumper 导出来的 TIMESTAMP 类型的数据和数据库中的数据不一致? + +检查一下运行 Mydumper 的服务器的时区与数据库的时区是否一致,Mydumper 会根据运行所在服务器的时区对 TIMESTAMP 类型的数据进行转化,可以给 Mydumper 加上 `--skip-tz-utc` 参数禁止这种转化。 + +### 如何配置 Mydumper 的参数 `-F, --chunk-filesize`? + +Mydumper 在备份时会根据这个参数的值把每个表的数据划分成多个 chunk,每个 chunk 保存到一个文件中,大小约为 `chunk-filesize`。根据这个参数把数据切分到多个文件中,这样就可以利用 Loader/TiDB Lightning 的并行处理逻辑提高导入速度。如果后续使用 Loader 对备份文件进行恢复,建议把该参数的值设置为 `64`(单位 MB);如果使用 TiDB Lightning 恢复,则建议设置为 `256`(单位 MB)。 + +### 如何配置 Mydumper 的参数 `-s --statement-size`? + +Mydumper 使用该参数控制 `Insert Statement` 的大小,默认值为 `10000000`(约 1 MB)。使用该参数来尽量避免在恢复数据时报以下错误: + +```log +packet for query is too large. Try adjusting the 'max_allowed_packet' variable +``` + +默认值在绝大部分情况下都可以满足需求,但是**如果表为宽表,单行数据的大小可能超过 statement-size 的限制,Mydumper 会报如下的 Warning**: + +```log +Row bigger than statement_size for xxx +``` + +此时恢复数据时仍然会报 `packet for query is too large` 的错误日志,这个时候需要修改以下两个配置(以设置为 `128M` 为例): + +* 在 TiDB Server 执行 `set @@global.max_allowed_packet=134217728`(`134217728` = `128M`)。 +* 根据实际情况为 Loader 的配置文件或者 DM task 配置文件中的 db 配置增加类似 `max-allowed-packet=128M` 的语句,然后重启进程或者任务。 + +### 如何设置 Mydumper 的参数 `-l, --long-query-guard`? + +把该参数设置为预估备份需要消耗的时间,如果 Mydumper 运行时间超过该参数的值,就会报错退出。推荐初次备份设置为 `7200`(单位:秒),之后可根据具体备份时间进行调整。 + +### 如何设置 Mydumper 的参数 `--tidb-force-priority`? + +仅当备份 TiDB 的数据时才可以设置该参数,值可以为 `LOW_PRIORITY`,`DELAYED` 或者 `HIGH_PRIORITY`。如果不希望数据备份对线上业务造成影响,推荐将该参数设置为 `LOW_PRIORITY`;如果备份的优先级更高,则可以设置为 `HIGH_PRIORITY`。 + +### Mydumper 备份 TiDB 数据报错 "GC life time is shorter than transaction duration" 应该怎么解决? + +Mydumper 备份 TiDB 数据时为了保证数据的一致性使用了 TiDB 的 snapshot 特性,如果备份过程中 snapshot 对应的历史数据被 TiDB GC 处理了,则会报该错误。解决步骤如下: + +1. 在备份前,使用 MySQL 客户端查询 TiDB 集群的 `tikv_gc_life_time` 的值,并将其调整为一个合适的值: + + {{< copyable "sql" >}} + + ```sql + SELECT * FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'; + ``` + + ``` + +-----------------------+------------------------------------------------------------------------------------------------+ + | VARIABLE_NAME | VARIABLE_VALUE | + +-----------------------+------------------------------------------------------------------------------------------------+ + | tikv_gc_life_time | 10m0s | + +-----------------------+------------------------------------------------------------------------------------------------+ + 1 rows in set (0.02 sec) + ``` + + {{< copyable "sql" >}} + + ```sql + update mysql.tidb set VARIABLE_VALUE = '720h' where VARIABLE_NAME = 'tikv_gc_life_time'; + ``` + +2. 备份完成后,将 `tikv_gc_life_time` 调整为原来的值: + + {{< copyable "sql" >}} + + ```sql + update mysql.tidb set VARIABLE_VALUE = '10m0s' where VARIABLE_NAME = 'tikv_gc_life_time'; + ``` + +### Mydumper 的参数 `--tidb-rowid` 是否需要配置? + +如果设置该参数为 true,则导出的数据中会包含 TiDB 的隐藏列的数据。将数据恢复到 TiDB 的时候使用隐藏列会有数据不一致的风险,目前不推荐使用该参数。 + +### Mydumper 报错 "Segmentation fault" 怎么解决? + +该 bug 已修复。如果仍然报错,可尝试升级到最新版本。 + +### Mydumper 报错 "Error dumping table ({schema}.{table}) data: line ...... (total length ...)" 怎么解决? + +Mydumper 解析 SQL 时报错,可尝试使用最新版本。如果仍然报错,可以提 issue 到 [mydumper/issues](https://github.com/pingcap/mydumper/issues)。 + +### Mydumper 报错 "Failed to set tidb_snapshot: parsing time \"20190901-10:15:00 +0800\" as \"20190901-10:15:00 +0700 MST\": cannot parse \"\" as \"MST\"" 如何解决? + +检查 TiDB 的版本是否低于 v2.1.11。如果是的话,需要升级 TiDB 到 v2.1.11 或以上版本。 + +### 未来是否计划让 PingCAP 对 Mydumper 的改动合并到上游? + +是的,PingCAP 团队计划将对 Mydumper 的改动合并到上游。参见 [PR #155](https://github.com/maxbube/mydumper/pull/155)。 diff --git a/mysql-compatibility.md b/mysql-compatibility.md new file mode 100644 index 000000000000..6db28a34767a --- /dev/null +++ b/mysql-compatibility.md @@ -0,0 +1,208 @@ +--- +title: 与 MySQL 兼容性对比 +summary: 本文对 TiDB 和 MySQL 二者之间从语法和功能特性上做出详细的对比。 +category: reference +aliases: ['/docs-cn/stable/reference/mysql-compatibility/'] +--- + +# 与 MySQL 兼容性对比概览 + +- TiDB 100% 兼容 MySQL5.7 协议、MySQL5.7 常用的功能及语法,MySQL5.7 生态中系统的工具(PHPMyAdmin, Navicat, MySQL Workbench、mysqldump、Mydumper/myloader)、客户端等均用于 TiDB。 + +- TiDB 是一款分布式数据库, MySQL5.7 中的部分特性由于工程实现难较大,投入产出比较低等多种原因在 TiDB 未能实现或者仅兼容语法但功能并没有实现,因此使用过程中请特别注意。例如:`CREATE TABLE` 语句中 `ENGINE`,仅兼容语法功能并没有实现,因此 TiDB 中没有 `ENGINE` 这类的概念。 + +> **注意:** +> +> 本页内容仅涉及 MySQL 与 TiDB 的总体差异。关于[安全特性](/security-compatibility-with-mysql.md)、[悲观事务模型](/pessimistic-transaction.md#和-mysql-innodb-的差异) 相关的兼容信息请查看各自具体页面。 + +## 不支持的功能特性 + +* 存储过程与函数 +* 触发器 +* 事件 +* 自定义函数 +* 外键约束 +* 全文/空间函数与索引 +* 非 `ascii`/`latin1`/`binary`/`utf8`/`utf8mb4` 的字符集 +* SYS schema +* MySQL 追踪优化器 +* XML 函数 +* X Protocol +* Savepoints +* 列级权限 +* `XA` 语法(TiDB 内部使用两阶段提交,但并没有通过 SQL 接口公开) +* `CREATE TABLE tblName AS SELECT stmt` 语法 +* `CREATE TEMPORARY TABLE` 语法 +* `CHECK TABLE` 语法 +* `CHECKSUM TABLE` 语法 +* `SELECT INTO FILE` 语法 + +## 与 MySQL 有差异的特性详细说明 + +### 自增 ID + +- TiDB 的自增列仅保证自增且唯一、但不保证自动分配的值的连续性,建议不要将缺省值和自定义值混用,若混用可能会收 `Duplicated Error` 的错误信息。 + +- TiDB 在工程实现上会在每一个 tidb-server 实例上缓存一段 ID 的值用于给表的自增列分配值,缓存 ID 的个数由表的 `AUTO_ID_CACHE` 确定,默认值:30000,请特别注意:自增列和`_tidb_rowid`都会消耗缓存的 ID,如果 `INSERT` 语句中所要求的连续的 ID 个数大于 `AUTO_ID_CACHE` 的值时系统会自动调整 `AUTO_ID_CACHE` 的值以确保该语句能正常执行。 + +- TiDB 可通过 `tidb_allow_remove_auto_inc` 系统变量开启或者关闭删除列的 `AUTO_INCREMENT` 属性,删除列属性的语法是:`alter table modify` 或 `alter table change` 。 + +> **注意:** +> +> * `tidb_allow_remove_auto_inc` 要求版本号 >= v2.1.18 或者 >= v3.0.4。 +> * 表的 `AUTO_ID_CACHE` 属性要求版本号 >= v3.0.14 或者 >= v3.1.2 或者 >= v4.0.rc-2。 +> * 若创建表时没有指定主键时, TiDB 会使用 `_tidb_rowid` 来标识行,该数值的分配会和自增列(如果存在的话)共用一个分配器。如果指定了自增列为主键,则 TiDB 会用该列来标识行。因此会有以下的示例情况: + +```sql +mysql> create table t(id int unique key AUTO_INCREMENT); +Query OK, 0 rows affected (0.05 sec) + +mysql> insert into t values(),(),(); +Query OK, 3 rows affected (0.00 sec) +Records: 3 Duplicates: 0 Warnings: 0 + +mysql> select _tidb_rowid, id from t; ++-------------+------+ +| _tidb_rowid | id | ++-------------+------+ +| 4 | 1 | +| 5 | 2 | +| 6 | 3 | ++-------------+------+ +3 rows in set (0.01 sec) +``` + +### Performance schema + +- TiDB 主要使用 Prometheus 和 Grafana 来存储及查询相关的性能监控指标,故 Performance schema 部分表是空表。 + +### 查询计划 + +- `EXPLAIN`/`EXPLAIN FOR` 输出格式、内容、权限设置与 MySQL 有比较大的差别,参见[理解 TiDB 执行计划](/query-execution-plan.md)。 + +### 内建函数 + +- 支持常用的 MySQL 内建函数,有部分函数并未支持,参考 [SQL 语法文档](https://pingcap.github.io/sqlgram/#functioncallkeyword)。 + +### DDL 的限制 + +- Add Index + + 同一条 SQL 语句不支持创建多个索引。 + + 仅在语法在支持创建不同类型的索引 (HASH/BTREE/RTREE),功能未实现。 + +- Add Column + + 不支持设置`PRIMARY KEY` 及 `UNIQUE KEY`,不支持设置 `AUTO_INCREMENT` 属性。可能输出的错误信息:`unsupported add column '%s' constraint PRIMARY/UNIQUE/AUTO_INCREMENT KEY` + +- Drop Column + + 不支持删除主键列及索引列,可能输出的错误信息:`Unsupported drop integer primary key/column a with index covered`。 + +- Drop Primary Key + + 仅支持删除建表时启用了 `alter-primary-key` 配置项的表的主键,可能输出的错误信息: `Unsupported drop primary key when alter-primary-key is false`。 + +- Order By 忽略所有列排序相关的选项。 + +- Change/Modify Column + + 不支持有损变更,比如从 `BIGINT` 变为 `INTEGER`,或者从 `VARCHAR(255)` 变为 `VARCHAR(10)`,可能输出的错误信息:`length %d is less than origin %d` + + 不支持修改 `DECIMAL` 类型的精度,可能输出的错误信息:`can't change decimal column precision`。 + + 不支持更改 `UNSIGNED` 属性,可能输出的错误信息:`can't change unsigned integer to signed or vice versa`。 + + 只支持将 `CHARACTER SET` 属性从 `utf8` 更改为 `utf8mb4` + +- `LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}` + + 仅在语法上支持,功能未实现,故所有的 DDL 都不会锁表。 + +- `ALGORITHM [=] {DEFAULT|INSTANT|INPLACE|COPY}` + + 支持 `ALGORITHM=INSTANT` 和 `ALGORITHM=INPLACE` 语法,但行为与 MySQL 有所不同,MySQL 中的一些 `INPLACE` 操作在 TiDB 中的 是`INSTANT` 操作。 + + 仅在语法上支持 `ALGORITHM=COPY`,功能未实现,会返回警告信息。 + +- 单条 `ALTER TABLE` 语句中无法完成多个操作。例如:不能用一条语句来添加多个列或多个索引。可能输出的错误信息:`Unsupported multi schema change`。 + +- Table Option 仅支持`AUTO_INCREMENT`、`CHARACTER SET`、`COLLATE`、`COMMENT`,不支持以下语法: + + `WITH/WITHOUT VALIDATION` + + `SECONDARY_LOAD/SECONDARY_UNLOAD` + + `CHECK/DROP CHECK` + + `STATS_AUTO_RECALC/STATS_SAMPLE_PAGES` + + `SECONDARY_ENGINE` + + `ENCRYPTION` + +- Table Partition 分区类型支持 Hash、Range;支持 Add/Drop/Truncate/Coalese;忽略其他分区操作,可能错误信息:`Warning: Unsupported partition type, treat as normal table`,不支持以下语法: + + `PARTITION BY LIST` + + `PARTITION BY KEY` + + `SUBPARTITION` + + `{CHECK|EXCHANGE|TRUNCATE|OPTIMIZE|REPAIR|IMPORT|DISCARD|REBUILD|REORGANIZE} PARTITION` + +### `ANALYZE TABLE` + +- [`ANALYZE TABLE`](/statistics.md#手动收集) 语句会完全重构表的统计数据,语句执行过程较长,但在 MySQL/InnoDB 中,它是一个轻量级语句,执行过程较短。 + +### 视图 + +- 不支持 `UPDATE`、`INSERT`、`DELETE` 等写入操作。 + +### 存储引擎 + +- 仅在语法上兼容创建表时指定存储引擎,实际上 TiDB 会将元信息统一描述为 InnoDB 存储引擎。TiDB 支持类似 MySQL 的存储引擎抽象,但需要在系统启动时通过[`--store`](/command-line-flags-for-tidb-configuration.md#store) 配置项来指定存储引擎。 + +### SQL 模式 + +- 不支持兼容模式,例如: `ORACLE` 和 `POSTGRESQL`,MySQL 5.7 已弃用兼容模式,MySQL 8.0 已移除兼容模式。 + +- `ONLY_FULL_GROUP_BY` 与 MySQL 5.7 相比有细微的[语义差别](/functions-and-operators/aggregate-group-by-functions.md#与-mysql-的区别)。 + +- `NO_DIR_IN_CREATE` 和 `NO_ENGINE_SUBSTITUTION` MySQL 用于解决兼容问题,并不适用于 TiDB。 + +### 默认设置 + +- 字符集: + + TiDB 默认:`utf8mb4`。 + + MySQL 5.7 默认:`latin1`。 + + MySQL 8.0 默认: `utf8mb4`。 + +- 排序规则: + + TiDB 中 `utf8mb4` 字符集默认: `utf8mb4_bin`。 + + MySQL 5.7 中 `utf8mb4` 字符集默认: `utf8mb4_general_ci`。 + + MySQL 8.0 中 `utf8mb4` 字符集默认: `utf8mb4_0900_ai_ci`。 + +- `foreign_key_checks`: + + TiDB 默认: `OFF`,且仅支持设置该值为 `OFF`。 + + MySQL 5.7 默认: `ON`。 + +- SQL mode: + + TiDB 默认: `ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION` + + MySQL 5.7 默认 与 TiDB 相同。 + + MySQL 8.0 默认 `ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION`。 + +- `lower_case_table_names`: + + TiDB 默认: 2,且仅支持设置该值为 2。 + + MySQL 默认如下: + - Linux 系统中该值为 0 + - Windows 系统中该值为 1 + - macOS 系统中该值为 2 + +- `explicit_defaults_for_timestamp`: + + TiDB 默认: `ON`,且仅支持设置该值为 `ON`。 + + MySQL 5.7 默认:`OFF`。 + + MySQL 8.0 默认:`ON`。 + +### 日期时间处理的区别 + +#### 时区 + +- TiDB 采用系统当前安装的所有时区规则进行计算(一般为 `tzdata` 包), 不需要导入时区表数据就能使用所有时区名称,无法通过导入时区表数据的形式修改计算规则。 + +- MySQL 默认使用本地时区,依赖于系统内置的当前的时区规则(例如什么时候开始夏令时等)进行计算;且在未[导入时区表数据](https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html#time-zone-installation)的情况下不能通过时区名称来指定时区。 + +#### 零月和零日 + +- 与 MySQL 一样,TiDB 默认启用了 `NO_ZERO_DATE` 和 `NO_ZERO_IN_DATE` 模式,但是 TiDB 与 MySQL 在处理这两个 SQL 模式有以下不同: + - TiDB 在非严格模式下启用以上两个 SQL 模式,插入零月/零日/零日期不会给出警告,MySQL 则会给出对应的警告。 + - TiDB 在严格模式下,启用了 `NO_ZERO_DATE` ,仍然能够插入零日期;如果启用了 `NO_ZERO_IN_DATE` 则无法插入零月/零日日期。MySQL 在严格模式下则都无法插入两种类型的日期。 + +### 类型系统 + ++ 不支持 FLOAT4/FLOAT8。 + ++ 不支持 FIXED (alias for DECIMAL)。 + ++ 不支持 SERIAL (alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE)。 + ++ 不支持 SQL_TSI_* (包括 SQL_TSI_YEAR、SQL_TSI_MONTH、SQL_TSI_WEEK、SQL_TSI_DAY、SQL_TSI_HOUR、SQL_TSI_MINUTE 和 SQL_TSI_SECOND)。 diff --git a/offline-deployment-using-ansible.md b/offline-deployment-using-ansible.md new file mode 100644 index 000000000000..78f5f3e4ab50 --- /dev/null +++ b/offline-deployment-using-ansible.md @@ -0,0 +1,160 @@ +--- +title: 离线 TiDB Ansible 部署方案 +category: how-to +aliases: ['/docs-cn/stable/how-to/deploy/orchestrated/offline-ansible/'] +--- + +# 离线 TiDB Ansible 部署方案 + +## 准备机器 + +1. 下载机一台 + + - 该机器需开放外网访问,用于下载 TiDB Ansible、TiDB 及相关软件安装包。 + - 推荐安装 CentOS 7.3 及以上版本 Linux 操作系统。 + +2. 部署目标机器若干及部署中控机一台 + + - 系统要求及配置参考[准备机器](/online-deployment-using-ansible.md#准备机器)。 + - 可以无法访问外网。 + +## 在中控机上安装系统依赖包 + +1. 在下载机上下载[系统依赖离线安装包](https://download.pingcap.org/ansible-system-rpms.el7.tar.gz),然后上传至中控机。该离线包仅支持 CentOS 7 系统,包含 `pip` 及 `sshpass`。 + +2. 在中控机上安装系统依赖包: + + {{< copyable "shell-root" >}} + + ```bash + tar -xzvf ansible-system-rpms.el7.tar.gz && + cd ansible-system-rpms.el7 && + chmod u+x install_ansible_system_rpms.sh && + ./install_ansible_system_rpms.sh + ``` + +3. 安装完成后,可通过 `pip -V` 验证 pip 是否安装成功: + + {{< copyable "shell-root" >}} + + ```bash + pip -V + ``` + + ``` + pip 8.1.2 from /usr/lib/python2.7/site-packages (python 2.7) + ``` + +> **注意:** +> +> 如果你的系统已安装 pip,请确认版本 >= 8.1.2,否则离线安装 TiDB Ansible 及其依赖时,会有兼容问题。 + +## 在中控机上创建 tidb 用户,并生成 ssh key + +参考[在中控机上创建 tidb 用户,并生成 ssh key](/online-deployment-using-ansible.md#第-2-步在中控机上创建-tidb-用户并生成-ssh-key) 即可。 + +## 在中控机器上离线安装 TiDB Ansible 及其依赖 + +以下是 CentOS 7 系统 Ansible 离线安装方式: + +建议使用 Ansible 2.4 至 2.7.11 版本,Ansible 及相关依赖版本记录在 `tidb-ansible/requirements.txt` 文件中。下面步骤以安装 Ansible 2.5 为例。 + +1. 在下载机上下载 [Ansible 2.5 离线安装包](https://download.pingcap.org/ansible-2.5.0-pip.tar.gz),然后上传至中控机。 + +2. 离线安装 TiDB Ansible 及相关依赖: + + {{< copyable "shell-root" >}} + + ```bash + tar -xzvf ansible-2.5.0-pip.tar.gz && + cd ansible-2.5.0-pip/ && + chmod u+x install_ansible.sh && + ./install_ansible.sh + ``` + +3. 安装完成后,可通过 `ansible --version` 查看版本: + + {{< copyable "shell-root" >}} + + ```bash + ansible --version + ``` + + ``` + ansible 2.5.0 + ``` + +## 在下载机上下载 TiDB Ansible 及 TiDB 安装包 + +1. 在下载机上安装 TiDB Ansible: + + 请按以下方式在 CentOS 7 系统的下载机上在线安装 TiDB Ansible。安装完成后,可通过 `ansible --version` 查看版本,请务必确认是 **Ansible 2.5.0** 版本,否则会有兼容问题。 + + {{< copyable "shell-root" >}} + + ```bash + yum install epel-release && + yum install ansible curl && + ansible --version + ``` + + ``` + ansible 2.5.0 + ``` + +2. 下载 tidb-ansible: + + 使用以下命令从 Github [TiDB Ansible 项目](https://github.com/pingcap/tidb-ansible)上下载 TiDB Ansible 相应版本,默认的文件夹名称为 `tidb-ansible`。 + + {{< copyable "shell-regular" >}} + + ```bash + git clone https://github.com/pingcap/tidb-ansible.git + ``` + + > **注意:** + > + > 部署和升级 TiDB 集群需使用对应的 tidb-ansible 版本,通过改 `inventory.ini` 文件中的版本来混用可能会产生一些错误。 + +3. 执行 `local_prepare.yml` playbook,联网下载 TiDB binary 到下载机: + + {{< copyable "shell-regular" >}} + + ```bash + cd tidb-ansible && + ansible-playbook local_prepare.yml + ``` + +4. 将执行完以上命令之后的 `tidb-ansible` 文件夹拷贝到中控机 `/home/tidb` 目录下,文件属主权限需是 `tidb` 用户。 + +## 在中控机上配置部署机器 SSH 互信及 sudo 规则 + +参考[在中控机上配置部署机器 SSH 互信及 sudo 规则](/online-deployment-using-ansible.md#第-5-步在中控机上配置部署机器-ssh-互信及-sudo-规则)即可。 + +## 在部署目标机器上安装 NTP 服务 + +如果你的部署目标机器时间、时区设置一致,已开启 NTP 服务且在正常同步时间,此步骤可忽略,可参考[如何检测 NTP 服务是否正常](/online-deployment-using-ansible.md#如何检测-ntp-服务是否正常)。 + +参考[在部署目标机器上安装 NTP 服务](/online-deployment-using-ansible.md#第-6-步在部署目标机器上安装-ntp-服务)即可。 + +## 在部署目标机器上配置 CPUfreq 调节器模式 + +参考[在部署目标机器上配置 CPUfreq 调节器模式](/online-deployment-using-ansible.md#第-7-步在部署目标机器上配置-cpufreq-调节器模式)即可。 + +## 在部署目标机器上添加数据盘 ext4 文件系统挂载参数 + +参考[在部署目标机器上添加数据盘 ext4 文件系统挂载参数](/online-deployment-using-ansible.md#第-8-步在部署目标机器上添加数据盘-ext4-文件系统挂载参数)即可。 + +## 分配机器资源,编辑 inventory.ini 文件 + +参考[分配机器资源,编辑 inventory.ini 文件](/online-deployment-using-ansible.md#第-9-步编辑-inventoryini-文件分配机器资源)即可。 + +## 部署任务 + +1. `ansible-playbook local_prepare.yml` 该 playbook 不需要再执行。 + +2. 参考[部署任务](/online-deployment-using-ansible.md#第-11-步部署-tidb-集群)即可。 + +## 测试集群 + +参考[测试集群](/online-deployment-using-ansible.md#测试集群)即可。 diff --git a/online-deployment-using-ansible.md b/online-deployment-using-ansible.md new file mode 100644 index 000000000000..67997a99adb1 --- /dev/null +++ b/online-deployment-using-ansible.md @@ -0,0 +1,964 @@ +--- +title: 使用 TiDB Ansible 部署 TiDB 集群 +category: how-to +aliases: ['/docs-cn/stable/how-to/deploy/orchestrated/ansible/'] +--- + +# 使用 TiDB Ansible 部署 TiDB 集群 + +Ansible 是一款自动化运维工具,[TiDB Ansible](https://github.com/pingcap/tidb-ansible) 是 PingCAP 基于 Ansible playbook 功能编写的集群部署工具。本文档介绍如何使用 TiDB Ansible 部署一个完整的 TiDB 集群。 + +本部署工具可以通过配置文件设置集群拓扑,完成以下各项运维工作: + +- 初始化操作系统参数 +- 部署 TiDB 集群(包括 PD、TiDB、TiKV 等组件和监控组件) +- [启动集群](/maintain-tidb-using-ansible.md#启动集群) +- [关闭集群](/maintain-tidb-using-ansible.md#关闭集群) +- [变更组件配置](/upgrade-tidb-using-ansible.md#编辑-tidb-集群组件配置文件) +- [集群扩容缩容](/scale-tidb-using-ansible.md) +- [升级组件版本](/upgrade-tidb-using-ansible.md#滚动升级-tidb-集群组件) +- [集群开启 binlog](/tidb-binlog/tidb-binlog-overview.md) +- [清除集群数据](/maintain-tidb-using-ansible.md#清除集群数据) +- [销毁集群](/maintain-tidb-using-ansible.md#销毁集群) + +> **警告:** +> +> 对于生产环境,推荐[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)。从 TiDB 4.0 版本开始,不再推荐使用 TiDB Ansible 部署 TiDB 集群,但可以使用 TiUP 直接支持之前的 Ansible 集群。 +> +> 如果只是希望测试 TiDB 或体验 TiDB 特性,可参考 [TiDB 快速上手指南](/quick-start-with-tidb.md)或者[使用 Docker Compose 在单机上快速部署 TiDB 集群](/deploy-test-cluster-using-docker-compose.md)。 + +## 准备机器 + +1. 部署目标机器若干 + + - 建议 4 台及以上,TiKV 至少 3 实例,且与 TiDB、PD 模块不位于同一主机,详见[部署建议](/hardware-and-software-requirements.md)。 + - 目前支持在 x86_64 (AMD64) 和 ARM64 两种架构上部署 TiDB 集群。在 AMD64 架构下,建议使用 CentOS 7.3 及以上版本 Linux 操作系统;在 ARM 架构下,建议使用 CentOS 7.6 1810 版本 Linux 操作系统。 + - 机器之间内网互通。 + + > **注意:** + > + > 使用 TiDB Ansible 方式部署时,TiKV 及 PD 节点数据目录所在磁盘请使用 SSD 磁盘,否则无法通过检测。**如果仅验证功能,建议使用 [Docker Compose 部署方案](/deploy-test-cluster-using-docker-compose.md)单机进行测试。** + +2. 部署中控机一台 + + - 中控机可以是部署目标机器中的某一台。 + - 推荐安装 CentOS 7.3 及以上版本 Linux 操作系统(默认包含 Python 2.7)。 + - 该机器需开放外网访问,用于下载 TiDB 及相关软件安装包。 + +## 第 1 步:在中控机上安装系统依赖包 + +以 `root` 用户登录中控机,然后根据操作系统类型执行相应的安装命令。 + +- 如果中控机使用的是 CentOS 7 系统,执行以下命令: + + {{< copyable "shell-root" >}} + + ```bash + yum -y install epel-release git curl sshpass && \ + yum -y install python2-pip + ``` + +- 如果中控机使用的是 Ubuntu 系统,执行以下命令: + + {{< copyable "shell-root" >}} + + ```bash + apt-get -y install git curl sshpass python-pip + ``` + +## 第 2 步:在中控机上创建 `tidb` 用户,并生成 SSH key + +以 `root` 用户登录中控机,执行以下步骤: + +1. 创建 `tidb` 用户。 + + {{< copyable "shell-root" >}} + + ```bash + useradd -m -d /home/tidb tidb + ``` + +2. 设置 `tidb` 用户密码。 + + {{< copyable "shell-root" >}} + + ```bash + passwd tidb + ``` + +3. 配置 `tidb` 用户 sudo 免密码,将 `tidb ALL=(ALL) NOPASSWD: ALL` 添加到文件末尾即可。 + + {{< copyable "shell-root" >}} + + ```bash + visudo + ``` + + ``` + tidb ALL=(ALL) NOPASSWD: ALL + ``` + +4. 生成 SSH key。 + + 执行 `su` 命令,从 `root` 用户切换到 `tidb` 用户下。 + + {{< copyable "shell-root" >}} + + ```bash + su - tidb + ``` + + 创建 `tidb` 用户 SSH key,提示 `Enter passphrase` 时直接回车即可。执行成功后,SSH 私钥文件为 `/home/tidb/.ssh/id_rsa`,SSH 公钥文件为 `/home/tidb/.ssh/id_rsa.pub`。 + + {{< copyable "shell-regular" >}} + + ```bash + ssh-keygen -t rsa + ``` + + ``` + Generating public/private rsa key pair. + Enter file in which to save the key (/home/tidb/.ssh/id_rsa): + Created directory '/home/tidb/.ssh'. + Enter passphrase (empty for no passphrase): + Enter same passphrase again: + Your identification has been saved in /home/tidb/.ssh/id_rsa. + Your public key has been saved in /home/tidb/.ssh/id_rsa.pub. + The key fingerprint is: + SHA256:eIBykszR1KyECA/h0d7PRKz4fhAeli7IrVphhte7/So tidb@172.16.10.49 + The key's randomart image is: + +---[RSA 2048]----+ + |=+o+.o. | + |o=o+o.oo | + | .O.=.= | + | . B.B + | + |o B * B S | + | * + * + | + | o + . | + | o E+ . | + |o ..+o. | + +----[SHA256]-----+ + ``` + +## 第 3 步:在中控机器上下载 TiDB Ansible + +以 `tidb` 用户登录中控机并进入 `/home/tidb` 目录。使用以下命令从 [TiDB Ansible 项目](https://github.com/pingcap/tidb-ansible)上下载 TiDB Ansible 4.0 [相应 TAG 版本](https://github.com/pingcap/tidb-ansible/tags),默认的文件夹名称为 `tidb-ansible`。 + +{{< copyable "shell-regular" >}} + +```bash +git clone -b $tag https://github.com/pingcap/tidb-ansible.git +``` + +> **注意:** +> +> - `$tag` 替换为选定的 TAG 版本的值,例如 `v4.0.0-beta.2`。 +> - 部署和升级 TiDB 集群需使用对应的 tidb-ansible 版本,通过改 `inventory.ini` 文件中的版本来混用可能会产生一些错误。 +> - 请务必按文档操作,将 `tidb-ansible` 下载到 `/home/tidb` 目录下,权限为 `tidb` 用户,不要下载到 `/root` 下,否则会遇到权限问题。 + +## 第 4 步:在中控机器上安装 TiDB Ansible 及其依赖 + +以 `tidb` 用户登录中控机,请务必按以下方式通过 `pip` 安装 TiDB Ansible 及其相关依赖的指定版本,否则会有兼容问题。目前,TiDB Ansible release-4.0 版本兼容 Ansible 2.5 ~ 2.7.11 (2.5 ≤ Ansible ≤ 2.7.11)。 + +1. 在中控机器上安装 TiDB Ansible 及其依赖。 + + {{< copyable "shell-regular" >}} + + ```bash + cd /home/tidb/tidb-ansible && \ + sudo pip install -r ./requirements.txt + ``` + + Ansible 及相关依赖的版本信息记录在 `tidb-ansible/requirements.txt` 文件中。 + +2. 查看 Ansible 的版本。 + + {{< copyable "shell-regular" >}} + + ```bash + ansible --version + ``` + + ``` + ansible 2.7.11 + ``` + +## 第 5 步:在中控机上配置部署机器 SSH 互信及 sudo 规则 + +以 `tidb` 用户登录中控机,然后执行以下步骤: + +1. 将你的部署目标机器 IP 添加到 `hosts.ini` 文件的 `[servers]` 区块下。 + + {{< copyable "shell-regular" >}} + + ```bash + cd /home/tidb/tidb-ansible && \ + vi hosts.ini + ``` + + ```ini + [servers] + 172.16.10.1 + 172.16.10.2 + 172.16.10.3 + 172.16.10.4 + 172.16.10.5 + 172.16.10.6 + + [all:vars] + username = tidb + ntp_server = pool.ntp.org + ``` + +2. 执行以下命令,按提示输入部署目标机器的 `root` 用户密码。 + + {{< copyable "shell-regular" >}} + + ```bash + ansible-playbook -i hosts.ini create_users.yml -u root -k + ``` + + 该步骤将在部署目标机器上创建 `tidb` 用户,并配置 sudo 规则,配置中控机与部署目标机器之间的 SSH 互信。 + +如果要手工配置 SSH 互信及 sudo 免密码,可参考[如何手工配置 ssh 互信及 sudo 免密码](#如何手工配置-ssh-互信及-sudo-免密码)。 + +## 第 6 步:在部署目标机器上安装 NTP 服务 + +> **注意:** +> +> 如果你的部署目标机器时间、时区设置一致,已开启 NTP 服务且在正常同步时间,此步骤可忽略。可参考[如何检测 NTP 服务是否正常](#如何检测-ntp-服务是否正常)。 + +以 `tidb` 用户登录中控机,执行以下命令: + +{{< copyable "shell-regular" >}} + +```bash +cd /home/tidb/tidb-ansible && \ +ansible-playbook -i hosts.ini deploy_ntp.yml -u tidb -b +``` + +该步骤将在部署目标机器上使用系统自带软件源联网安装并启动 NTP 服务,服务使用安装包默认的 NTP server 列表,见配置文件 `/etc/ntp.conf` 中 server 参数。如果使用默认的 NTP server,你的机器需要连接外网。 + +为了让 NTP 尽快开始同步,启动 NTP 服务前,系统会执行 `ntpdate` 命令,与用户在 `hosts.ini` 文件中指定的 `ntp_server` 同步日期与时间。默认的服务器为 `pool.ntp.org`,也可替换为你的 NTP server。 + +## 第 7 步:在部署目标机器上配置 CPUfreq 调节器模式 + +为了让 CPU 发挥最大性能,请将 CPUfreq 调节器模式设置为 `performance` 模式。如需了解 CPUfreq 的更多信息,可查看[使用 CPUFREQ 调控器](https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/power_management_guide/cpufreq_governors#cpufreq_setup)文档。 + +### 查看系统支持的调节器模式 + +执行以下 `cpupower` 命令,可查看系统支持的调节器模式: + +{{< copyable "shell-root" >}} + +```bash +cpupower frequency-info --governors +``` + +``` +analyzing CPU 0: + available cpufreq governors: performance powersave +``` + +> **注意:** +> +> 本例中系统支持设置 `performance` 和 `powersave` 模式。如果返回 `Not Available`,表示当前系统不支持配置 CPUfreq,跳过该步骤即可。 + +{{< copyable "shell-root" >}} + +```bash +cpupower frequency-info --governors +``` + +``` +analyzing CPU 0: + available cpufreq governors: Not Available +``` + +### 查看系统当前的 CPUfreq 调节器模式 + +执行以下 `cpupower` 命令,可查看系统当前的 CPUfreq 调节器模式: + +{{< copyable "shell-root" >}} + +```bash +cpupower frequency-info --policy +``` + +``` +analyzing CPU 0: + current policy: frequency should be within 1.20 GHz and 3.20 GHz. + The governor "powersave" may decide which speed to use + within this range. +``` + +如上述代码所示,本例中的当前配置是 `powersave` 模式。 + +### 修改调节器模式 + +你可以通过以下两种方法来修改调节器模式。本例中,当前调节器模式为 `powersave`,以下命令会将模式变更为 `performance`。 + +- 使用 `cpupower frequency-set --governor` 命令来修改。 + + {{< copyable "shell-root" >}} + + ```bash + cpupower frequency-set --governor performance + ``` + +- 使用以下命令在部署目标机器上批量设置。 + + {{< copyable "shell-regular" >}} + + ```bash + ansible -i hosts.ini all -m shell -a "cpupower frequency-set --governor performance" -u tidb -b + ``` + +## 第 8 步:在部署目标机器上添加数据盘 ext4 文件系统挂载参数 + +使用 `root` 用户登录目标机器,将部署目标机器数据盘格式化成 ext4 文件系统,挂载时添加 `nodelalloc` 和 `noatime` 挂载参数。`nodelalloc` 是必选参数,否则 Ansible 安装时检测无法通过;`noatime` 是可选建议参数。 + +> **注意:** +> +> 如果你的数据盘已经格式化成 ext4 并挂载了磁盘,可先执行 `umount /dev/nvme0n1p1` 命令卸载,从编辑 `/etc/fstab` 文件步骤开始执行,添加挂载参数重新挂载即可。 + +以 `/dev/nvme0n1` 数据盘为例,具体操作步骤如下: + +1. 查看数据盘。 + + {{< copyable "shell-root" >}} + + ```bash + fdisk -l + ``` + + ``` + Disk /dev/nvme0n1: 1000 GB + ``` + +2. 创建分区表。 + + {{< copyable "shell-root" >}} + + ```bash + parted -s -a optimal /dev/nvme0n1 mklabel gpt -- mkpart primary ext4 1 -1 + ``` + + > **注意:** + > + > 使用 `lsblk` 命令查看分区的设备号:对于 nvme 磁盘,生成的分区设备号一般为 `nvme0n1p1`;对于普通磁盘(例如 `/dev/sdb`),生成的的分区设备号一般为 `sdb1`。 + +3. 格式化文件系统。 + + {{< copyable "shell-root" >}} + + ```bash + mkfs.ext4 /dev/nvme0n1p1 + ``` + +4. 查看数据盘分区 UUID。 + + 本例中 `nvme0n1p1` 的 UUID 为 `c51eb23b-195c-4061-92a9-3fad812cc12f`。 + + {{< copyable "shell-root" >}} + + ```bash + lsblk -f + ``` + + ``` + NAME FSTYPE LABEL UUID MOUNTPOINT + sda + ├─sda1 ext4 237b634b-a565-477b-8371-6dff0c41f5ab /boot + ├─sda2 swap f414c5c0-f823-4bb1-8fdf-e531173a72ed + └─sda3 ext4 547909c1-398d-4696-94c6-03e43e317b60 / + sr0 + nvme0n1 + └─nvme0n1p1 ext4 c51eb23b-195c-4061-92a9-3fad812cc12f + ``` + +5. 编辑 `/etc/fstab` 文件,添加 `nodelalloc` 挂载参数。 + + {{< copyable "shell-root" >}} + + ```bash + vi /etc/fstab + ``` + + ``` + UUID=c51eb23b-195c-4061-92a9-3fad812cc12f /data1 ext4 defaults,nodelalloc,noatime 0 2 + ``` + +6. 挂载数据盘。 + + {{< copyable "shell-root" >}} + + ```bash + mkdir /data1 && \ + mount -a + ``` + +7. 执行以下命令,如果文件系统为 ext4,并且挂载参数中包含 `nodelalloc`,则表示已生效。 + + {{< copyable "shell-root" >}} + + ```bash + mount -t ext4 + ``` + + ``` + /dev/nvme0n1p1 on /data1 type ext4 (rw,noatime,nodelalloc,data=ordered) + ``` + +## 第 9 步:编辑 `inventory.ini` 文件,分配机器资源 + +以 `tidb` 用户登录中控机,编辑 `/home/tidb/tidb-ansible/inventory.ini` 文件为 TiDB 集群分配机器资源。一个标准的 TiDB 集群需要 6 台机器:2 个 TiDB 实例,3 个 PD 实例,3 个 TiKV 实例。 + +- 至少需部署 3 个 TiKV 实例。 +- 不要将 TiKV 实例与 TiDB 或 PD 实例混合部署在同一台机器上。 +- 将第一台 TiDB 机器同时用作监控机。 + +> **注意:** +> +> 请使用内网 IP 来部署集群,如果部署目标机器 SSH 端口非默认的 22 端口,需添加 `ansible_port` 变量,如 `TiDB1 ansible_host=172.16.10.1 ansible_port=5555`。 +> +> 如果是 ARM 架构的机器,需要将 `cpu_architecture` 改为 `arm64`。 + +你可以根据实际场景从以下两种集群拓扑中选择一种: + +- [单机单 TiKV 实例集群拓扑](#单机单-tikv-实例集群拓扑) + + 默认情况下,建议在每个 TiKV 节点上仅部署一个 TiKV 实例,以提高性能。但是,如果你的 TiKV 部署机器的 CPU 和内存配置是[部署建议](/hardware-and-software-requirements.md)的两倍或以上,并且一个节点拥有两块 SSD 硬盘或者单块 SSD 硬盘的容量大于 2 TB,则可以考虑部署两实例,但不建议部署两个以上实例。 + +- [单机多 TiKV 实例集群拓扑](#单机多-tikv-实例集群拓扑) + +### 单机单 TiKV 实例集群拓扑 + +| Name | Host IP | Services | +| :---- | :------- | :-------- | +| node1 | 172.16.10.1 | PD1, TiDB1 | +| node2 | 172.16.10.2 | PD2, TiDB2 | +| node3 | 172.16.10.3 | PD3 | +| node4 | 172.16.10.4 | TiKV1 | +| node5 | 172.16.10.5 | TiKV2 | +| node6 | 172.16.10.6 | TiKV3 | + +```ini +[tidb_servers] +172.16.10.1 +172.16.10.2 + +[pd_servers] +172.16.10.1 +172.16.10.2 +172.16.10.3 + +[tikv_servers] +172.16.10.4 +172.16.10.5 +172.16.10.6 + +[monitoring_servers] +172.16.10.1 + +[grafana_servers] +172.16.10.1 + +[monitored_servers] +172.16.10.1 +172.16.10.2 +172.16.10.3 +172.16.10.4 +172.16.10.5 +172.16.10.6 +``` + +### 单机多 TiKV 实例集群拓扑 + +以两实例为例: + +| Name | Host IP | Services | +| :---- | :------- | :-------- | +| node1 | 172.16.10.1 | PD1, TiDB1 | +| node2 | 172.16.10.2 | PD2, TiDB2 | +| node3 | 172.16.10.3 | PD3 | +| node4 | 172.16.10.4 | TiKV1-1, TiKV1-2 | +| node5 | 172.16.10.5 | TiKV2-1, TiKV2-2 | +| node6 | 172.16.10.6 | TiKV3-1, TiKV3-2 | + +```ini +[tidb_servers] +172.16.10.1 +172.16.10.2 + +[pd_servers] +172.16.10.1 +172.16.10.2 +172.16.10.3 + +# 注意:要使用 TiKV 的 labels,必须同时配置 PD 的 location_labels 参数,否则 labels 设置不生效。 + +# 多实例场景需要额外配置 status 端口,示例如下: +[tikv_servers] +TiKV1-1 ansible_host=172.16.10.4 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv1" +TiKV1-2 ansible_host=172.16.10.4 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv1" +TiKV2-1 ansible_host=172.16.10.5 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv2" +TiKV2-2 ansible_host=172.16.10.5 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv2" +TiKV3-1 ansible_host=172.16.10.6 deploy_dir=/data1/deploy tikv_port=20171 tikv_status_port=20181 labels="host=tikv3" +TiKV3-2 ansible_host=172.16.10.6 deploy_dir=/data2/deploy tikv_port=20172 tikv_status_port=20182 labels="host=tikv3" + +[monitoring_servers] +172.16.10.1 + +[grafana_servers] +172.16.10.1 + +[monitored_servers] +172.16.10.1 +172.16.10.2 +172.16.10.3 +172.16.10.4 +172.16.10.5 +172.16.10.6 + +# 注意:为使 TiKV 的 labels 设置生效,部署集群时必须设置 PD 的 location_labels 参数。 +[pd_servers:vars] +location_labels = ["host"] +``` + +- 服务配置文件参数调整 + + 1. 多实例情况下,需要修改 `tidb-ansible/conf/tikv.yml` 中 `block-cache-size` 下面的 `capacity` 参数: + + ```yaml + storage: + block-cache: + capacity: "1GB" + ``` + + > **注意:** + > + > TiKV 实例数量指每个服务器上 TiKV 的进程数量。 + > + > 推荐设置:`capacity` = MEM_TOTAL * 0.5 / TiKV 实例数量 + + 2. 多实例情况下,需要修改 `tidb-ansible/conf/tikv.yml` 中 `high-concurrency`、`normal-concurrency` 和 `low-concurrency` 三个参数: + + ```yaml + readpool: + coprocessor: + # Notice: if CPU_NUM > 8, default thread pool size for coprocessors + # will be set to CPU_NUM * 0.8. + # high-concurrency: 8 + # normal-concurrency: 8 + # low-concurrency: 8 + ``` + + > **注意:** + > + > 推荐设置:TiKV 实例数量 \* 参数值 = CPU 核心数量 \* 0.8 + + 3. 如果多个 TiKV 实例部署在同一块物理磁盘上,需要修改 `conf/tikv.yml` 中的 `capacity` 参数: + + ```yaml + raftstore: + capacity: 0 + ``` + + > **注意:** + > + > 推荐配置:`capacity` = 磁盘总容量 / TiKV 实例数量 + > + > 例如:`capacity: "100GB"` + +## 第 10 步:调整 `inventory.ini` 文件中的变量 + +本小节介绍如何编辑部署目录的变量和 `inventory.ini` 文件中的其它变量。 + +### 调整部署目录 + +部署目录通过 `deploy_dir` 变量控制,默认全局变量已设置为 `/home/tidb/deploy`,对所有服务生效。如数据盘挂载目录为 `/data1`,可设置为 `/data1/deploy`,样例如下: + +```ini +## Global variables +[all:vars] +deploy_dir = /data1/deploy +``` + +如为某一服务单独设置部署目录,可在配置服务主机列表时配置主机变量,以 TiKV 节点为例,其他服务类推,请务必添加第一列别名,以免服务混布时混淆。 + +```ini +TiKV1-1 ansible_host=172.16.10.4 deploy_dir=/data1/deploy +``` + +### 调整其它变量(可选) + +> **注意:** +> +> 以下控制变量开启请使用首字母大写 `True`,关闭请使用首字母大写 `False`。 + +| 变量 | 含义 | +| :--------------- | :-------------------------------------------------------- | +| `cluster_name` | 集群名称,可调整 | +| `cpu_architecture` | CPU 体系架构,默认为 `amd64`,可选 `arm64` | +| `tidb_version` | TiDB 版本,TiDB Ansible 各分支默认已配置 | +| `process_supervision` | 进程监管方式,默认为 `systemd`,可选 `supervise` | +| `timezone` | 新安装 TiDB 集群第一次启动 bootstrap(初始化)时,将 TiDB 全局默认时区设置为该值。TiDB 使用的时区后续可通过 `time_zone` 全局变量和 session 变量来修改,参考[时区支持](/configure-time-zone.md)。默认为 `Asia/Shanghai`,可选值参考 [timzone 列表](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)。 | +| `enable_firewalld` | 开启防火墙,默认不开启,如需开启,请将[部署建议-网络要求](/hardware-and-software-requirements.md#网络要求) 中的端口加入白名单 | +| `enable_ntpd` | 检测部署目标机器 NTP 服务,默认为 `True`,请勿关闭 | +| `set_hostname` | 根据 IP 修改部署目标机器主机名,默认为 `False` | +| `enable_binlog` | 是否部署 Pump 并开启 binlog,默认为 `False`,依赖 Kafka 集群,参见 `zookeeper_addrs` 变量 | +| `zookeeper_addrs` | binlog Kafka 集群的 zookeeper 地址 | +| `deploy_without_tidb` | KV 模式,不部署 TiDB 服务,仅部署 PD、TiKV 及监控服务,请将 `inventory.ini` 文件中 `tidb_servers` 主机组 IP 设置为空。| +| `alertmanager_target` | 可选:如果你已单独部署 alertmanager,可配置该变量,格式:`alertmanager_host:alertmanager_port` | +| `grafana_admin_user` | Grafana 管理员帐号用户名,默认为 admin | +| `grafana_admin_password` | Grafana 管理员帐号密码,默认为 admin,用于 Ansible 导入 Dashboard 和创建 API Key,如后期通过 grafana web 修改了密码,请更新此变量 | +| `collect_log_recent_hours` | 采集日志时,采集最近几个小时的日志,默认为 2 小时 | +| `enable_bandwidth_limit` | 在中控机上从部署目标机器拉取诊断数据时,是否限速,默认为 `True`,与 `collect_bandwidth_limit` 变量结合使用 | +| `collect_bandwidth_limit` | 在中控机上从部署目标机器拉取诊断数据时限速多少,单位: Kbit/s,默认 10000,即 10Mb/s,如果是单机多 TiKV 实例部署方式,需除以单机实例个数 | +| `prometheus_storage_retention` | Prometheus 监控数据的保留时间(默认为 30 天);2.1.7、3.0 以及之后的 tidb-ansible 版本中,`group_vars/monitoring_servers.yml` 文件里新增的配置 | + +## 第 11 步:部署 TiDB 集群 + +`ansible-playbook` 执行 Playbook 时,默认并发为 5。部署目标机器较多时,可添加 `-f` 参数指定并发数,例如 `ansible-playbook deploy.yml -f 10`。以下示例使用 `tidb` 用户作为服务运行用户: + +1. 在 `tidb-ansible/inventory.ini` 文件中,确认 `ansible_user = tidb`。 + + ```ini + ## Connection + # ssh via normal user + ansible_user = tidb + ``` + + > **注意:** + > + > 不要将 `ansible_user` 设置为 `root` 用户,因为 `tidb-ansible` 限制了服务以普通用户运行。 + + 执行以下命令,如果所有 server 均返回 `tidb`,表示 SSH 互信配置成功: + + {{< copyable "shell-regular" >}} + + ```bash + ansible -i inventory.ini all -m shell -a 'whoami' + ``` + + 执行以下命令,如果所有 server 均返回 `root`,表示 `tidb` 用户 sudo 免密码配置成功。 + + {{< copyable "shell-regular" >}} + + ```bash + ansible -i inventory.ini all -m shell -a 'whoami' -b + ``` + +2. 执行 `local_prepare.yml` playbook,联网下载 TiDB binary 至中控机。 + + {{< copyable "shell-regular" >}} + + ```bash + ansible-playbook local_prepare.yml + ``` + +3. 初始化系统环境,修改内核参数。 + + {{< copyable "shell-regular" >}} + + ```bash + ansible-playbook bootstrap.yml + ``` + +4. 部署 TiDB 集群软件。 + + {{< copyable "shell-regular" >}} + + ```bash + ansible-playbook deploy.yml + ``` + + > **注意:** + > + > Grafana Dashboard 上的 **Report** 按钮可用来生成 PDF 文件,此功能依赖 `fontconfig` 包和英文字体。如需使用该功能,登录 **grafana_servers** 机器,用以下命令安装: + > + > {{< copyable "shell-regular" >}} + > + > ```bash + > sudo yum install fontconfig open-sans-fonts + > ``` + +5. 启动 TiDB 集群。 + + {{< copyable "shell-regular" >}} + + ```bash + ansible-playbook start.yml + ``` + +## 测试集群 + +TiDB 兼容 MySQL,因此可使用 MySQL 客户端直接连接 TiDB。推荐配置负载均衡以提供统一的 SQL 接口。 + +1. 使用 MySQL 客户端连接 TiDB 集群。TiDB 服务的默认端口为 `4000`。 + + {{< copyable "sql" >}} + + ```sql + mysql -u root -h 172.16.10.1 -P 4000 + ``` + +2. 通过浏览器访问监控平台。 + + - 地址: + - 默认帐号与密码:`admin`;`admin` + +## 常见部署问题 + +本小节介绍使用 TiDB Ansible 部署 TiDB 集群过程中的常见问题与解决方案。 + +### 如何自定义端口 + +修改 `inventory.ini` 文件,在相应服务 IP 后添加以下主机变量即可: + +| 组件 | 端口变量 | 默认端口 | 说明 | +| :-- | :-- | :-- | :-- | +| TiDB | tidb_port | 4000 | 应用及 DBA 工具访问通信端口 | +| TiDB | tidb_status_port | 10080 | TiDB 状态信息上报通信端口 | +| TiKV | tikv_port | 20160 | TiKV 通信端口 | +| TiKV | tikv_status_port | 20180 | 上报 TiKV 状态的通信端口 | +| PD | pd_client_port | 2379 | 提供 TiDB 和 PD 通信端口 | +| PD | pd_peer_port | 2380 | PD 集群节点间通信端口 | +| Pump | pump_port | 8250 | Pump 通信端口 | +| Prometheus | prometheus_port | 9090 | Prometheus 服务通信端口 | +| Pushgateway | pushgateway_port | 9091 | TiDB, TiKV, PD 监控聚合和上报端口 | +| Node_exporter | node_exporter_port | 9100 | TiDB 集群每个节点的系统信息上报通信端口 | +| Blackbox_exporter | blackbox_exporter_port | 9115 | Blackbox_exporter 通信端口,用于 TiDB 集群端口监控 | +| Grafana | grafana_port | 3000 | Web 监控服务对外服务和客户端(浏览器)访问端口 | +| Kafka_exporter | kafka_exporter_port | 9308 | Kafka_exporter 通信端口,用于监控 binlog Kafka 集群 | + +### 如何自定义部署目录 + +修改 `inventory.ini` 文件,在相应服务 IP 后添加以下主机变量即可: + +| 组件 | 目录变量 | 默认目录 | 说明 | +| :-- | :-- | :-- | :-- | +| 全局 | deploy_dir | /home/tidb/deploy | 部署目录 | +| TiDB | tidb_log_dir | {{ deploy_dir }}/log | 日志目录 | +| TiKV | tikv_log_dir | {{ deploy_dir }}/log | 日志目录 | +| TiKV | tikv_data_dir | {{ deploy_dir }}/data | 数据目录 | +| TiKV | wal_dir | "" | rocksdb write-ahead 日志目录,为空时与 TiKV 数据目录一致 | +| TiKV | raftdb_path | "" | raftdb 目录,为空时为 tikv_data_dir/raft | +| PD | pd_log_dir | {{ deploy_dir }}/log | 日志目录 | +| PD | pd_data_dir | {{ deploy_dir }}/data.pd | 数据目录 | +| pump | pump_log_dir | {{ deploy_dir }}/log | 日志目录 | +| pump | pump_data_dir | {{ deploy_dir }}/data.pump | 数据目录 | +| prometheus | prometheus_log_dir | {{ deploy_dir }}/log | 日志目录 | +| prometheus | prometheus_data_dir | {{ deploy_dir }}/data.metrics | 数据目录 | +| pushgateway | pushgateway_log_dir | {{ deploy_dir }}/log | 日志目录 | +| node_exporter | node_exporter_log_dir | {{ deploy_dir }}/log | 日志目录 | +| grafana | grafana_log_dir | {{ deploy_dir }}/log | 日志目录 | +| grafana | grafana_data_dir | {{ deploy_dir }}/data.grafana | 数据目录 | + +### 如何检测 NTP 服务是否正常 + +1. 执行以下命令,如果输出 `running` 表示 NTP 服务正在运行: + + {{< copyable "shell-regular" >}} + + ```bash + sudo systemctl status ntpd.service + ``` + + ``` + ntpd.service - Network Time Service + Loaded: loaded (/usr/lib/systemd/system/ntpd.service; disabled; vendor preset: disabled) + Active: active (running) since 一 2017-12-18 13:13:19 CST; 3s ago + ``` + +2. 执行 `ntpstat` 命令,如果输出 `synchronised to NTP server`(正在与 NTP server 同步),表示在正常同步: + + {{< copyable "shell-regular" >}} + + ```bash + ntpstat + ``` + + ``` + synchronised to NTP server (85.199.214.101) at stratum 2 + time correct to within 91 ms + polling server every 1024 s + ``` + +> **注意:** +> +> Ubuntu 系统需安装 `ntpstat` 软件包。 + +- 以下情况表示 NTP 服务未正常同步: + + {{< copyable "shell-regular" >}} + + ```bash + ntpstat + ``` + + ``` + unsynchronised + ``` + +- 以下情况表示 NTP 服务未正常运行: + + {{< copyable "shell-regular" >}} + + ```bash + ntpstat + ``` + + ``` + Unable to talk to NTP daemon. Is it running? + ``` + +- 如果要使 NTP 服务尽快开始同步,执行以下命令。可以将 `pool.ntp.org` 替换为你的 NTP server: + + {{< copyable "shell-regular" >}} + + ```bash + sudo systemctl stop ntpd.service && \ + sudo ntpdate pool.ntp.org && \ + sudo systemctl start ntpd.service + ``` + +- 如果要在 CentOS 7 系统上手动安装 NTP 服务,可执行以下命令: + + {{< copyable "shell-regular" >}} + + ```bash + sudo yum install ntp ntpdate && \ + sudo systemctl start ntpd.service && \ + sudo systemctl enable ntpd.service + ``` + +### 如何调整进程监管方式从 supervise 到 systemd + +{{< copyable "shell-root" >}} + +```shell +process supervision, [systemd, supervise] +``` + +``` +process_supervision = systemd +``` + +TiDB Anisble 在 TiDB v1.0.4 版本之前进程监管方式默认为 `supervise`。之前安装的集群可保持不变,如需更新为 `systemd`,需关闭集群,按以下方式变更: + +{{< copyable "shell-regular" >}} + +```bash +ansible-playbook stop.yml && \ +ansible-playbook deploy.yml -D && \ +ansible-playbook start.yml +``` + +### 如何手工配置 SSH 互信及 sudo 免密码 + +1. 以 `root` 用户依次登录到部署目标机器创建 `tidb` 用户并设置登录密码。 + + {{< copyable "shell-root" >}} + + ```bash + useradd tidb && \ + passwd tidb + ``` + +2. 执行以下命令,将 `tidb ALL=(ALL) NOPASSWD: ALL` 添加到文件末尾,即配置好 sudo 免密码。 + + {{< copyable "shell-root" >}} + + ```bash + visudo + ``` + + ``` + tidb ALL=(ALL) NOPASSWD: ALL + ``` + +3. 以 `tidb` 用户登录到中控机,执行以下命令。将 `172.16.10.61` 替换成你的部署目标机器 IP,按提示输入部署目标机器 `tidb` 用户密码,执行成功后即创建好 SSH 互信,其他机器同理。 + + {{< copyable "shell-regular" >}} + + ```bash + ssh-copy-id -i ~/.ssh/id_rsa.pub 172.16.10.61 + ``` + +4. 以 `tidb` 用户登录中控机,通过 `ssh` 的方式登录目标机器 IP。如果不需要输入密码并登录成功,即表示 SSH 互信配置成功。 + + {{< copyable "shell-regular" >}} + + ```bash + ssh 172.16.10.61 + ``` + + ``` + [tidb@172.16.10.61 ~]$ + ``` + +5. 以 `tidb` 用户登录到部署目标机器后,执行以下命令,不需要输入密码并切换到 `root` 用户,表示 `tidb` 用户 sudo 免密码配置成功。 + + {{< copyable "shell-regular" >}} + + ```bash + sudo -su root + ``` + + ``` + [root@172.16.10.61 tidb]# + ``` + +### You need to install jmespath prior to running json_query filter 报错 + +1. 请参照[在中控机器上安装 TiDB Ansible 及其依赖](#在中控机器上安装-tidb-ansible-及其依赖) 在中控机上通过 `pip` 安装 TiDB Ansible 及相关依赖的指定版本,默认会安装 `jmespath`。 + +2. 执行以下命令,验证 `jmespath` 是否安装成功: + + {{< copyable "shell-regular" >}} + + ```bash + pip show jmespath + ``` + + ``` + Name: jmespath + Version: 0.9.0 + ``` + +3. 在中控机上 Python 交互窗口里执行 `import jmespath`。 + + - 如果没有报错,表示依赖安装成功。 + - 如果有 `ImportError: No module named jmespath` 报错,表示未成功安装 Python `jmespath` 模块。 + + {{< copyable "shell-regular" >}} + + ```bash + python + ``` + + ``` + Python 2.7.5 (default, Nov 6 2016, 00:28:07) + [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + ``` + + {{< copyable "shell-regular" >}} + + ```shell + import jmespath + ``` + +### 启动 Pump/Drainer 报 `zk: node does not exist` 错误 + +请检查 `inventory.ini` 里的 `zookeeper_addrs` 参数配置与 Kafka 集群内的配置是否相同、是否填写了命名空间。关于命名空间的配置说明如下: + +```ini +# ZooKeeper connection string (see ZooKeeper docs for details). +# ZooKeeper address of Kafka cluster, example: +# zookeeper_addrs = "192.168.0.11:2181,192.168.0.12:2181,192.168.0.13:2181" +# You can also append an optional chroot string to the URLs to specify the root directory for all Kafka znodes. Example: +# zookeeper_addrs = "192.168.0.11:2181,192.168.0.12:2181,192.168.0.13:2181/kafka/123" +``` diff --git a/optimistic-transaction.md b/optimistic-transaction.md new file mode 100644 index 000000000000..cf184527f981 --- /dev/null +++ b/optimistic-transaction.md @@ -0,0 +1,151 @@ +--- +title: TiDB 乐观事务模型 +summary: 了解 TiDB 的乐观事务模型。 +category: reference +aliases: ['/docs-cn/stable/reference/transactions/transaction-optimistic/'] +--- + +# TiDB 乐观事务模型 + +本文介绍 TiDB 乐观事务的原理,以及相关特性。 + +TiDB 默认使用乐观事务模型。对于写写冲突,只有事务提交时,才会通过两阶段提交检测是否存在写写冲突。 + +> **注意:** +> +> 自 v3.0.8 开始,新创建的 TiDB 集群默认使用[悲观事务模型](/pessimistic-transaction.md)。但如果从 3.0.7 及之前版本创建的集群升级到 >= 3.0.8 的版本,不会改变默认事务模型,即**只有新创建的集群才会默认使用悲观事务模型**。 + +## 乐观事务原理 + +为支持分布式事务,TiDB 中乐观事务使用两阶段提交协议,流程如下: + +![TiDB 中的两阶段提交](/media/2pc-in-tidb.png) + +1. 客户端开始一个事务。 + + TiDB 从 PD 获取一个全局唯一递增的时间戳作为当前事务的唯一事务 ID,这里称为该事务的 `start_ts`。TiDB 实现了多版本并发控制(MVCC),因此 `start_ts` 同时也作为该事务获取的数据库快照版本。该事务只能读到此 `start_ts` 版本可以读到的数据。 + +2. 客户端发起读请求。 + + 1. TiDB 从 PD 获取数据路由信息,即数据具体存在哪个 TiKV 节点上。 + 2. TiDB 从 TiKV 获取 `start_ts` 版本下对应的数据。 + +3. 客户端发起写请求。 + + TiDB 校验写入数据是否符合约束(如数据类型是否正确、是否符合非空约束等)。**校验通过的数据将存放在 TiDB 中该事务的私有内存里。** + +4. 客户端发起 commit。 + +5. TiDB 开始两阶段提交,在保证事务原子性的前提下,进行数据持久化。 + + 1. TiDB 从当前要写入的数据中选择一个 Key 作为当前事务的 Primary Key。 + 2. TiDB 从 PD 获取所有数据的写入路由信息,并将所有的 Key 按照所有的路由进行分类。 + 3. TiDB 并发地向所有涉及的 TiKV 发起 prewrite 请求。TiKV 收到 prewrite 数据后,检查数据版本信息是否存在冲突或已过期。符合条件的数据会被加锁。 + 4. TiDB 收到所有 prewrite 响应且所有 prewrite 都成功。 + 5. TiDB 向 PD 获取第二个全局唯一递增版本号,定义为本次事务的 `commit_ts`。 + 6. TiDB 向 Primary Key 所在 TiKV 发起第二阶段提交。TiKV 收到 commit 操作后,检查数据合法性,清理 prewrite 阶段留下的锁。 + 7. TiDB 收到两阶段提交成功的信息。 + +6. TiDB 向客户端返回事务提交成功的信息。 + +7. TiDB 异步清理本次事务遗留的锁信息。 + +## 优缺点分析 + +通过分析 TiDB 中事务的处理流程,可以发现 TiDB 事务有如下优点: + +* 实现原理简单,易于理解。 +* 基于单实例事务实现了跨节点事务。 +* 锁管理实现了去中心化。 + +但 TiDB 事务也存在以下缺点: + +* 两阶段提交使网络交互增多。 +* 需要一个中心化的分配时间戳服务。 +* 事务数据量过大时易导致内存暴涨。 + +## 事务的重试 + +使用乐观事务模型时,在高冲突率的场景中,事务容易发生写写冲突而导致提交失败。MySQL 使用悲观事务模型,在执行 SQL 语句的过程中进行加锁并且其 Repeatable Read 隔离级别允许出现不可重复读,所以提交时一般不会出现异常。为了降低应用改造难度,TiDB 提供了数据库内部自动重试机制。 + +### 重试机制 + +当事务提交时,如果发现写写冲突,TiDB 内部重新执行包含写操作的 SQL 语句。你可以通过设置 `tidb_disable_txn_auto_retry = off` 开启自动重试,并通过 `tidb_retry_limit` 设置重试次数: + +```toml +# 设置是否禁用自动重试,默认为 “on”,即不重试。 +tidb_disable_txn_auto_retry = off +# 控制重试次数,默认为 “10”。只有自动重试启用时该参数才会生效。 +# 当 “tidb_retry_limit= 0” 时,也会禁用自动重试。 +tidb_retry_limit = 10 +``` + +你也可以修改当前 Session 或 Global 的值: + +- Session 级别设置: + + {{< copyable "sql" >}} + + ```sql + set @@tidb_disable_txn_auto_retry = off; + ``` + + {{< copyable "sql" >}} + + ```sql + set @@tidb_retry_limit = 10; + ``` + +- Global 级别设置: + + {{< copyable "sql" >}} + + ```sql + set @@global.tidb_disable_txn_auto_retry = off; + ``` + + {{< copyable "sql" >}} + + ```sql + set @@global.tidb_retry_limit = 10; + ``` + +> **注意:** +> +> `tidb_retry_limit` 变量决定了事务重试的最大次数。当它被设置为 0 时,所有事务都不会自动重试,包括自动提交的单语句隐式事务。这是彻底禁用 TiDB 中自动重试机制的方法。禁用自动重试后,所有冲突的事务都会以最快的方式上报失败信息(包含 `try again later`)给应用层。 + +### 重试的局限性 + +TiDB 默认不进行事务重试,因为重试事务可能会导致更新丢失,从而破坏[可重复读的隔离级别](/transaction-isolation-levels.md)。 + +事务重试的局限性与其原理有关。事务重试可概括为以下三个步骤: + +1. 重新获取 `start_ts`。 +2. 重新执行包含写操作的 SQL 语句。 +3. 再次进行两阶段提交。 + +第二步中,重试时仅重新执行包含写操作的 SQL 语句,并不涉及读操作的 SQL 语句。但是当前事务中读到数据的时间与事务真正开始的时间发生了变化,写入的版本变成了重试时获取的 `start_ts` 而非事务一开始时获取的 `start_ts`。因此,当事务中存在依赖查询结果来更新的语句时,重试将无法保证事务原本可重复读的隔离级别,最终可能导致结果与预期出现不一致。 + +如果业务可以容忍事务重试导致的异常,或并不关注事务是否以可重复读的隔离级别来执行,则可以开启自动重试。 + +## 冲突检测 + +作为一个分布式系统,TiDB 在内存中的冲突检测是在 TiKV 中进行,主要发生在 prewrite 阶段。因为 TiDB 集群是一个分布式系统,TiDB 实例本身无状态,实例之间无法感知到彼此的存在,也就无法确认自己的写入与别的 TiDB 实例是否存在冲突,所以会在 TiKV 这一层检测具体的数据是否有冲突。 + +具体配置如下:: + +```toml +# scheduler 内置一个内存锁机制,防止同时对一个 Key 进行操作。 +# 每个 Key hash 到不同的 slot。(默认为 2048000) +scheduler-concurrency = 2048000 +``` + +此外,TiKV 支持监控等待 latch 的时间: + +![Scheduler latch wait duration](/media/optimistic-transaction-metric.png) + +当 `Scheduler latch wait duration` 的值特别高时,说明大量时间消耗在等待锁的请求上。如果不存在底层写入慢的问题,基本上可以判断该段时间内冲突比较多。 + +## 更多阅读 + +- [Percolator 和 TiDB 事务算法](https://pingcap.com/blog-cn/percolator-and-txn/) diff --git a/optimizer-hints.md b/optimizer-hints.md new file mode 100644 index 000000000000..aafb198502e2 --- /dev/null +++ b/optimizer-hints.md @@ -0,0 +1,312 @@ +--- +title: Optimizer Hints +category: reference +aliases: ['/docs-cn/stable/reference/performance/optimizer-hints/'] +--- + +# Optimizer Hints + +TiDB 支持 Optimizer Hints 语法,它基于 MySQL 5.7 中介绍的类似 comment 的语法,例如 `/*+ HINT_NAME(t1, t2) */`。当 TiDB 优化器选择的不是最优查询计划时,建议使用 Optimizer Hints。 + +> **注意:** +> +> MySQL 命令行客户端在 5.7.7 版本之前默认清除了 Optimizer Hints。如果需要在这些早期版本的客户端中使用 `Hint` 语法,需要在启动客户端时加上 `--comments` 选项,例如 `mysql -h 127.0.0.1 -P 4000 -uroot --comments`。 + +## 语法 + +Optimizer Hints 通过 `/*+ ... */` 注释的形式跟在 `SELECT`、`UPDATE` 或 `DELETE` 关键字的后面(`INSERT` 关键字后不支持 Optimizer Hints),常见形式如 `/*+ HINT_NAME([t1_name [, t2_name] ...]) */`。Hint 名称不区分大小写,多个不同的 Hint 之间需用逗号隔开。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ USE_INDEX(t1, idx1), HASH_AGG(), HASH_JOIN(t1) */ count(*) from t t1, t t2 where t1.a = t2.b; +``` + +Optimizer Hints 可以和 `Explain` / `Explain Analyze` 组合使用,通过这两个命令查看验证 Optimizer Hints 是否按照预期对查询产生了影响。如果 Optimizer Hints 包含语法错误,或者不适用于当前语句,查询会按照没有 Optimizer Hints 的情况执行,不会对 Optimizer Hints 部分报错,而是会记录 Warning,用户可以在查询结束后通过 `Show Warnings` 命令查看具体信息。 + +> **注意:** +> +> 如果注释不是跟在指定的关键字后,会被当作是普通的 MySQL comment,注释不会生效,且不会上报 warning。 + +TiDB 目前支持的 Optimizer Hints 根据生效范围的不同可以划分为两类:第一类是在查询块范围生效的 Hint,例如 [`/*+ HASH_AGG() */`](#hash_agg);第二类是在整个查询范围生效的 Hint,例如 [`/*+ MEMORY_QUOTA(1024 MB)*/`](#memory_quotan)。 + +每条语句中每一个查询和子查询都对应着一个不同的查询块,每个查询块有自己对应的名字。以下面这条语句为例: + +{{< copyable "sql" >}} + +```sql +select * from (select * from t) t1, (select * from t) t2; +``` + +该查询语句有 3 个查询块,最外面一层 `SELECT` 所在的查询块的名字为 `sel_1`,两个 `SELECT` 子查询的名字依次为 `sel_2` 和 `sel_3`。其中数字序号根据 `SELECT` 出现的位置从左到右计数。如果分别用 `DELETE` 和 `UPDATE` 查询替代第一个 `SELECT` 查询,则对应的查询块名字分别为 `del_1` 和 `upd_1`。 + +## 查询块范围生效的 Hint + +这类 Hint 可以跟在查询语句中**任意** `SELECT`、`UPDATE` 或 `DELETE` 关键字的后面。通过在 Hint 中使用查询块名字可以控制 Hint 的生效范围,以及准确标识查询中的每一个表(有可能表的名字或者别名相同),方便明确 Hint 的参数指向。若不显式地在 Hint 中指定查询块,Hint 默认作用于当前查询块。以如下查询为例: + +{{< copyable "sql" >}} + +```sql +select /*+ HASH_JOIN(@sel_1 t1@sel_1, t3) */ * from (select t1.a, t1.b from t t1, t t2 where t1.a = t2.a) t1, t t3 where t1.b = t3.b; +``` + +该 Hint 在 `sel_1` 这个查询块中生效,参数分别为 `sel_1` 中的 `t1` 表(`sel_2` 中也有一个 `t1` 表)和 `t3` 表。 + +如上例所述,在 Hint 中使用查询块名字的方式有两种:第一种是作为 Hint 的第一个参数,与其他参数用空格隔开。除 `QB_NAME` 外,本节所列的所有 Hint 除自身明确列出的参数外都有一个隐藏的可选参数 `@QB_NAME`,通过使用这个参数可以指定该 Hint 的生效范围;第二种在 Hint 中使用查询块名字的方式是在参数中的某一个表名后面加 `@QB_NAME`,用以明确指出该参数是哪个查询块中的表。 + +> **注意:** +> +> Hint 声明的位置必须在指定生效的查询块之中或之前,不能是在之后的查询块中,否则无法生效。 + +### QB_NAME + +当查询语句是包含多层嵌套子查询的复杂语句时,识别某个查询块的序号和名字很可能会出错,Hint `QB_NAME` 可以方便我们使用查询块。`QB_NAME` 是 Query Block Name 的缩写,用于为某个查询块指定新的名字,同时查询块原本默认的名字依然有效。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ QB_NAME(QB1) */ * from (select * from t) t1, (select * from t) t2; +``` + +这条 Hint 将最外层 `SELECT` 查询块的命名为 `QB1`,此时 `QB1` 和默认名称 `sel_1` 对于这个查询块来说都是有效的。 + +> **注意:** +> +> 上述例子中,如果指定的 `QB_NAME` 为 `sel_2`,并且不给原本 `sel_2` 对应的第二个查询块指定新的 `QB_NAME`,则第二个查询块的默认名字 `sel_2` 会失效。 + +### MERGE_JOIN(t1_name [, tl_name ...]) + +`MERGE_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表使用 Sort Merge Join 算法。这个算法通常会占用更少的内存,但执行时间会更久。当数据量太大,或系统内存不足时,建议尝试使用。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ MERGE_JOIN(t1, t2) */ * from t1,t2 where t1.id = t2.id; +``` + +> **注意:** +> +> `MERGE_JOIN` 的别名是 `TIDB_SMJ`,在 3.0.x 及之前版本仅支持使用该别名;之后的版本同时支持使用这两种名称,但推荐使用 `MERGE_JOIN`。 + +### INL_JOIN(t1_name [, tl_name ...]) + +`INL_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表使用 Index Nested Loop Join 算法。这个算法可能会在某些场景更快,消耗更少系统资源,有的场景会更慢,消耗更多系统资源。对于外表经过 WHERE 条件过滤后结果集较小(小于 1 万行)的场景,可以尝试使用。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ INL_JOIN(t1, t2) */ * from t1,t2 where t1.id = t2.id; +``` + +`INL_JOIN()` 中的参数是建立查询计划时内表的候选表,比如 `INL_JOIN(t1)` 只会考虑使用 t1 作为内表构建查询计划。表如果指定了别名,就只能使用表的别名作为 `INL_JOIN()` 的参数;如果没有指定别名,则用表的本名作为其参数。比如在 `select /*+ INL_JOIN(t1) */ * from t t1, t t2 where t1.a = t2.b;` 中,`INL_JOIN()` 的参数只能使用 t 的别名 t1 或 t2,不能用 t。 + +> **注意:** +> +> `INL_JOIN` 的别名是 `TIDB_INLJ`,在 3.0.x 及之前版本仅支持使用该别名;之后的版本同时支持使用这两种名称,但推荐使用 `INL_JOIN`。 + +### INL_HASH_JOIN + +`INL_HASH_JOIN(t1_name [, tl_name])` 提示优化器使用 Index Nested Loop Hash Join 算法。该算法与 Index Nested Loop Join 使用条件完全一样,两者的区别是 `INL_JOIN` 会在连接的内表上建哈希表,而 `INL_HASH_JOIN` 会在连接的外表上建哈希表,后者对于内存的使用是有固定上限的,而前者使用的内存使用取决于内表匹配到的行数。 + +### INL_MERGE_JOIN + +`INL_MERGE_JOIN(t1_name [, tl_name])` 提示优化器使用 Index Nested Loop Merge Join 算法。这个 Hint 的适用场景和 `INL_JOIN` 一致,相比于 `INL_JOIN` 和 `INL_HASH_JOIN` 会更节省内存,但使用条件会更苛刻:join keys 中的内表列集合是内表使用的索引的前缀,或内表使用的索引是 join keys 中的内表列集合的前缀。 + +### HASH_JOIN(t1_name [, tl_name ...]) + +`HASH_JOIN(t1_name [, tl_name ...])` 提示优化器对指定表使用 Hash Join 算法。这个算法多线程并发执行,执行速度较快,但会消耗较多内存。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ HASH_JOIN(t1, t2) */ * from t1,t2 where t1.id = t2.id; +``` + +> **注意:** +> +> `HASH_JOIN` 的别名是 `TIDB_HJ`,在 3.0.x 及之前版本仅支持使用该别名;之后的版本同时支持使用这两种名称,推荐使用 `HASH_JOIN`。 + +### HASH_AGG() + +`HASH_AGG()` 提示优化器对指定查询块中所有聚合函数使用 Hash Aggregation 算法。这个算法多线程并发执行,执行速度较快,但会消耗较多内存。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ HASH_AGG() */ count(*) from t1,t2 where t1.a > 10 group by t1.id; +``` + +### STREAM_AGG() + +`STREAM_AGG()` 提示优化器对指定查询块中所有聚合函数使用 Stream Aggregation 算法。这个算法通常会占用更少的内存,但执行时间会更久。数据量太大,或系统内存不足时,建议尝试使用。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ STREAM_AGG() */ count(*) from t1,t2 where t1.a > 10 group by t1.id; +``` + +### USE_INDEX(t1_name, idx1_name [, idx2_name ...]) + +`USE_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示优化器对指定表仅使用给出的索引。 + +下面例子的效果等价于 `select * from t t1 use index(idx1, idx2);`: + +{{< copyable "sql" >}} + +```sql +select /*+ USE_INDEX(t1, idx1, idx2) */ * from t t1; +``` + +> **注意:** +> +> 当该 Hint 中只指定表名,不指定索引名时,表示不考虑使用任何索引,而是选择全表扫。 + +### IGNORE_INDEX(t1_name, idx1_name [, idx2_name ...]) + +`IGNORE_INDEX(t1_name, idx1_name [, idx2_name ...])` 提示优化器对指定表忽略给出的索引。 + +下面例子的效果等价于 `select * from t t1 ignore index(idx1, idx2);`: + +{{< copyable "sql" >}} + +```sql +select /*+ IGNORE_INDEX(t1, idx1, idx2) */ * from t t1; +``` + +### AGG_TO_COP() + +`AGG_TO_COP()` 提示优化器将指定查询块中的聚合函数下推到 coprocessor。如果优化器没有下推某些适合下推的聚合函数,建议尝试使用。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ AGG_TO_COP() */ sum(t1.a) from t t1; +``` + +### READ_FROM_STORAGE(TIFLASH[t1_name [, tl_name ...]], TIKV[t2_name [, tl_name ...]]) + +`READ_FROM_STORAGE(TIFLASH[t1_name [, tl_name ...]], TIKV[t2_name [, tl_name ...]])` 提示优化器从指定的存储引擎来读取指定的表,目前支持的存储引擎参数有 `TIKV` 和 `TIFLASH`。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ READ_FROM_STORAGE(TIFLASH[t1], TIKV[t2]) */ t1.a from t t1, t t2 where t1.a = t2.a; +``` + +### USE_INDEX_MERGE(t1_name, idx1_name [, idx2_name ...]) + +`USE_INDEX_MERGE(t1_name, idx1_name [, idx2_name ...])` 提示优化器通过 index merge 的方式来访问指定的表,其中索引列表为可选参数。若显式地指出索引列表,会尝试在索引列表中选取索引来构建 index merge。若不给出索引列表,会尝试在所有可用的索引中选取索引来构建 index merge。例如: + +{{< copyable "sql" >}} + +```sql +select /*+ USE_INDEX_MERGE(t1, idx_a, idx_b, idx_c) */ * from t t1 where t1.a > 10 or t1.b > 10; +``` + +当对同一张表有多个 `USE_INDEX_MERGE` Hint 时,优化器会从这些 Hint 指定的索引列表的并集中尝试选取索引。 + +> **注意:** +> +> `USE_INDEX_MERGE` 的参数是索引名,而不是列名。对于主键索引,索引名为 `primary`。 + +目前该 Hint 生效的条件较为苛刻,包括: + +- 如果查询有除了全表扫以外的单索引扫描方式可以选择,优化器不会选择 index merge; +- 如果查询在显式事务里,且该条查询之前的语句已经涉及写入,优化器不会选择 index merge; + +## 查询范围生效的 Hint + +这类 Hint 只能跟在语句中**第一个** `SELECT`、`UPDATE` 或 `DELETE` 关键字的后面,等同于在当前这条查询运行时对指定的系统变量进行修改,其优先级高于现有系统变量的值。 + +> **注意:** +> +> 这类 Hint 虽然也有隐藏的可选变量 `@QB_NAME`,但就算指定了该值,Hint 还是会在整个查询范围生效。 + +### NO_INDEX_MERGE() + +`NO_INDEX_MERGE()` 会关闭优化器的 index merge 功能。 + +下面的例子不会使用 index merge: + +{{< copyable "sql" >}} + +```sql +select /*+ NO_INDEX_MERGE() */ * from t where t.a > 0 or t.b > 0; +``` + +除了 Hint 外,系统变量 `tidb_enable_index_merge` 也能决定是否开启该功能。 + +> **注意:** +> +> `NO_INDEX_MERGE` 优先级高于 `USE_INDEX_MERGE`,当这两类 Hint 同时存在时,`USE_INDEX_MERGE` 不会生效。 + +### USE_TOJA(boolean_value) + +参数 `boolean_value` 可以是 `TRUE` 或者 `FALSE`。`USE_TOJA(TRUE)` 会开启优化器尝试将 in (subquery) 条件转换为 join 和 aggregation 的功能。相对地,`USE_TOJA(FALSE)` 会关闭该功能。 + +下面的例子会将 `in (select t2.a from t2) subq` 转换为等价的 join 和 aggregation: + +{{< copyable "sql" >}} + +```sql +select /*+ USE_TOJA(TRUE) */ t1.a, t1.b from t1 where t1.a in (select t2.a from t2) subq; +``` + +除了 Hint 外,系统变量 `tidb_opt_insubq_to_join_and_agg` 也能决定是否开启该功能。 + +### MAX_EXECUTION_TIME(N) + +`MAX_EXECUTION_TIME(N)` 把语句的执行时间限制在 `N` 毫秒以内,超时后服务器会终止这条语句的执行。 + +下面的 Hint 设置了 1000 毫秒(即 1 秒)超时: + +{{< copyable "sql" >}} + +```sql +select /*+ MAX_EXECUTION_TIME(1000) */ * from t1 inner join t2 where t1.id = t2.id; +``` + +除了 Hint 之外,系统变量 `global.max_execution_time` 也能对语句执行时间进行限制。 + +### MEMORY_QUOTA(N) + +`MEMORY_QUOTA(N)` 用于限制语句执行时的内存使用。该 Hint 支持 MB 和 GB 两种单位。内存使用超过该限制时会根据当前设置的内存超限行为来打出一条 log 或者终止语句的执行。 + +下面的 Hint 设置了 1024 MB 的内存限制: + +{{< copyable "sql" >}} + +```sql +select /*+ MEMORY_QUOTA(1024 MB) */ * from t; +``` + +除了 Hint 外,系统变量 `tidb_mem_quota_query` 也能限制语句执行的内存使用。 + +### READ_CONSISTENT_REPLICA() + +`READ_CONSISTENT_REPLICA()` 会开启从数据一致的 TiKV follower 节点读取数据的特性。 + +下面的例子会从 follower 节点读取数据: + +{{< copyable "sql" >}} + +```sql +select /*+ READ_CONSISTENT_REPLICA() */ * from t; +``` + +除了 Hint 外,环境变量 `tidb_replica_read` 设为 `'follower'` 或者 `'leader'` 也能决定是否开启该特性。 + +### IGNORE_PLAN_CACHE() + +`IGNORE_PLAN_CACHE()` 提示优化器在处理当前 `prepare` 语句时不使用 plan cache。 + +该 Hint 用于在 [prepare-plan-cache](/tidb-configuration-file.md#prepared-plan-cache) 开启的场景下临时对某类查询禁用 plan cache。 + +以下示例强制该 `prepare` 语句不使用 plan cache: + +{{< copyable "sql" >}} + +```sql +prepare stmt from 'select /*+ IGNORE_PLAN_CACHE() */ * from t where t.id = ?'; +``` diff --git a/overview.md b/overview.md index 819c8e6b9530..3a0a557d70e6 100644 --- a/overview.md +++ b/overview.md @@ -1,66 +1,49 @@ --- title: TiDB 简介 category: introduction +aliases: ['/docs-cn/stable/key-features/'] --- # TiDB 简介 -TiDB 是 PingCAP 公司设计的开源分布式 HTAP (Hybrid Transactional and Analytical Processing) 数据库,结合了传统的 RDBMS 和 NoSQL 的最佳特性。TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性。TiDB 的目标是为 OLTP (Online Transactional Processing) 和 OLAP (Online Analytical Processing) 场景提供一站式的解决方案。 +TiDB 是 PingCAP 公司自主设计、研发的开源分布式关系型数据库,是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP)的融合型分布式数据库产品,具备水平扩容或者缩容、金融级高可用、实时 HTAP、云原生的分布式数据库、兼容 MySQL 5.7 协议和 MySQL 生态等重要特性。目标是为用户提供一站式 OLTP (Online Transactional Processing)、OLAP (Online Analytical Processing)、HTAP 解决方案。TiDB 适合高可用、强一致要求较高、数据规模较大等各种应用场景。 -TiDB 具备如下特性: +## 五大核心特性 -- 高度兼容 MySQL +- 一键水平扩容或者缩容 - [大多数情况下](/reference/mysql-compatibility.md),无需修改代码即可从 MySQL 轻松迁移至 TiDB,分库分表后的 MySQL 集群亦可通过 TiDB 工具进行实时迁移。 + 得益于 TiDB 存储计算分离的架构的设计,可按需对计算、存储分别进行在线扩容或者缩容,扩容或者缩容过程中对应用、运维人员透明。 + + - 金融级高可用 -- 水平弹性扩展 + 数据采用多副本存储,数据副本通过 Multi-Raft 协议同步事务日志,多数派写入成功事务才能提交,确保数据强一致性且少数副本发生故障时不影响数据的可用性。可按需配置副本地理位置、副本数量等策略满足不同容灾级别的要求。 + +- 实时 HTAP - 通过简单地增加新节点即可实现 TiDB 的水平扩展,按需扩展吞吐或存储,轻松应对高并发、海量数据场景。 + 提供行存储引擎 TiKV、列存储引擎 TiFlash 两款存储引擎,TiFlash 通过 Multi-Raft Learner 协议实时从 TiKV 复制数据,确保行存储引擎 TiKV 和列存储引擎 TiFlash 之间的数据强一致。TiKV、TiFlash 可按需部署在不同的机器,解决 HTAP 资源隔离的问题。 + +- 云原生的分布式数据库 -- 分布式事务 + 专为云而设计的分布式数据库,通过 [TiDB Operator](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/tidb-operator-overview/) 可在公有云、私有云、混合云中实现部署工具化、自动化。 - TiDB 100% 支持标准的 ACID 事务。 +- 兼容 MySQL 5.7 协议和 MySQL 生态 -- 真正金融级高可用 + 兼容 MySQL 5.7 协议、MySQL 常用的功能、MySQL 生态,应用无需或者修改少量代码即可从 MySQL 迁移到 TiDB。提供丰富的数据迁移工具帮助应用便捷完成数据迁移。 - 相比于传统主从 (M-S) 复制方案,基于 Raft 的多数派选举协议可以提供金融级的 100% 数据强一致性保证,且在不丢失大多数副本的前提下,可以实现故障的自动恢复 (auto-failover),无需人工介入。 +## 四大核心应用场景 -- 一站式 HTAP 解决方案 - - TiDB 作为典型的 OLTP 行存数据库,同时兼具强大的 OLAP 性能,配合 TiSpark,可提供一站式 HTAP 解决方案,一份存储同时处理 OLTP & OLAP,无需传统繁琐的 ETL 过程。 - -- 云原生 SQL 数据库 - - TiDB 是为云而设计的数据库,支持公有云、私有云和混合云,配合 [TiDB Operator 项目](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/tidb-operator-overview/) 可实现自动化运维,使部署、配置和维护变得十分简单。 - -TiDB 的设计目标是 100% 的 OLTP 场景和 80% 的 OLAP 场景,更复杂的 OLAP 分析可以通过 [TiSpark 项目](/reference/tispark.md)来完成。 - -TiDB 对业务没有任何侵入性,能优雅地替换传统的数据库中间件、数据库分库分表等 Sharding 方案。同时它也让开发运维人员不用关注数据库 Scale 的细节问题,专注于业务开发,极大地提升研发的生产力。 - -三篇文章了解 TiDB 技术内幕: - -- [说存储](https://pingcap.com/blog-cn/tidb-internal-1/) -- [说计算](https://pingcap.com/blog-cn/tidb-internal-2/) -- [谈调度](https://pingcap.com/blog-cn/tidb-internal-3/) - -## 部署方式 - -TiDB 可以部署在本地和云平台上,支持公有云、私有云和混合云。你可以根据实际场景或需求,选择相应的方式来部署 TiDB 集群: - -- [使用 Ansible 部署](/how-to/deploy/orchestrated/ansible.md):如果用于生产环境,推荐使用 TiDB Ansible 部署 TiDB 集群。 -- [使用 Ansible 离线部署](/how-to/deploy/orchestrated/offline-ansible.md):如果部署环境无法访问网络,可使用 TiDB Ansible 进行离线部署。 -- [使用 TiDB Operator 部署](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-tidb-operator/):使用 TiDB Operator 在 Kubernetes 集群上部署生产就绪的 TiDB 集群,支持[部署到 AWS EKS](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-on-aws-eks/)、[部署到谷歌云 GKE (beta)](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-on-gcp-gke/)、[部署到阿里云 ACK](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-on-alibaba-cloud/) 等。 -- [使用 Docker Compose 部署](/how-to/get-started/deploy-tidb-from-docker-compose.md):如果你只是想测试 TiDB、体验 TiDB 的特性,或者用于开发环境,可以使用 Docker Compose 在本地快速部署 TiDB 集群。该部署方式不适用于生产环境。 -- [使用 Docker 部署](/how-to/deploy/orchestrated/docker.md):你可以使用 Docker 部署 TiDB 集群,但该部署方式不适用于生产环境。 -- [使用 TiDB Operator 部署到 Minikube](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-tidb-from-kubernetes-minikube/):你可以使用 TiDB Operator 将 TiDB 集群部署到本地 Minikube 启动的 Kubernetes 集群中。该部署方式不适用于生产环境。 -- [使用 TiDB Operator 部署到 kind](https://pingcap.com/docs-cn/tidb-in-kubernetes/stable/deploy-tidb-from-kubernetes-kind/):你可以使用 TiDB Operator 将 TiDB 集群部署到以 kind 方式启动的 Kubernetes 本地集群中。该部署方式不适用于生产环境。 - -## 项目源码 - -TiDB 集群所有组件的源码均可从 GitHub 上直接访问: - -- [TiDB](https://github.com/pingcap/tidb) -- [TiKV](https://github.com/tikv/tikv) -- [PD](https://github.com/pingcap/pd) -- [TiSpark](https://github.com/pingcap/tispark) -- [TiDB Operator](https://github.com/pingcap/tidb-operator) +- 对数据一致性及高可靠、系统高可用、可扩展性、容灾要求较高的金融行业属性的场景 + + 众所周知,金融行业对数据一致性及高可靠、系统高可用、可扩展性、容灾要求较高,传统的解决方案是同城两个机房提供服务、异地一个机房提供数据容灾能务但不提供服务,此解决方案存在资源利用率低、维扩成本高、RTO 及 PRO 无法真实达到企业所期望的值。TiDB 采用多副本 + Mutli Raft 协议的方式将数据调度到不同的机房、机架、机器,当部分机器故障时系统可自动进行切换,确保系统的 RTO <= 30s 及 RPO = 0 。 + +- 对存储容量、可扩展性、并发要求较高的海量数量及高并的 OLTP 场景 + + 随着业务的高速发展,数据呈现爆炸性的增长,传统的单机数据库无法满足因数据爆炸性的增长对数据的容量要求,可行方案是采用分库分表的中间件产品或者 NewSQL 数据库替代、采用高端的存储设备等,其中性价比最大的是 NewSQL 数据库,例如:TiDB。TiDB 采用计算、存储分离的架构,可对计算、存储分别进行扩容和缩容,计算节点最大支持 512 节点,每个节点最大支持 1000 并发,集群容量最大支持 PB 级别。 + +- Real-time HTAP 场景 + + 随着 5G、物联网、人工智能的高速发展,企业所生产的数据会越来越多,其规模可能达到数百 TB 甚至 PB 级别,传统的解决方案是通过 OLTP 型数据库处理在线联机交易业务,通过 ETL 工具将数据同步到 OLAP 型数据库进行数据分析,这种处理方案存在存储成本高、实际性差等多方面的问题。TiDB 在 4.0 版本中引入列存储引擎 TiFlash 结合行存储引擎 TiKV 构建真正的 HTAP 数据库,在增加少量存储成本的情况下,可以同一个系统中做联机交易处理、实时数据分析,极大的节省企业的成本。 + +- 数据汇聚、二次加工处理的场景 + + 当前绝大部分企业的业务数据都分散在不同的系统中,没有一个统一的汇总,随着业务的发展,企业的决策层需要了解整个公司的业务状况方便即时的做出决策,故需要将分散在各个系统的数据汇聚在同一个系统并进行二次加工处理生成 T + 0/1 的报表。传统常见的解决方案是采用 ETL + Hadoop 来完成,但 Hadoop 体系统太复杂,运维、存储成本太高无法满足用户的需求。与 Hadoop 相比,TiDB 就会简单得多,业务通过 ETL 工具或者 TiDB 的同步工具将数据同步到 TiDB,在 TiDB 中可通过 SQL 直接生成报表。 diff --git a/partition-pruning.md b/partition-pruning.md new file mode 100644 index 000000000000..42cf11d1e21f --- /dev/null +++ b/partition-pruning.md @@ -0,0 +1,263 @@ +--- +title: 分区裁剪 +category: performance +--- + +# 分区裁剪 + +分区裁剪是只有当目标表为分区表时,才可以进行的一种优化方式。分区裁剪通过分析查询语句中的过滤条件,只选择可能满足条件的分区,不扫描匹配不上的分区,进而显著地减少计算的数据量。 + +## 分区裁剪的使用场景 + +分区表有 Range 分区和 hash 分区两种形式,分区裁剪对两种分区表也有不同的使用场景。 + +### 分区裁剪在 Hash 分区表上的应用 + +#### Hash 分区表上可以使用分区裁剪的场景 + +只有等值比较的查询条件能够支持 Hash 分区表的裁剪。 + +{{< copyable "sql" >}} + +```sql +create table t (x int) partition by hash(x) partitions 4; +explain select * from t where x = 1; +``` + +```sql ++-------------------------+----------+-----------+-----------------------+--------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------+----------+-----------+-----------------------+--------------------------------+ +| TableReader_8 | 10.00 | root | | data:Selection_7 | +| └─Selection_7 | 10.00 | cop[tikv] | | eq(test.t.x, 1) | +| └─TableFullScan_6 | 10000.00 | cop[tikv] | table:t, partition:p1 | keep order:false, stats:pseudo | ++-------------------------+----------+-----------+-----------------------+--------------------------------+ +``` + +在这条 SQL 中,由条件 `x = 1` 可以知道所有结果均在一个分区上。数值 `1` 在经过 Hash 后,可以确定其在分区 `p1` 中。因此只需要扫描分区 `p1` ,而无需访问一定不会出现相关结果的 `p2` 、`p3` 、`p4` 分区。从执行计划来看,其中只出现了一个 `TableFullScan` 算子,且在 `access object` 中指定了 `p1` 分区,确认 `partition pruning` 生效了。 + +#### Hash 分区表上不能使用分区裁剪的场景 + +##### 场景一 + +不能确定查询结果只在一个分区上的条件:如 `in`, `between`, `> < >= <=` 等查询条件,不能使用分区裁剪的优化。 + +{{< copyable "sql" >}} + +```sql +create table t (x int) partition by hash(x) partitions 4; +explain select * from t where x > 2; +``` + +```sql ++------------------------------+----------+-----------+-----------------------+--------------------------------+ +| id | estRows | task | access object | operator info | ++------------------------------+----------+-----------+-----------------------+--------------------------------+ +| Union_10 | 13333.33 | root | | | +| ├─TableReader_13 | 3333.33 | root | | data:Selection_12 | +| │ └─Selection_12 | 3333.33 | cop[tikv] | | gt(test.t.x, 2) | +| │ └─TableFullScan_11 | 10000.00 | cop[tikv] | table:t, partition:p0 | keep order:false, stats:pseudo | +| ├─TableReader_16 | 3333.33 | root | | data:Selection_15 | +| │ └─Selection_15 | 3333.33 | cop[tikv] | | gt(test.t.x, 2) | +| │ └─TableFullScan_14 | 10000.00 | cop[tikv] | table:t, partition:p1 | keep order:false, stats:pseudo | +| ├─TableReader_19 | 3333.33 | root | | data:Selection_18 | +| │ └─Selection_18 | 3333.33 | cop[tikv] | | gt(test.t.x, 2) | +| │ └─TableFullScan_17 | 10000.00 | cop[tikv] | table:t, partition:p2 | keep order:false, stats:pseudo | +| └─TableReader_22 | 3333.33 | root | | data:Selection_21 | +| └─Selection_21 | 3333.33 | cop[tikv] | | gt(test.t.x, 2) | +| └─TableFullScan_20 | 10000.00 | cop[tikv] | table:t, partition:p3 | keep order:false, stats:pseudo | ++------------------------------+----------+-----------+-----------------------+--------------------------------+ +``` + +在这条 SQL 中,`x > 2` 条件无法确定对应的 Hash Partition,所以不能使用分区裁剪。 + +##### 场景二 + +由于分区裁剪的规则优化是在查询计划的生成阶段,对于执行阶段才能获取到过滤条件的场景,无法利用分区裁剪的优化。 + +{{< copyable "sql" >}} + +```sql +create table t (x int) partition by hash(x) partitions 4; +explain select * from t2 where x = (select * from t1 where t2.x = t1.x and t2.x < 2); +``` + +```sql ++--------------------------------------+----------+-----------+------------------------+----------------------------------------------+ +| id | estRows | task | access object | operator info | ++--------------------------------------+----------+-----------+------------------------+----------------------------------------------+ +| Projection_13 | 9990.00 | root | | test.t2.x | +| └─Apply_15 | 9990.00 | root | | inner join, equal:[eq(test.t2.x, test.t1.x)] | +| ├─TableReader_18(Build) | 9990.00 | root | | data:Selection_17 | +| │ └─Selection_17 | 9990.00 | cop[tikv] | | not(isnull(test.t2.x)) | +| │ └─TableFullScan_16 | 10000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | +| └─Selection_19(Probe) | 0.80 | root | | not(isnull(test.t1.x)) | +| └─MaxOneRow_20 | 1.00 | root | | | +| └─Union_21 | 2.00 | root | | | +| ├─TableReader_24 | 2.00 | root | | data:Selection_23 | +| │ └─Selection_23 | 2.00 | cop[tikv] | | eq(test.t2.x, test.t1.x), lt(test.t2.x, 2) | +| │ └─TableFullScan_22 | 2500.00 | cop[tikv] | table:t1, partition:p0 | keep order:false, stats:pseudo | +| └─TableReader_27 | 2.00 | root | | data:Selection_26 | +| └─Selection_26 | 2.00 | cop[tikv] | | eq(test.t2.x, test.t1.x), lt(test.t2.x, 2) | +| └─TableFullScan_25 | 2500.00 | cop[tikv] | table:t1, partition:p1 | keep order:false, stats:pseudo | ++--------------------------------------+----------+-----------+------------------------+----------------------------------------------+ +``` + +这个查询每从 `t2` 读取一行,都会去分区表 `t1` 上进行查询,理论上这时会满足 `t1.x = val` 的过滤条件,但实际上由于分区裁剪只作用于查询计划生成阶段,而不是执行阶段,因而不会做裁剪。 + +### 分区裁剪在 Range 分区表上的应用 + +#### Range 分区表上可以使用分区裁剪的场景 + +##### 场景一 + +等值比较的查询条件可以使用分区裁剪。 + +{{< copyable "sql" >}} + +```sql +create table t (x int) partition by range (x) ( + partition p0 values less than (5), + partition p1 values less than (10), + partition p2 values less than (15) + ); +explain select * from t where x = 3; +``` + +```sql ++-------------------------+----------+-----------+-----------------------+--------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------+----------+-----------+-----------------------+--------------------------------+ +| TableReader_8 | 10.00 | root | | data:Selection_7 | +| └─Selection_7 | 10.00 | cop[tikv] | | eq(test.t.x, 3) | +| └─TableFullScan_6 | 10000.00 | cop[tikv] | table:t, partition:p0 | keep order:false, stats:pseudo | ++-------------------------+----------+-----------+-----------------------+--------------------------------+ +``` + +使用 `in` 条件的等值比较查询条件也可以使用分区裁剪。 + +{{< copyable "sql" >}} + +```sql +create table t (x int) partition by range (x) ( + partition p0 values less than (5), + partition p1 values less than (10), + partition p2 values less than (15) + ); +explain select * from t where x in(1,13); +``` + +```sql ++-----------------------------+----------+-----------+-----------------------+--------------------------------+ +| id | estRows | task | access object | operator info | ++-----------------------------+----------+-----------+-----------------------+--------------------------------+ +| Union_8 | 40.00 | root | | | +| ├─TableReader_11 | 20.00 | root | | data:Selection_10 | +| │ └─Selection_10 | 20.00 | cop[tikv] | | in(test.t.x, 1, 13) | +| │ └─TableFullScan_9 | 10000.00 | cop[tikv] | table:t, partition:p0 | keep order:false, stats:pseudo | +| └─TableReader_14 | 20.00 | root | | data:Selection_13 | +| └─Selection_13 | 20.00 | cop[tikv] | | in(test.t.x, 1, 13) | +| └─TableFullScan_12 | 10000.00 | cop[tikv] | table:t, partition:p2 | keep order:false, stats:pseudo | ++-----------------------------+----------+-----------+-----------------------+--------------------------------+ +``` + +在这条 SQL 中,由条件 `x in(1,13)` 可以知道所有结果只会分布在几个分区上。经过分析,发现所有 `x = 1` 的记录都在分区 `p0` 上, 所有 `x = 13` 的记录都在分区 `p2` 上,因此只需要访问 `p0`、`p2` 这两个分区, + +##### 场景二 + +区间比较的查询条件如 `between`, `> < = >= <=` 可以使用分区裁剪。 + +{{< copyable "sql" >}} + +```sql +create table t (x int) partition by range (x) ( + partition p0 values less than (5), + partition p1 values less than (10), + partition p2 values less than (15) + ); +explain select * from t where x between 7 and 14; +``` + +```sql ++-----------------------------+----------+-----------+-----------------------+-----------------------------------+ +| id | estRows | task | access object | operator info | ++-----------------------------+----------+-----------+-----------------------+-----------------------------------+ +| Union_8 | 500.00 | root | | | +| ├─TableReader_11 | 250.00 | root | | data:Selection_10 | +| │ └─Selection_10 | 250.00 | cop[tikv] | | ge(test.t.x, 7), le(test.t.x, 14) | +| │ └─TableFullScan_9 | 10000.00 | cop[tikv] | table:t, partition:p1 | keep order:false, stats:pseudo | +| └─TableReader_14 | 250.00 | root | | data:Selection_13 | +| └─Selection_13 | 250.00 | cop[tikv] | | ge(test.t.x, 7), le(test.t.x, 14) | +| └─TableFullScan_12 | 10000.00 | cop[tikv] | table:t, partition:p2 | keep order:false, stats:pseudo | ++-----------------------------+----------+-----------+-----------------------+-----------------------------------+ +``` + +##### 场景三 + +分区表达式为 `fn(col)` 的简单形式,查询条件是 `> < = >= <=` ,且 `fn` 是单调函数,可以使用分区裁剪。 + +理论上所有满足单调条件(严格或者非严格)的函数都是可以支持分区裁剪。实际上,目前 TiDB 已经支持的单调函数只有: + +```sql +unix_timestamp +to_days +``` + +例如,分区表达式是 `fn(col)` 形式,`fn` 为我们支持的单调函数 `to_days`,就可以使用分区裁剪: + +{{< copyable "sql" >}} + +```sql +create table t (id datetime) partition by range (to_days(id)) ( + partition p0 values less than (to_days('2020-04-01')), + partition p1 values less than (to_days('2020-05-01'))); +explain select * from t where id > '2020-04-18'; +``` + +```sql ++-------------------------+----------+-----------+-----------------------+-------------------------------------------+ +| id | estRows | task | access object | operator info | ++-------------------------+----------+-----------+-----------------------+-------------------------------------------+ +| TableReader_8 | 3333.33 | root | | data:Selection_7 | +| └─Selection_7 | 3333.33 | cop[tikv] | | gt(test.t.id, 2020-04-18 00:00:00.000000) | +| └─TableFullScan_6 | 10000.00 | cop[tikv] | table:t, partition:p1 | keep order:false, stats:pseudo | ++-------------------------+----------+-----------+-----------------------+-------------------------------------------+ +``` + +#### Range 分区表上不能使用分区裁剪的场景 + +由于分区裁剪的规则优化是在查询计划的生成阶段,对于执行阶段才能获取到过滤条件的场景,无法利用分区裁剪的优化。 + +{{< copyable "sql" >}} + +```sql +create table t1 (x int) partition by range (x) ( + partition p0 values less than (5), + partition p1 values less than (10)); +create table t2 (x int); +explain select * from t2 where x < (select * from t1 where t2.x < t1.x and t2.x < 2); +``` + +```sql ++--------------------------------------+----------+-----------+------------------------+-----------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++--------------------------------------+----------+-----------+------------------------+-----------------------------------------------------------+ +| Projection_13 | 9990.00 | root | | test.t2.x | +| └─Apply_15 | 9990.00 | root | | CARTESIAN inner join, other cond:lt(test.t2.x, test.t1.x) | +| ├─TableReader_18(Build) | 9990.00 | root | | data:Selection_17 | +| │ └─Selection_17 | 9990.00 | cop[tikv] | | not(isnull(test.t2.x)) | +| │ └─TableFullScan_16 | 10000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | +| └─Selection_19(Probe) | 0.80 | root | | not(isnull(test.t1.x)) | +| └─MaxOneRow_20 | 1.00 | root | | | +| └─Union_21 | 2.00 | root | | | +| ├─TableReader_24 | 2.00 | root | | data:Selection_23 | +| │ └─Selection_23 | 2.00 | cop[tikv] | | lt(test.t2.x, 2), lt(test.t2.x, test.t1.x) | +| │ └─TableFullScan_22 | 2.50 | cop[tikv] | table:t1, partition:p0 | keep order:false, stats:pseudo | +| └─TableReader_27 | 2.00 | root | | data:Selection_26 | +| └─Selection_26 | 2.00 | cop[tikv] | | lt(test.t2.x, 2), lt(test.t2.x, test.t1.x) | +| └─TableFullScan_25 | 2.50 | cop[tikv] | table:t1, partition:p1 | keep order:false, stats:pseudo | ++--------------------------------------+----------+-----------+------------------------+-----------------------------------------------------------+ +14 rows in set (0.00 sec) +``` + +这个查询每从 `t2` 读取一行,都会去分区表 `t1` 上进行查询,理论上这时会满足 `t1.x > val` 的过滤条件,但实际上由于分区裁剪只作用于查询计划生成阶段,而不是执行阶段,因而不会做裁剪。 \ No newline at end of file diff --git a/partitioned-table.md b/partitioned-table.md new file mode 100644 index 000000000000..cf5a0a5dee72 --- /dev/null +++ b/partitioned-table.md @@ -0,0 +1,1057 @@ +--- +title: 分区表 +category: reference +aliases: ['/docs-cn/stable/reference/sql/partitioning/'] +--- + +# 分区表 + +本文介绍 TiDB 的分区表。 + +## 分区类型 + +本节介绍在 TiDB 中的分区类型。当前支持的类型包括 Range 分区和 Hash 分区。Range 分区可以用于解决业务中大量删除带来的性能问题,支持快速删除分区。Hash 分区则可以用于大量写入场景下的数据打散。 + +### Range 分区 + +一个表按 Range 分区是指,对于表的每个分区中包含的所有行,按分区表达式计算的值都落在给定的范围内。Range 必须是连续的,并且不能有重叠,通过使用 `VALUES LESS THAN` 进行定义。 + +下列场景中,假设你要创建一个人事记录的表: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE employees ( + id INT NOT NULL, + fname VARCHAR(30), + lname VARCHAR(30), + hired DATE NOT NULL DEFAULT '1970-01-01', + separated DATE NOT NULL DEFAULT '9999-12-31', + job_code INT NOT NULL, + store_id INT NOT NULL +); +``` + +你可以根据需求按各种方式进行 Range 分区。其中一种方式是按 `store_id` 列进行分区: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE employees ( + id INT NOT NULL, + fname VARCHAR(30), + lname VARCHAR(30), + hired DATE NOT NULL DEFAULT '1970-01-01', + separated DATE NOT NULL DEFAULT '9999-12-31', + job_code INT NOT NULL, + store_id INT NOT NULL +) + +PARTITION BY RANGE (store_id) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11), + PARTITION p2 VALUES LESS THAN (16), + PARTITION p3 VALUES LESS THAN (21) +); +``` + +在这个分区模式中,所有 `store_id` 为 1 到 5 的员工,都存储在分区 `p0` 里面,`store_id` 为 6 到 10 的员工则存储在分区 `p1` 里面。Range 分区要求,分区的定义必须是有序的,按从小到大递增。 + +新插入一行数据 `(72, 'Mitchell', 'Wilson', '1998-06-25', NULL, 13)` 将会落到分区 `p2` 里面。但如果你插入一条 `store_id` 大于 20 的记录,则会报错,因为 TiDB 无法知晓应该将它插入到哪个分区。这种情况下,可以在建表时使用最大值: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE employees ( + id INT NOT NULL, + fname VARCHAR(30), + lname VARCHAR(30), + hired DATE NOT NULL DEFAULT '1970-01-01', + separated DATE NOT NULL DEFAULT '9999-12-31', + job_code INT NOT NULL, + store_id INT NOT NULL +) + +PARTITION BY RANGE (store_id) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11), + PARTITION p2 VALUES LESS THAN (16), + PARTITION p3 VALUES LESS THAN MAXVALUE +); +``` + +`MAXVALUE` 表示一个比所有整数都大的整数。现在,所有 `store_id` 列大于等于 16 的记录都会存储在 `p3` 分区中。 + +你也可以按员工的职位编号进行分区,也就是使用 `job_code` 列的值进行分区。假设两位数字编号是用于普通员工,三位数字编号是用于办公室以及客户支持,四位数字编号是管理层职位,那么你可以这样建表: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE employees ( + id INT NOT NULL, + fname VARCHAR(30), + lname VARCHAR(30), + hired DATE NOT NULL DEFAULT '1970-01-01', + separated DATE NOT NULL DEFAULT '9999-12-31', + job_code INT NOT NULL, + store_id INT NOT NULL +) + +PARTITION BY RANGE (job_code) ( + PARTITION p0 VALUES LESS THAN (100), + PARTITION p1 VALUES LESS THAN (1000), + PARTITION p2 VALUES LESS THAN (10000) +); +``` + +在这个例子中,所有普通员工存储在 `p0` 分区,办公室以及支持人员在 `p1` 分区,管理者在 `p2` 分区。 + +除了可以按 `store_id` 切分,你还可以按日期切分。例如,假设按员工离职的年份进行分区: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE employees ( + id INT NOT NULL, + fname VARCHAR(30), + lname VARCHAR(30), + hired DATE NOT NULL DEFAULT '1970-01-01', + separated DATE NOT NULL DEFAULT '9999-12-31', + job_code INT, + store_id INT +) + +PARTITION BY RANGE ( YEAR(separated) ) ( + PARTITION p0 VALUES LESS THAN (1991), + PARTITION p1 VALUES LESS THAN (1996), + PARTITION p2 VALUES LESS THAN (2001), + PARTITION p3 VALUES LESS THAN MAXVALUE +); +``` + +在 Range 分区中,可以基于 `timestamp` 列的值分区,并使用 `unix_timestamp()` 函数,例如: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE quarterly_report_status ( + report_id INT NOT NULL, + report_status VARCHAR(20) NOT NULL, + report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) + +PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) ( + PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ), + PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ), + PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ), + PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ), + PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ), + PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ), + PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ), + PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ), + PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ), + PARTITION p9 VALUES LESS THAN (MAXVALUE) +); +``` + +对于 timestamp 列,使用其它的分区表达式是不允许的。 + +Range 分区在下列条件之一或者多个都满足时,尤其有效: + +* 删除旧数据。如果你使用之前的 `employees` 表的例子,你可以简单使用 `ALTER TABLE employees DROP PARTITION p0;` 删除所有在 1991 年以前停止继续在这家公司工作的员工记录。这会比使用 `DELETE FROM employees WHERE YEAR(separated) <= 1990;` 执行快得多。 +* 使用包含时间或者日期的列,或者是其它按序生成的数据。 +* 频繁查询分区使用的列。例如执行这样的查询 `EXPLAIN SELECT COUNT(*) FROM employees WHERE separated BETWEEN '2000-01-01' AND '2000-12-31' GROUP BY store_id;` 时,TiDB 可以迅速确定,只需要扫描 `p2` 分区的数据,因为其它的分区不满足 `where` 条件。 + +### Hash 分区 + +Hash 分区主要用于保证数据均匀地分散到一定数量的分区里面。在 Range 分区中你必须为每个分区指定值的范围;在 Hash 分区中,你只需要指定分区的数量。 + +使用 Hash 分区时,需要在 `CREATE TABLE` 后面添加 `PARTITION BY HASH (expr)`,其中 `expr` 是一个返回整数的表达式。当这一列的类型是整数类型时,它可以是一个列名。此外,你很可能还需要加上 `PARTITIONS num`,其中 `num` 是一个正整数,表示将表划分多少分区。 + +下面的语句将创建一个 Hash 分区表,按 `store_id` 分成 4 个分区: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE employees ( + id INT NOT NULL, + fname VARCHAR(30), + lname VARCHAR(30), + hired DATE NOT NULL DEFAULT '1970-01-01', + separated DATE NOT NULL DEFAULT '9999-12-31', + job_code INT, + store_id INT +) + +PARTITION BY HASH(store_id) +PARTITIONS 4; +``` + +如果不指定 `PARTITIONS num`,默认的分区数量为 1。 + +你也可以使用一个返回整数的 SQL 表达式。例如,你可以按入职年份分区: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE employees ( + id INT NOT NULL, + fname VARCHAR(30), + lname VARCHAR(30), + hired DATE NOT NULL DEFAULT '1970-01-01', + separated DATE NOT NULL DEFAULT '9999-12-31', + job_code INT, + store_id INT +) + +PARTITION BY HASH( YEAR(hired) ) +PARTITIONS 4; +``` + +最高效的 Hash 函数是作用在单列上,并且函数的单调性是跟列的值是一样递增或者递减的。 + +例如,`date_col` 是类型为 `DATE` 的列,表达式 `TO_DAYS(date_col)` 的值是直接随 `date_col` 的值变化的。`YEAR(date_col)` 跟 `TO_DAYS(date_col)` 就不太一样,因为不是每次 `date_col` 变化时 `YEAR(date_col)` 都会得到不同的值。 + +作为对比,假设我们有一个类型是 INT 的 `int_col` 的列。考虑一下表达式 `POW(5-int_col,3) + 6`,这并不是一个比较好的 Hash 函数,因为随着 `int_col` 的值的变化,表达式的结果不会成比例地变化。改变 `int_col` 的值会使表达式的结果的值变化巨大。例如,`int_col` 从 5 变到 6 表达式的结果变化是 -1,但是从 6 变到 7 的时候表达式的值的变化是 -7。 + +总而言之,表达式越接近 `y = cx` 的形式,它越是适合作为 Hash 函数。因为表达式越是非线性的,在各个分区上面的数据的分布越是倾向于不均匀。 + +理论上,Hash 分区也是可以做分区裁剪的。而实际上对于多列的情况,实现很难并且计算很耗时。因此,不推荐 Hash 分区在表达式中涉及多列。 + +使用 `PARTITIION BY HASH` 的时候,TiDB 通过表达式的结果做“取余”运算,决定数据落在哪个分区。换句话说,如果分区表达式是 `expr`,分区数是 `num`,则由 `MOD(expr, num)` 决定存储的分区。假设 `t1` 定义如下: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE) + PARTITION BY HASH( YEAR(col3) ) + PARTITIONS 4; +``` + +向 `t1` 插入一行数据,其中 `col3` 列的值是 '2005-09-15',这条数据会被插入到分区 1 中: + +``` +MOD(YEAR('2005-09-01'),4) += MOD(2005,4) += 1 +``` + +### 分区对 NULL 值的处理 + +TiDB 允许计算结果为 NULL 的分区表达式。注意,NULL 不是一个整数类型,NULL 小于所有的整数类型值,正如 `ORDER BY` 的规则一样。 + +#### Range 分区对 NULL 的处理 + +如果插入一行到 Range 分区表,它的分区列的计算结果是 NULL,那么这一行会被插入到最小的那个分区。 + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1 ( + c1 INT, + c2 VARCHAR(20) +) + +PARTITION BY RANGE(c1) ( + PARTITION p0 VALUES LESS THAN (0), + PARTITION p1 VALUES LESS THAN (10), + PARTITION p2 VALUES LESS THAN MAXVALUE +); +``` + +``` +Query OK, 0 rows affected (0.09 sec) +``` + +{{< copyable "sql" >}} + +```sql +select * from t1 partition(p0); +``` + +``` ++------|--------+ +| c1 | c2 | ++------|--------+ +| NULL | mothra | ++------|--------+ +1 row in set (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +select * from t1 partition(p1); +``` + +``` +Empty set (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +select * from t1 partition(p2); +``` + +``` +Empty set (0.00 sec) +``` + +删除 `p0` 后验证: + +{{< copyable "sql" >}} + +```sql +alter table t1 drop partition p0; +``` + +``` +Query OK, 0 rows affected (0.08 sec) +``` + +{{< copyable "sql" >}} + +```sql +select * from t1; +``` + +``` +Empty set (0.00 sec) +``` + +#### Hash 分区对 NULL 的处理 + +在 Hash 分区中 NULL 值的处理有所不同,如果分区表达式的计算结果为 NULL,它会被当作 0 值处理。 + +{{< copyable "sql" >}} + +```sql +CREATE TABLE th ( + c1 INT, + c2 VARCHAR(20) +) + +PARTITION BY HASH(c1) +PARTITIONS 2; +``` + +``` +Query OK, 0 rows affected (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +INSERT INTO th VALUES (NULL, 'mothra'), (0, 'gigan'); +``` + +``` +Query OK, 2 rows affected (0.04 sec) +``` + +{{< copyable "sql" >}} + +```sql +select * from th partition (p0); +``` + +``` ++------|--------+ +| c1 | c2 | ++------|--------+ +| NULL | mothra | +| 0 | gigan | ++------|--------+ +2 rows in set (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +select * from th partition (p1); +``` + +``` +Empty set (0.00 sec) +``` + +可以看到,插入的记录 `(NULL, 'mothra')` 跟 `(0, 'gigan')` 落在了同一个分区。 + +> **注意:** +> +> 这里 Hash 分区对 NULL 的处理跟 [MySQL 的文档描述](https://dev.mysql.com/doc/refman/8.0/en/partitioning-handling-nulls.html)一致,但是跟 MySQL 的实际行为并不一致。也就是说,MySQL 的文档跟它的实现并不一致。 +> +> TiDB 的最终行为以本文档描述为准。 + +## 分区管理 + +通过 `ALTER TABLE` 语句可以执行一些添加、删除、合并、切分、重定义分区的操作。 + +### Range 分区管理 + +创建分区表: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE members ( + id INT, + fname VARCHAR(25), + lname VARCHAR(25), + dob DATE +) + +PARTITION BY RANGE( YEAR(dob) ) ( + PARTITION p0 VALUES LESS THAN (1980), + PARTITION p1 VALUES LESS THAN (1990), + PARTITION p2 VALUES LESS THAN (2000) +); +``` + +删除分区: + +{{< copyable "sql" >}} + +```sql +ALTER TABLE members DROP PARTITION p2; +``` + +``` +Query OK, 0 rows affected (0.03 sec) +``` + +清空分区: + +{{< copyable "sql" >}} + +```sql +ALTER TABLE members TRUNCATE PARTITION p1; +``` + +``` +Query OK, 0 rows affected (0.03 sec) +``` + +> **注意:** +> +> `ALTER TABLE ... REORGANIZE PARTITION` 在 TiDB 中暂不支持。 + +添加分区: + +{{< copyable "sql" >}} + +```sql +ALTER TABLE members ADD PARTITION (PARTITION p3 VALUES LESS THAN (2010)); +``` + +Range 分区中,`ADD PARTITION` 只能在分区列表的最后面添加,如果是添加到已存在的分区范围则会报错: + +{{< copyable "sql" >}} + +```sql +ALTER TABLE members + ADD PARTITION ( + PARTITION n VALUES LESS THAN (1970)); +``` + +``` +ERROR 1463 (HY000): VALUES LESS THAN value must be strictly » + increasing for each partition +``` + +### Hash 分区管理 + +跟 Range 分区不同,Hash 分区不能够 `DROP PARTITION`。 + +目前 TiDB 的实现暂时不支持 `ALTER TABLE ... COALESCE PARTITION`。对于暂不支持的分区管理语句,TiDB 会返回错误。 + +{{< copyable "sql" >}} + +```sql +alter table members optimize partition p0; +``` + +```sql +ERROR 8200 (HY000): Unsupported optimize partition +``` + +## 分区裁剪 + +有一个优化叫做“分区裁剪”,它基于一个非常简单的概念:不需要扫描那些匹配不上的分区。 + +假设创建一个分区表 `t1`: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1 ( + fname VARCHAR(50) NOT NULL, + lname VARCHAR(50) NOT NULL, + region_code TINYINT UNSIGNED NOT NULL, + dob DATE NOT NULL +) + +PARTITION BY RANGE( region_code ) ( + PARTITION p0 VALUES LESS THAN (64), + PARTITION p1 VALUES LESS THAN (128), + PARTITION p2 VALUES LESS THAN (192), + PARTITION p3 VALUES LESS THAN MAXVALUE +); +``` + +如果你想获得这个 select 语句的结果: + +{{< copyable "sql" >}} + +```sql +SELECT fname, lname, region_code, dob + FROM t1 + WHERE region_code > 125 AND region_code < 130; +``` + +很显然,结果必然是在分区 `p1` 或者 `p2` 里面,也就是说,我们只需要在 `p1` 和 `p2` 里面去搜索匹配的行。去掉不必要的分区就是所谓的裁剪。优化器如果能裁剪掉一部分的分区,则执行会快于处理整个不做分区的表的相同查询。 + +优化器可以通过 where 条件裁剪的两个场景: + +* partition_column = constant +* partition_column IN (constant1, constant2, ..., constantN) + +### 分区裁剪生效的场景 + +1. 分区裁剪需要使用分区表上面的查询条件,所以根据优化器的优化规则,如果查询条件不能下推到分区表,则相应的查询语句无法执行分区裁剪。 + + 例如: + + {{< copyable "sql" >}} + + ```sql + create table t1 (x int) partition by range (x) ( + partition p0 values less than (5), + partition p1 values less than (10)); + create table t2 (x int); + ``` + + {{< copyable "sql" >}} + + ```sql + explain select * from t1 left join t2 on t1.x = t2.x where t2.x > 5; + ``` + + 在这个查询中,外连接可以简化成内连接,然后由 `t1.x = t2.x` 和 `t2.x > 5` 可以推出条件 `t1.x > 5`,于是可以分区裁剪并且只使用 `p1` 分区。 + + {{< copyable "sql" >}} + + ```sql + explain select * from t1 left join t2 on t1.x = t2.x and t2.x > 5; + ``` + + 这个查询中的 `t2.x > 5` 条件不能下推到 `t1` 分区表上面,因此 `t1` 无法分区裁剪。 + +2. 由于分区裁剪的规则优化是在查询计划的生成阶段,对于执行阶段才能获取到过滤条件的场景,无法利用分区裁剪的优化。 + + 例如: + + {{< copyable "sql" >}} + + ```sql + create table t1 (x int) partition by range (x) ( + partition p0 values less than (5), + partition p1 values less than (10)); + ``` + + {{< copyable "sql" >}} + + ```sql + explain select * from t2 where x < (select * from t1 where t2.x < t1.x and t2.x < 2); + ``` + + 这个查询每从 `t2` 读取一行,都会去分区表 `t1` 上进行查询,理论上这时会满足 `t1.x > val` 的过滤条件,但实际上由于分区裁剪只作用于查询计划生成阶段,而不是执行阶段,因而不会做裁剪。 + +3. 由于当前实现中的一处限制,对于查询条件无法下推到 TiKV 的表达式,不支持分区裁剪。 + + 对于一个函数表达式 `fn(col)`,如果 TiKV 支持这个函数 `fn`,则在查询优化做谓词下推的时候,`fn(col)` 会被推到叶子节点(也就是分区),因而能够执行分区裁剪。 + + 如果 TiKV 不支持 `fn`,则优化阶段不会把 `fn(col)` 推到叶子节点,而是在叶子上面连接一个 Selection 节点,分区裁剪的实现没有处理这种父节点的 Selection 中的条件,因此对不能下推到 TiKV 的表达式不支持分区裁剪。 + +4. 对于 Hash 分区类型,只有等值比较的查询条件能够支持分区裁剪。 + +5. 对于 Range 分区类型,分区表达式必须是 `col` 或者 `fn(col)` 的简单形式,查询条件是 > < = >= <= 时才能支持分区裁剪。如果分区表达式是 `fn(col)` 形式,还要求 `fn` 必须是单调函数,才有可能分区裁剪。 + + 这里单调函数是指某个函数 `fn` 满足条件:对于任意 `x` `y`,如果 `x > y`,则 `fn(x) > fn(y)`。 + + 这种是严格递增的单调函数,非严格递增的单调函数也可以符合分区裁剪要求,只要函数 `fn` 满足:对于任意 `x` `y`,如果 `x > y`,则 `fn(x) >= fn(y)`。 + + 理论上所有满足单调条件(严格或者非严格)的函数都是可以支持分区裁剪。实际上,目前 TiDB 已经支持的单调函数只有: + + ``` + unix_timestamp + to_days + ``` + + 例如,分区表达式是简单列的情况: + + {{< copyable "sql" >}} + + ```sql + create table t (id int) partition by range (id) ( + partition p0 values less than (5), + partition p1 values less than (10)); + select * from t where t > 6; + ``` + + 分区表达式是 `fn(col)` 的形式,`fn` 是我们支持的单调函数 `to_days`: + + {{< copyable "sql" >}} + + ```sql + create table t (dt datetime) partition by range (to_days(id)) ( + partition p0 values less than (to_days('2020-04-01')), + partition p1 values less than (to_days('2020-05-01'))); + select * from t where t > '2020-04-18'; + ``` + + 有一处例外是 `floor(unix_timestamp(ts))` 作为分区表达式,TiDB 针对这个场景做了特殊处理,可以支持分区裁剪。 + + {{< copyable "sql" >}} + + ```sql + create table t (ts timestamp(3) not null default current_timestamp(3)) + partition by range (floor(unix_timestamp(ts))) ( + partition p0 values less than (unix_timestamp('2020-04-01 00:00:00')), + partition p1 values less than (unix_timestamp('2020-05-01 00:00:00'))); + select * from t where t > '2020-04-18 02:00:42.123'; + ``` + +## 分区选择 + +SELECT 语句中支持分区选择。实现通过使用一个 `PARTITION` 选项实现。 + +{{< copyable "sql" >}} + +```sql +CREATE TABLE employees ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + fname VARCHAR(25) NOT NULL, + lname VARCHAR(25) NOT NULL, + store_id INT NOT NULL, + department_id INT NOT NULL +) + +PARTITION BY RANGE(id) ( + PARTITION p0 VALUES LESS THAN (5), + PARTITION p1 VALUES LESS THAN (10), + PARTITION p2 VALUES LESS THAN (15), + PARTITION p3 VALUES LESS THAN MAXVALUE +); + +INSERT INTO employees VALUES + ('', 'Bob', 'Taylor', 3, 2), ('', 'Frank', 'Williams', 1, 2), + ('', 'Ellen', 'Johnson', 3, 4), ('', 'Jim', 'Smith', 2, 4), + ('', 'Mary', 'Jones', 1, 1), ('', 'Linda', 'Black', 2, 3), + ('', 'Ed', 'Jones', 2, 1), ('', 'June', 'Wilson', 3, 1), + ('', 'Andy', 'Smith', 1, 3), ('', 'Lou', 'Waters', 2, 4), + ('', 'Jill', 'Stone', 1, 4), ('', 'Roger', 'White', 3, 2), + ('', 'Howard', 'Andrews', 1, 2), ('', 'Fred', 'Goldberg', 3, 3), + ('', 'Barbara', 'Brown', 2, 3), ('', 'Alice', 'Rogers', 2, 2), + ('', 'Mark', 'Morgan', 3, 3), ('', 'Karen', 'Cole', 3, 2); +``` + +你可以查看存储在分区 `p1` 中的行: + +{{< copyable "sql" >}} + +```sql +SELECT * FROM employees PARTITION (p1); +``` + +``` ++----|-------|--------|----------|---------------+ +| id | fname | lname | store_id | department_id | ++----|-------|--------|----------|---------------+ +| 5 | Mary | Jones | 1 | 1 | +| 6 | Linda | Black | 2 | 3 | +| 7 | Ed | Jones | 2 | 1 | +| 8 | June | Wilson | 3 | 1 | +| 9 | Andy | Smith | 1 | 3 | ++----|-------|--------|----------|---------------+ +5 rows in set (0.00 sec) +``` + +如果希望获得多个分区中的行,可以提供分区名的列表,用逗号隔开。例如,`SELECT * FROM employees PARTITION (p1, p2)` 返回分区 `p1` 和 `p2` 的所有行。 + +使用分区选择时,仍然可以使用 where 条件,以及 ORDER BY 和 LIMIT 等选项。使用 HAVING 和 GROUP BY 等聚合选项也是支持的。 + +{{< copyable "sql" >}} + +```sql +SELECT * FROM employees PARTITION (p0, p2) + WHERE lname LIKE 'S%'; +``` + +``` ++----|-------|-------|----------|---------------+ +| id | fname | lname | store_id | department_id | ++----|-------|-------|----------|---------------+ +| 4 | Jim | Smith | 2 | 4 | +| 11 | Jill | Stone | 1 | 4 | ++----|-------|-------|----------|---------------+ +2 rows in set (0.00 sec) +``` + +{{< copyable "sql" >}} + +```sql +SELECT id, CONCAT(fname, ' ', lname) AS name + FROM employees PARTITION (p0) ORDER BY lname; +``` + +``` ++----|----------------+ +| id | name | ++----|----------------+ +| 3 | Ellen Johnson | +| 4 | Jim Smith | +| 1 | Bob Taylor | +| 2 | Frank Williams | ++----|----------------+ +4 rows in set (0.06 sec) +``` + +{{< copyable "sql" >}} + +```sql +SELECT store_id, COUNT(department_id) AS c + FROM employees PARTITION (p1,p2,p3) + GROUP BY store_id HAVING c > 4; +``` + +``` ++---|----------+ +| c | store_id | ++---|----------+ +| 5 | 2 | +| 5 | 3 | ++---|----------+ +2 rows in set (0.00 sec) +``` + +分支选择支持所有类型的分区表,无论是 Range 分区或是 Hash 分区等。对于 Hash 分区,如果没有指定分区名,会自动使用 `p0`、`p1`、`p2`、……、或 `pN-1` 作为分区名。 + +在 `INSERT ... SELECT` 的 `SELECT` 中也是可以使用分区选择的。 + +## 分区的约束和限制 + +本节介绍当前 TiDB 分区表的一些约束和限制。 + +### 分区键,主键和唯一键 + +本节讨论分区键,主键和唯一键之间的关系。一句话总结它们之间的关系要满足的规则:**分区表的每个唯一键,必须包含分区表达式中用到的所有列**。 + +> every unique key on the table must use every column in the table's partitioning expression. + +这里所指的唯一也包含了主键,因为根据主键的定义,主键必须是唯一的。例如,下面这些建表语句就是无效的: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1 ( + col1 INT NOT NULL, + col2 DATE NOT NULL, + col3 INT NOT NULL, + col4 INT NOT NULL, + UNIQUE KEY (col1, col2) +) + +PARTITION BY HASH(col3) +PARTITIONS 4; + +CREATE TABLE t2 ( + col1 INT NOT NULL, + col2 DATE NOT NULL, + col3 INT NOT NULL, + col4 INT NOT NULL, + UNIQUE KEY (col1), + UNIQUE KEY (col3) +) + +PARTITION BY HASH(col1 + col3) +PARTITIONS 4; +``` + +它们都是有唯一键但没有包含所有分区键的。 + +下面是一些合法的语句的例子: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t1 ( + col1 INT NOT NULL, + col2 DATE NOT NULL, + col3 INT NOT NULL, + col4 INT NOT NULL, + UNIQUE KEY (col1, col2, col3) +) + +PARTITION BY HASH(col3) +PARTITIONS 4; + +CREATE TABLE t2 ( + col1 INT NOT NULL, + col2 DATE NOT NULL, + col3 INT NOT NULL, + col4 INT NOT NULL, + UNIQUE KEY (col1, col3) +) + +PARTITION BY HASH(col1 + col3) +PARTITIONS 4; +``` + +下例中会产生一个报错: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t3 ( + col1 INT NOT NULL, + col2 DATE NOT NULL, + col3 INT NOT NULL, + col4 INT NOT NULL, + UNIQUE KEY (col1, col2), + UNIQUE KEY (col3) +) + +PARTITION BY HASH(col1 + col3) + PARTITIONS 4; +``` + +``` +ERROR 1491 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function +``` + +原因是 `col1` 和 `col3` 出现在分区键中,但是几个唯一键定义并没有完全包含它们。 + +下面这个表就没法做分区了,因为无论如何都不可能找到满足条件的分区键: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t4 ( + col1 INT NOT NULL, + col2 INT NOT NULL, + col3 INT NOT NULL, + col4 INT NOT NULL, + UNIQUE KEY (col1, col3), + UNIQUE KEY (col2, col4) +); +``` + +根据定义,主键也是唯一键,下面两个建表语句是无效的: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t5 ( + col1 INT NOT NULL, + col2 DATE NOT NULL, + col3 INT NOT NULL, + col4 INT NOT NULL, + PRIMARY KEY(col1, col2) +) + +PARTITION BY HASH(col3) +PARTITIONS 4; + +CREATE TABLE t6 ( + col1 INT NOT NULL, + col2 DATE NOT NULL, + col3 INT NOT NULL, + col4 INT NOT NULL, + PRIMARY KEY(col1, col3), + UNIQUE KEY(col2) +) + +PARTITION BY HASH( YEAR(col2) ) +PARTITIONS 4; +``` + +两个例子中,主键都没有包含分区表达式中的全部的列。 + +如果既没有主键,也没有唯一键,则不存在这个限制。 + +DDL 变更时,添加唯一索引也需要考虑到这个限制。比如创建了这样一个表: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t_no_pk (c1 INT, c2 INT) + PARTITION BY RANGE(c1) ( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN (20), + PARTITION p2 VALUES LESS THAN (30), + PARTITION p3 VALUES LESS THAN (40) + ); +``` + +``` +Query OK, 0 rows affected (0.12 sec) +``` + +通过 `ALTER TABLE` 添加非唯一索引是可以的。但是添加唯一索引时,唯一索引里面必须包含 `c1` 列。 + +使用分区表时,前缀索引是不能指定为唯一属性的: + +{{< copyable "sql" >}} + +```sql +CREATE TABLE t (a varchar(20), b blob, + UNIQUE INDEX (a(5))) + PARTITION by range columns (a) ( + PARTITION p0 values less than ('aaaaa'), + PARTITION p1 values less than ('bbbbb'), + PARTITION p2 values less than ('ccccc')); +``` + +```sql +ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function +``` + +### 关于函数的分区限制 + +只有以下函数可以用于分区表达式: + +``` +ABS() +CEILING() +DATEDIFF() +DAY() +DAYOFMONTH() +DAYOFWEEK() +DAYOFYEAR() +EXTRACT() (see EXTRACT() function with WEEK specifier) +FLOOR() +HOUR() +MICROSECOND() +MINUTE() +MOD() +MONTH() +QUARTER() +SECOND() +TIME_TO_SEC() +TO_DAYS() +TO_SECONDS() +UNIX_TIMESTAMP() (with TIMESTAMP columns) +WEEKDAY() +YEAR() +YEARWEEK() +``` + +### 兼容性 + +目前 TiDB 里面只实现了 Range 分区和 Hash 分区,其它的 MySQL 分区类型比如 List 分区和 Key 分区尚不支持。 + +对于 Range Columns 类型的分区表,目前只支持单列的场景。 + +分区管理方面,只要底层实现可能会涉及数据挪到的操作,目前都暂不支持。包括且不限于:调整 Hash 分区表的分区数量,修改 Range 分区表的范围,合并分区,交换分区等。 + +对于暂不支持的分区类型,在 TiDB 中建表时会忽略分区信息,以普通表的形式创建,并且会报 Warning。 + +INFORMATION_SCHEMA.PARTITION 表暂不支持。 + +Load Data 暂时不支持分区选择。 + +{{< copyable "sql" >}} + +```sql +create table t (id int, val int) partition by hash(id) partitions 4; +``` + +普通的 Load Data 操作在 TiDB 中是支持的,如下: + +{{< copyable "sql" >}} + +```sql +load local data infile "xxx" into t ... +``` + +但 Load Data 不支持分区选择操作: + +{{< copyable "sql" >}} + +```sql +load local data infile "xxx" into t partition (p1)... +``` + +对于分区表,`select * from t` 的返回结果是分区之间无序的。这跟 MySQL 不同,MySQL 的返回结果是分区之间有序,分区内部无序。 + +{{< copyable "sql" >}} + +```sql +create table t (id int, val int) partition by range (id) ( + partition p0 values less than (3), + partition p1 values less than (7), + partition p2 values less than (11)); +``` + +``` +Query OK, 0 rows affected (0.10 sec) +``` + +{{< copyable "sql" >}} + +```sql +insert into t values (1, 2), (3, 4),(5, 6),(7,8),(9,10); +``` + +``` +Query OK, 5 rows affected (0.01 sec) +Records: 5 Duplicates: 0 Warnings: 0 +``` + +TiDB 每次返回结果会不同,例如: + +{{< copyable "sql" >}} + +``` +select * from t; +``` + +``` ++------|------+ +| id | val | ++------|------+ +| 7 | 8 | +| 9 | 10 | +| 1 | 2 | +| 3 | 4 | +| 5 | 6 | ++------|------+ +5 rows in set (0.00 sec) +``` + +MySQL 的返回结果: + +{{< copyable "sql" >}} + +``` +select * from t; +``` + +``` ++------|------+ +| id | val | ++------|------+ +| 1 | 2 | +| 3 | 4 | +| 5 | 6 | +| 7 | 8 | +| 9 | 10 | ++------|------+ +5 rows in set (0.00 sec) +``` + +环境变量 `tidb_enable_table_partition` 可以控制是否启用分区表功能。如果该变量设置为 `off`,则建表时会忽略分区信息,以普通表的方式建表。 + +该变量仅作用于建表,已经建表之后再修改该变量无效。详见 [TiDB 专用系统变量和语法](/tidb-specific-system-variables.md#tidb_enable_table_partition)。 diff --git a/pd-configuration-file.md b/pd-configuration-file.md new file mode 100644 index 000000000000..5ef5c2c28b38 --- /dev/null +++ b/pd-configuration-file.md @@ -0,0 +1,284 @@ +--- +title: PD 配置文件描述 +category: reference +aliases: ['/docs-cn/stable/reference/configuration/pd-server/configuration-file/'] +--- + +# PD 配置文件描述 + + + +PD 配置文件比命令行参数支持更多的选项。你可以在 [conf/config.toml](https://github.com/pingcap/pd/blob/master/conf/config.toml) 找到默认的配置文件。 + +本文档只阐述未包含在命令行参数中的参数,命令行参数参见 [PD 配置参数](/command-line-flags-for-pd-configuration.md)。 + +### `lease` + ++ PD Leader Key 租约超时时间,超时系统重新选举 Leader。 ++ 默认:3 ++ 单位:秒 + +### `tso-save-interval` + ++ TSO 分配的时间窗口,实时持久存储。 ++ 默认:3s + +### `initial-cluster-state` + ++ 集群初始状态 ++ 默认:new + +### `enable-prevote` + ++ 开启 raft prevote 的开关。 ++ 默认:true + +### `quota-backend-bytes` + ++ 元信息数据库存储空间的大小,默认 2GB。 ++ 默认:2147483648 + +### `auto-compaction-mod` + ++ 元信息数据库自动压缩的模式,可选项为 periodic(按周期),revision(按版本数)。 ++ 默认:periodic + +### `auto-compaction-retention` + ++ compaction-mode 为 periodic 时为元信息数据库自动压缩的间隔时间;compaction-mode 设置为 revision 时为自动压缩的版本数。 ++ 默认:1h + +### `force-new-cluster` + ++ 强制让该 PD 以一个新集群启动,且修改 raft 成员数为 1。 ++ 默认:false + +### `tick-interval` + ++ etcd raft 的 tick 周期。 ++ 默认:100ms + +### `election-interval` + ++ etcd leader 选举的超时时间。 ++ 默认:3s + +### `use-region-storage` + ++ 开启独立的 region 存储。 ++ 默认:false + +## security + +安全相关配置项。 + +### `cacert-path` + ++ CA 文件路径 ++ 默认:"" + +### `cert-path` + ++ 包含 X509 证书的 PEM 文件路径 ++ 默认:"" + +### `key-path` + ++ 包含 X509 key 的 PEM 文件路径 ++ 默认:"" + +## log + +日志相关的配置项。 + +### `format` + ++ 日志格式,可指定为"text","json", "console"。 ++ 默认:text + +### `disable-timestamp` + ++ 是否禁用日志中自动生成的时间戳。 ++ 默认:false + +## log.file + +日志文件相关的配置项。 + +### `max-size` + ++ 单个日志文件最大大小,超过该值系统自动切分成多个文件。 ++ 默认:300 ++ 单位:MiB ++ 最小值为 1 + +### `max-days` + ++ 日志保留的最长天数。 ++ 默认: 28 ++ 最小值为 1 + +### `max-backups` + ++ 日志文件保留的最大个数。 ++ 默认: 7 ++ 最小值为 1 + +## metric + +监控相关的配置项。 + +### `interval` + ++ 向 promethus 推送监控指标数据的间隔时间。 ++ 默认: 15s + +## schedule + +调度相关的配置项。 + +### `max-merge-region-size` + ++ 控制 Region Merge 的 size 上限,当 Region Size 大于指定值时 PD 不会将其与相邻的 Region 合并。 ++ 默认: 20 + +### `max-merge-region-keys` + ++ 控制 Region Merge 的 key 上限,当 Region key 大于指定值时 PD 不会将其与相邻的 Region 合并。 ++ 默认: 200000 + +### `patrol-region-interval` + ++ 控制 replicaChecker 检查 Region 健康状态的运行频率,越短则运行越快,通常状况不需要调整 ++ 默认: 100ms + +### `split-merge-interval` + ++ 控制对同一个 Region 做 split 和 merge 操作的间隔,即对于新 split 的 Region 一段时间内不会被 merge。 ++ 默认: 1h + +### `max-snapshot-count` + ++ 控制单个 store 最多同时接收或发送的 snapshot 数量,调度受制于这个配置来防止抢占正常业务的资源。 ++ 默认: 3 + +### `max-pending-peer-count` + ++ 控制单个 store 的 pending peer 上限,调度受制于这个配置来防止在部分节点产生大量日志落后的 Region。 ++ 默认:16 + +### `max-store-down-time` + ++ PD 认为失联 store 无法恢复的时间,当超过指定的时间没有收到 store 的心跳后,PD 会在其他节点补充副本。 ++ 默认:30m + +### `leader-schedule-limit` + ++ 同时进行 leader 调度的任务个数。 ++ 默认:4 + +### `region-schedule-limit` + ++ 同时进行 Region 调度的任务个数 ++ 默认:2048 + +### `replica-schedule-limit` + ++ 同时进行 replica 调度的任务个数。 ++ 默认:64 + +### `merge-schedule-limit` + ++ 同时进行的 Region Merge 调度的任务,设置为 0 则关闭 Region Merge。 ++ 默认:8 + +### `high-space-ratio` + ++ 设置 store 空间充裕的阈值。 ++ 默认:0.7 ++ 最小值:大于 0 ++ 最大值:小于 1 + +### `low-space-ratio` + ++ 设置 store 空间不足的阈值。 ++ 默认:0.8 ++ 最小值:大于 0 ++ 最大值:小于 1 + +### `tolerant-size-ratio` + ++ 控制 balance 缓冲区大小。 ++ 默认:0 (为 0 为自动调整缓冲区大小) ++ 最小值:0 + +### `disable-remove-down-replica` + ++ 关闭自动删除 DownReplica 的特性的开关,当设置为 true 时,PD 不会自动清理宕机状态的副本。 ++ 默认:false + +### `disable-replace-offline-replica` + ++ 关闭迁移 OfflineReplica 的特性的开关,当设置为 true 时,PD 不会迁移下线状态的副本。 ++ 默认:false + +### `disable-make-up-replica` + ++ 关闭补充副本的特性的开关,当设置为 true 时,PD 不会为副本数不足的 Region 补充副本。 ++ 默认:false + +### `disable-remove-extra-replica` + ++ 关闭删除多余副本的特性开关,当设置为 true 时,PD 不会为副本数过多的 Region 删除多余副本。 ++ 默认:false + +### `disable-location-replacement` + ++ 关闭隔离级别检查的开关,当设置为 true 时,PD 不会通过调度来提升 Region 副本的隔离级别。 ++ 默认:false + +### `store-balance-rate` + ++ 控制 TiKV 每分钟最多允许做 add peer 相关操作的次数。 ++ 默认:15 + +## replication + +副本相关的配置项。 + +### `max-replicas` + ++ 副本数量。 ++ 默认:3 + +### `location-labels` + ++ TiKV 集群的拓扑信息。 ++ 默认:[] ++ [配置集群拓扑](/schedule-replicas-by-topology-labels.md) + +### `strictly-match-label` + ++ 打开强制 TiKV Label 和 PD 的 localtion-labels 是否匹配的检查 ++ 默认:false + +### `enable-placement-rules` + ++ 打开 `placement-rules` ++ 默认:false ++ 参考[Placement Rules 使用文档](/configure-placement-rules.md) ++ 4.0 实验性特性 + +## label-property + +标签相关的配置项。 + +### `key` + ++ 拒绝 leader 的 store 带有的 label key。 ++ 默认:"" + +### `value` + ++ 拒绝 leader 的 store 带有的 label value。 ++ 默认:"" diff --git a/pd-control.md b/pd-control.md new file mode 100644 index 000000000000..fecea4e39cfe --- /dev/null +++ b/pd-control.md @@ -0,0 +1,1203 @@ +--- +title: PD Control 使用说明 +category: reference +aliases: ['/docs-cn/stable/reference/tools/pd-control/'] +--- + +# PD Control 使用说明 + +PD Control 是 PD 的命令行工具,用于获取集群状态信息和调整集群。 + +## 使用 TiUP + +可直接通过 `tiup ctl pd -- -u http://: [-i]` 使用。 + +## 下载安装包 + +如需下载最新版本的 `pd-ctl`,直接下载 TiDB 安装包即可,因为 `pd-ctl` 包含在 TiDB 安装包中。 + +| 安装包 | 操作系统 | 架构 | SHA256 校验和 | +|:---|:---|:---|:---| +| `https://download.pingcap.org/tidb-{version}-linux-amd64.tar.gz` (pd-ctl) | Linux | amd64 | `https://download.pingcap.org/tidb-{version}-linux-amd64.sha256` | + +> **注意:** +> +> 下载链接中的 `{version}` 为 TiDB 的版本号。例如 `v4.0.0-rc.2` 版本的下载链接为 `https://download.pingcap.org/tidb-v4.0.0-rc.2-linux-amd64.tar.gz`。也可以使用 `latest` 替代 `{version}` 来下载最新的未发布版本。 + +## 源码编译 + +1. [Go](https://golang.org/) Version 1.13 以上 +2. 在 PD 项目根目录使用 `make` 或者 `make pd-ctl` 命令进行编译,生成 bin/pd-ctl + +## 简单例子 + +单命令模式: + +{{< copyable "shell-regular" >}} + +```bash +./pd-ctl store -u http://127.0.0.1:2379 +``` + +交互模式: + +{{< copyable "shell-regular" >}} + +```bash +./pd-ctl -i -u http://127.0.0.1:2379 +``` + +使用环境变量: + +{{< copyable "shell-regular" >}} + +```bash +export PD_ADDR=http://127.0.0.1:2379 && +./pd-ctl +``` + +使用 TLS 加密: + +{{< copyable "shell-regular" >}} + +```bash +./pd-ctl -u https://127.0.0.1:2379 --cacert="path/to/ca" --cert="path/to/cert" --key="path/to/key" +``` + +## 命令行参数(flags) + +### --cacert + +- 指定 PEM 格式的受信任 CA 证书的文件路径 +- 默认值:"" + +### --cert + +- 指定 PEM 格式的 SSL 证书的文件路径 +- 默认值:"" + +### --detach,-d + ++ 使用单命令行模式(不进入 readline) ++ 默认值: true + +### --help,-h + ++ 输出帮助信息 ++ 默认值:false + +### --interact,-i + ++ 使用交互模式(进入 readline) ++ 默认值:false + +### --key + +- 指定 PEM 格式的 SSL 证书密钥文件路径,即 `--cert` 所指定的证书的私钥 +- 默认值: "" + +### --pd,-u + ++ 指定 PD 的地址 ++ 默认地址:`http://127.0.0.1:2379` ++ 环境变量:`PD_ADDR` + +### --version,-V + +- 打印版本信息并退出 +- 默认值: false + +## 命令 (command) + +### cluster + +用于显示集群基本信息。 + +示例: + +{{< copyable "" >}} + +```bash +>> cluster +``` + +``` +{ + "id": 6493707687106161130, + "max_peer_count": 3 +} +``` + +### `config [show | set